1 /* $RCSfile: form.c,v $$Revision: 4.0.1.3 $$Date: 92/06/08 13:21:42 $
3 * Copyright (c) 1991, Larry Wall
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.
9 * Revision 4.0.1.3 92/06/08 13:21:42 lwall
10 * patch20: removed implicit int declarations on funcions
11 * patch20: form feed for formats is now specifiable via $^L
12 * patch20: Perl now distinguishes overlapped copies from non-overlapped
14 * Revision 4.0.1.2 91/11/05 17:18:43 lwall
15 * patch11: formats didn't fill their fields as well as they could
16 * patch11: ^ fields chopped hyphens on line break
17 * patch11: # fields could write outside allocated memory
19 * Revision 4.0.1.1 91/06/07 11:07:59 lwall
20 * patch4: new copyright notice
21 * patch4: default top-of-form format is now FILEHANDLE_TOP
23 * Revision 4.0 91/03/20 01:19:23 lwall
33 static int countlines();
44 line_t oldline = curcmd->c_line;
45 int oldsave = savestack->ary_fill;
47 str = fcmd->f_unparsed;
48 curcmd->c_line = fcmd->f_line;
49 fcmd->f_unparsed = Nullstr;
50 (void)savehptr(&curstash);
51 curstash = str->str_u.str_hash;
55 items = arg->arg_len - 1; /* ignore $$ on end */
56 for (i = 1; i <= items; i++) {
57 if (!fcmd || fcmd->f_type == F_NULL)
58 fatal("Too many field values");
60 fcmd->f_expr = make_op(O_ITEM,1,
61 arg[i].arg_ptr.arg_arg,Nullarg,Nullarg);
62 if (fcmd->f_flags & FC_CHOP) {
63 if ((fcmd->f_expr[1].arg_type & A_MASK) == A_STAB)
64 fcmd->f_expr[1].arg_type = A_LVAL;
65 else if ((fcmd->f_expr[1].arg_type & A_MASK) == A_EXPR)
66 fcmd->f_expr[1].arg_type = A_LEXPR;
68 fatal("^ field requires scalar lvalue");
72 if (fcmd && fcmd->f_type)
73 fatal("Not enough field values");
74 curcmd->c_line = oldline;
81 #define CHKLEN(allow) \
82 newsize = (d - orec->o_str) + (allow); \
83 if (newsize >= curlen) { \
84 curlen = d - orec->o_str; \
85 GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \
86 d = orec->o_str + curlen; /* in case it moves */ \
87 curlen = orec->o_len - 2; \
92 register struct outrec *orec;
96 register char *d = orec->o_str;
98 register int curlen = orec->o_len - 2;
101 FCMD *linebeg = fcmd;
108 mycmd.c_type = C_NULL;
110 for (; fcmd; fcmd = nextfcmd) {
111 nextfcmd = fcmd->f_next;
112 CHKLEN(fcmd->f_presize);
114 if (s = fcmd->f_pre) {
117 while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
119 if (fcmd->f_flags & FC_NOBLANK) {
120 if (d == orec->o_str || d[-1] == '\n') {
121 orec->o_lines--; /* don't print blank line */
122 linebeg = fcmd->f_next;
125 else if (fcmd->f_flags & FC_REPEAT)
128 linebeg = fcmd->f_next;
131 linebeg = fcmd->f_next;
136 if (fcmd->f_unparsed)
137 form_parseargs(fcmd);
138 switch (fcmd->f_type) {
143 (void)eval(fcmd->f_expr,G_SCALAR,sp);
144 str = stack->ary_array[sp+1];
149 while (size && *s && *s != '\n') {
153 if (*s && index(chopset,(*d++ = *s++)))
155 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
160 else if (chophere && chophere < s && *s && index(chopset,*s))
162 if (fcmd->f_flags & FC_CHOP) {
165 size += (s - chophere);
167 if (fcmd->f_flags & FC_MORE &&
168 *chophere && strNE(chophere,"\n")) {
173 while (d[-1] == ' ' && size < fcmd->f_size) {
182 while (*chophere && index(chopset,*chophere)
183 && isSPACE(*chophere))
185 str_chop(str,chophere);
187 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
188 size = 0; /* no spaces before newline */
195 (void)eval(fcmd->f_expr,G_SCALAR,sp);
196 str = stack->ary_array[sp+1];
197 t = s = str_get(str);
201 while (size && *s && *s != '\n') {
205 if (*s && index(chopset,*s++))
207 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
212 else if (chophere && chophere < s && *s && index(chopset,*s))
214 if (fcmd->f_flags & FC_CHOP) {
217 size += (s - chophere);
219 while (*chophere && index(chopset,*chophere)
220 && isSPACE(*chophere))
233 if (fcmd->f_flags & FC_CHOP)
234 str_chop(str,chophere);
239 (void)eval(fcmd->f_expr,G_SCALAR,sp);
240 str = stack->ary_array[sp+1];
241 t = s = str_get(str);
245 while (size && *s && *s != '\n') {
249 if (*s && index(chopset,*s++))
251 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
256 else if (chophere && chophere < s && *s && index(chopset,*s))
258 if (fcmd->f_flags & FC_CHOP) {
261 size += (s - chophere);
263 while (*chophere && index(chopset,*chophere)
264 && isSPACE(*chophere))
270 while (size > halfsize) {
278 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
279 size = 0; /* no spaces before newline */
286 if (fcmd->f_flags & FC_CHOP)
287 str_chop(str,chophere);
291 (void)eval(fcmd->f_expr,G_SCALAR,sp);
292 str = stack->ary_array[sp+1];
296 orec->o_lines += countlines(s,size) - 1;
299 if (size && s[size-1] != '\n') {
303 linebeg = fcmd->f_next;
308 (void)eval(fcmd->f_expr,G_SCALAR,sp);
309 str = stack->ary_array[sp+1];
312 /* If the field is marked with ^ and the value is undefined,
314 if ((fcmd->f_flags & FC_CHOP) && !str->str_pok && !str->str_nok) {
321 value = str_gnum(str);
322 if (fcmd->f_flags & FC_DP) {
323 sprintf(d, "%#*.*f", size, fcmd->f_decimals, value);
325 sprintf(d, "%*.0f", size, value);
341 register int count = 0;
351 do_write(orec,stab,sp)
356 register STIO *stio = stab_io(stab);
357 FILE *ofp = stio->ofp;
361 fprintf(stderr,"left=%ld, todo=%ld\n",
362 (long)stio->lines_left, (long)orec->o_lines);
364 if (stio->lines_left < orec->o_lines) {
365 if (!stio->top_stab) {
369 if (!stio->top_name) {
371 stio->fmt_name = savestr(stab_name(stab));
372 sprintf(tmpbuf, "%s_TOP", stio->fmt_name);
373 topstab = stabent(tmpbuf,FALSE);
374 if (topstab && stab_form(topstab))
375 stio->top_name = savestr(tmpbuf);
377 stio->top_name = savestr("top");
379 topstab = stabent(stio->top_name,FALSE);
380 if (!topstab || !stab_form(topstab)) {
381 stio->lines_left = 100000000;
384 stio->top_stab = topstab;
386 if (stio->lines_left >= 0 && stio->page > 0)
387 fwrite(formfeed->str_ptr, formfeed->str_cur, 1, ofp);
388 stio->lines_left = stio->page_len;
390 format(&toprec,stab_form(stio->top_stab),sp);
391 fputs(toprec.o_str,ofp);
392 stio->lines_left -= toprec.o_lines;
395 fputs(orec->o_str,ofp);
396 stio->lines_left -= orec->o_lines;