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