perl 3.0 patch #14 patch #13, continued
[p5sagit/p5-mst-13.2.git] / form.c
CommitLineData
ac58e20f 1/* $Header: form.c,v 3.0.1.1 90/02/28 17:39:34 lwall Locked $
a687059c 2 *
3 * Copyright (c) 1989, Larry Wall
4 *
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
8d063cd8 7 *
8 * $Log: form.c,v $
ac58e20f 9 * Revision 3.0.1.1 90/02/28 17:39:34 lwall
10 * patch9: ... in format threw off subsequent field
11 *
a687059c 12 * Revision 3.0 89/10/18 15:17:26 lwall
13 * 3.0 baseline
8d063cd8 14 *
15 */
16
8d063cd8 17#include "EXTERN.h"
8d063cd8 18#include "perl.h"
19
20/* Forms stuff */
21
a687059c 22void
23form_parseargs(fcmd)
24register FCMD *fcmd;
25{
26 register int i;
27 register ARG *arg;
28 register int items;
29 STR *str;
30 ARG *parselist();
31 line_t oldline = line;
32 int oldsave = savestack->ary_fill;
33
34 str = fcmd->f_unparsed;
35 line = fcmd->f_line;
36 fcmd->f_unparsed = Nullstr;
37 (void)savehptr(&curstash);
38 curstash = str->str_u.str_hash;
39 arg = parselist(str);
40 restorelist(oldsave);
41
42 items = arg->arg_len - 1; /* ignore $$ on end */
43 for (i = 1; i <= items; i++) {
44 if (!fcmd || fcmd->f_type == F_NULL)
45 fatal("Too many field values");
46 dehoist(arg,i);
47 fcmd->f_expr = make_op(O_ITEM,1,
48 arg[i].arg_ptr.arg_arg,Nullarg,Nullarg);
49 if (fcmd->f_flags & FC_CHOP) {
50 if ((fcmd->f_expr[1].arg_type & A_MASK) == A_STAB)
51 fcmd->f_expr[1].arg_type = A_LVAL;
52 else if ((fcmd->f_expr[1].arg_type & A_MASK) == A_EXPR)
53 fcmd->f_expr[1].arg_type = A_LEXPR;
54 else
55 fatal("^ field requires scalar lvalue");
56 }
57 fcmd = fcmd->f_next;
58 }
59 if (fcmd && fcmd->f_type)
60 fatal("Not enough field values");
61 line = oldline;
62 Safefree(arg);
63 str_free(str);
64}
65
66int newsize;
67
8d063cd8 68#define CHKLEN(allow) \
a687059c 69newsize = (d - orec->o_str) + (allow); \
70if (newsize >= curlen) { \
8d063cd8 71 curlen = d - orec->o_str; \
72 GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \
73 d = orec->o_str + curlen; /* in case it moves */ \
74 curlen = orec->o_len - 2; \
75}
76
a687059c 77format(orec,fcmd,sp)
8d063cd8 78register struct outrec *orec;
79register FCMD *fcmd;
a687059c 80int sp;
8d063cd8 81{
82 register char *d = orec->o_str;
83 register char *s;
84 register int curlen = orec->o_len - 2;
85 register int size;
a687059c 86 FCMD *nextfcmd;
87 FCMD *linebeg = fcmd;
8d063cd8 88 char tmpchar;
89 char *t;
90 CMD mycmd;
91 STR *str;
92 char *chophere;
93
94 mycmd.c_type = C_NULL;
95 orec->o_lines = 0;
a687059c 96 for (; fcmd; fcmd = nextfcmd) {
97 nextfcmd = fcmd->f_next;
8d063cd8 98 CHKLEN(fcmd->f_presize);
a687059c 99 if (s = fcmd->f_pre) {
100 while (*s) {
101 if (*s == '\n') {
102 while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
103 d--;
104 if (fcmd->f_flags & FC_NOBLANK) {
105 if (d == orec->o_str || d[-1] == '\n') {
106 orec->o_lines--; /* don't print blank line */
107 linebeg = fcmd->f_next;
108 break;
109 }
110 else if (fcmd->f_flags & FC_REPEAT)
111 nextfcmd = linebeg;
112 }
113 else
114 linebeg = fcmd->f_next;
8d063cd8 115 }
a687059c 116 *d++ = *s++;
8d063cd8 117 }
8d063cd8 118 }
a687059c 119 if (fcmd->f_unparsed)
120 form_parseargs(fcmd);
8d063cd8 121 switch (fcmd->f_type) {
122 case F_NULL:
123 orec->o_lines++;
124 break;
125 case F_LEFT:
a687059c 126 (void)eval(fcmd->f_expr,G_SCALAR,sp);
127 str = stack->ary_array[sp+1];
8d063cd8 128 s = str_get(str);
129 size = fcmd->f_size;
130 CHKLEN(size);
131 chophere = Nullch;
132 while (size && *s && *s != '\n') {
a687059c 133 if (*s == '\t')
134 *s = ' ';
8d063cd8 135 size--;
a687059c 136 if (*s && index(chopset,(*d++ = *s++)))
8d063cd8 137 chophere = s;
a687059c 138 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
139 *s = ' ';
8d063cd8 140 }
141 if (size)
142 chophere = s;
a687059c 143 else if (chophere && chophere < s && *s && index(chopset,*s))
144 chophere = s;
8d063cd8 145 if (fcmd->f_flags & FC_CHOP) {
146 if (!chophere)
147 chophere = s;
148 size += (s - chophere);
149 d -= (s - chophere);
150 if (fcmd->f_flags & FC_MORE &&
151 *chophere && strNE(chophere,"\n")) {
152 while (size < 3) {
153 d--;
154 size++;
155 }
156 while (d[-1] == ' ' && size < fcmd->f_size) {
157 d--;
158 size++;
159 }
160 *d++ = '.';
161 *d++ = '.';
162 *d++ = '.';
ac58e20f 163 size -= 3;
8d063cd8 164 }
a687059c 165 while (*chophere && index(chopset,*chophere))
166 chophere++;
8d063cd8 167 str_chop(str,chophere);
168 }
169 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
170 size = 0; /* no spaces before newline */
171 while (size) {
172 size--;
173 *d++ = ' ';
174 }
175 break;
176 case F_RIGHT:
a687059c 177 (void)eval(fcmd->f_expr,G_SCALAR,sp);
178 str = stack->ary_array[sp+1];
179 t = s = str_get(str);
8d063cd8 180 size = fcmd->f_size;
181 CHKLEN(size);
182 chophere = Nullch;
183 while (size && *s && *s != '\n') {
a687059c 184 if (*s == '\t')
185 *s = ' ';
8d063cd8 186 size--;
a687059c 187 if (*s && index(chopset,*s++))
188 chophere = s;
189 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
190 *s = ' ';
8d063cd8 191 }
192 if (size)
193 chophere = s;
a687059c 194 else if (chophere && chophere < s && *s && index(chopset,*s))
195 chophere = s;
8d063cd8 196 if (fcmd->f_flags & FC_CHOP) {
197 if (!chophere)
198 chophere = s;
199 size += (s - chophere);
8d063cd8 200 s = chophere;
a687059c 201 while (*chophere && index(chopset,*chophere))
202 chophere++;
8d063cd8 203 }
204 tmpchar = *s;
205 *s = '\0';
206 while (size) {
207 size--;
208 *d++ = ' ';
209 }
210 size = s - t;
a687059c 211 (void)bcopy(t,d,size);
8d063cd8 212 d += size;
213 *s = tmpchar;
a687059c 214 if (fcmd->f_flags & FC_CHOP)
215 str_chop(str,chophere);
8d063cd8 216 break;
217 case F_CENTER: {
218 int halfsize;
219
a687059c 220 (void)eval(fcmd->f_expr,G_SCALAR,sp);
221 str = stack->ary_array[sp+1];
222 t = s = str_get(str);
8d063cd8 223 size = fcmd->f_size;
224 CHKLEN(size);
225 chophere = Nullch;
226 while (size && *s && *s != '\n') {
a687059c 227 if (*s == '\t')
228 *s = ' ';
8d063cd8 229 size--;
a687059c 230 if (*s && index(chopset,*s++))
231 chophere = s;
232 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
233 *s = ' ';
8d063cd8 234 }
235 if (size)
236 chophere = s;
a687059c 237 else if (chophere && chophere < s && *s && index(chopset,*s))
238 chophere = s;
8d063cd8 239 if (fcmd->f_flags & FC_CHOP) {
240 if (!chophere)
241 chophere = s;
242 size += (s - chophere);
8d063cd8 243 s = chophere;
a687059c 244 while (*chophere && index(chopset,*chophere))
245 chophere++;
8d063cd8 246 }
247 tmpchar = *s;
248 *s = '\0';
249 halfsize = size / 2;
250 while (size > halfsize) {
251 size--;
252 *d++ = ' ';
253 }
254 size = s - t;
a687059c 255 (void)bcopy(t,d,size);
8d063cd8 256 d += size;
257 *s = tmpchar;
258 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
259 size = 0; /* no spaces before newline */
260 else
261 size = halfsize;
262 while (size) {
263 size--;
264 *d++ = ' ';
265 }
a687059c 266 if (fcmd->f_flags & FC_CHOP)
267 str_chop(str,chophere);
8d063cd8 268 break;
269 }
270 case F_LINES:
a687059c 271 (void)eval(fcmd->f_expr,G_SCALAR,sp);
272 str = stack->ary_array[sp+1];
8d063cd8 273 s = str_get(str);
274 size = str_len(str);
275 CHKLEN(size);
276 orec->o_lines += countlines(s);
a687059c 277 (void)bcopy(s,d,size);
8d063cd8 278 d += size;
a687059c 279 linebeg = fcmd->f_next;
8d063cd8 280 break;
281 }
282 }
283 *d++ = '\0';
284}
285
286countlines(s)
287register char *s;
288{
289 register int count = 0;
290
291 while (*s) {
292 if (*s++ == '\n')
293 count++;
294 }
295 return count;
296}
297
a687059c 298do_write(orec,stio,sp)
8d063cd8 299struct outrec *orec;
300register STIO *stio;
a687059c 301int sp;
8d063cd8 302{
a687059c 303 FILE *ofp = stio->ofp;
8d063cd8 304
305#ifdef DEBUGGING
306 if (debug & 256)
378cc40b 307 fprintf(stderr,"left=%ld, todo=%ld\n",
308 (long)stio->lines_left, (long)orec->o_lines);
8d063cd8 309#endif
310 if (stio->lines_left < orec->o_lines) {
311 if (!stio->top_stab) {
312 STAB *topstab;
313
314 if (!stio->top_name)
315 stio->top_name = savestr("top");
316 topstab = stabent(stio->top_name,FALSE);
a687059c 317 if (!topstab || !stab_form(topstab)) {
8d063cd8 318 stio->lines_left = 100000000;
319 goto forget_top;
320 }
321 stio->top_stab = topstab;
322 }
a687059c 323 if (stio->lines_left >= 0 && stio->page > 0)
324 (void)putc('\f',ofp);
8d063cd8 325 stio->lines_left = stio->page_len;
326 stio->page++;
a687059c 327 format(&toprec,stab_form(stio->top_stab),sp);
8d063cd8 328 fputs(toprec.o_str,ofp);
329 stio->lines_left -= toprec.o_lines;
330 }
331 forget_top:
332 fputs(orec->o_str,ofp);
333 stio->lines_left -= orec->o_lines;
334}