1 /* $RCSfile: form.c,v $$Revision: 4.0.1.2 $$Date: 91/11/05 17:18:43 $
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.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
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
18 * Revision 4.0 91/03/20 01:19:23 lwall
37 line_t oldline = curcmd->c_line;
38 int oldsave = savestack->ary_fill;
40 str = fcmd->f_unparsed;
41 curcmd->c_line = fcmd->f_line;
42 fcmd->f_unparsed = Nullstr;
43 (void)savehptr(&curstash);
44 curstash = str->str_u.str_hash;
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");
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;
61 fatal("^ field requires scalar lvalue");
65 if (fcmd && fcmd->f_type)
66 fatal("Not enough field values");
67 curcmd->c_line = oldline;
74 #define CHKLEN(allow) \
75 newsize = (d - orec->o_str) + (allow); \
76 if (newsize >= curlen) { \
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; \
84 register struct outrec *orec;
88 register char *d = orec->o_str;
90 register int curlen = orec->o_len - 2;
100 mycmd.c_type = C_NULL;
102 for (; fcmd; fcmd = nextfcmd) {
103 nextfcmd = fcmd->f_next;
104 CHKLEN(fcmd->f_presize);
106 if (s = fcmd->f_pre) {
109 while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
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;
117 else if (fcmd->f_flags & FC_REPEAT)
120 linebeg = fcmd->f_next;
123 linebeg = fcmd->f_next;
128 if (fcmd->f_unparsed)
129 form_parseargs(fcmd);
130 switch (fcmd->f_type) {
135 (void)eval(fcmd->f_expr,G_SCALAR,sp);
136 str = stack->ary_array[sp+1];
141 while (size && *s && *s != '\n') {
145 if (*s && index(chopset,(*d++ = *s++)))
147 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
152 else if (chophere && chophere < s && *s && index(chopset,*s))
154 if (fcmd->f_flags & FC_CHOP) {
157 size += (s - chophere);
159 if (fcmd->f_flags & FC_MORE &&
160 *chophere && strNE(chophere,"\n")) {
165 while (d[-1] == ' ' && size < fcmd->f_size) {
174 while (*chophere && index(chopset,*chophere)
175 && isSPACE(*chophere))
177 str_chop(str,chophere);
179 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
180 size = 0; /* no spaces before newline */
187 (void)eval(fcmd->f_expr,G_SCALAR,sp);
188 str = stack->ary_array[sp+1];
189 t = s = str_get(str);
193 while (size && *s && *s != '\n') {
197 if (*s && index(chopset,*s++))
199 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
204 else if (chophere && chophere < s && *s && index(chopset,*s))
206 if (fcmd->f_flags & FC_CHOP) {
209 size += (s - chophere);
211 while (*chophere && index(chopset,*chophere)
212 && isSPACE(*chophere))
222 (void)bcopy(t,d,size);
225 if (fcmd->f_flags & FC_CHOP)
226 str_chop(str,chophere);
231 (void)eval(fcmd->f_expr,G_SCALAR,sp);
232 str = stack->ary_array[sp+1];
233 t = s = str_get(str);
237 while (size && *s && *s != '\n') {
241 if (*s && index(chopset,*s++))
243 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
248 else if (chophere && chophere < s && *s && index(chopset,*s))
250 if (fcmd->f_flags & FC_CHOP) {
253 size += (s - chophere);
255 while (*chophere && index(chopset,*chophere)
256 && isSPACE(*chophere))
262 while (size > halfsize) {
267 (void)bcopy(t,d,size);
270 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
271 size = 0; /* no spaces before newline */
278 if (fcmd->f_flags & FC_CHOP)
279 str_chop(str,chophere);
283 (void)eval(fcmd->f_expr,G_SCALAR,sp);
284 str = stack->ary_array[sp+1];
288 orec->o_lines += countlines(s,size) - 1;
289 (void)bcopy(s,d,size);
291 if (size && s[size-1] != '\n') {
295 linebeg = fcmd->f_next;
300 (void)eval(fcmd->f_expr,G_SCALAR,sp);
301 str = stack->ary_array[sp+1];
304 /* If the field is marked with ^ and the value is undefined,
306 if ((fcmd->f_flags & FC_CHOP) && !str->str_pok && !str->str_nok) {
313 value = str_gnum(str);
314 if (fcmd->f_flags & FC_DP) {
315 sprintf(d, "%#*.*f", size, fcmd->f_decimals, value);
317 sprintf(d, "%*.0f", size, value);
332 register int count = 0;
341 do_write(orec,stab,sp)
346 register STIO *stio = stab_io(stab);
347 FILE *ofp = stio->ofp;
351 fprintf(stderr,"left=%ld, todo=%ld\n",
352 (long)stio->lines_left, (long)orec->o_lines);
354 if (stio->lines_left < orec->o_lines) {
355 if (!stio->top_stab) {
359 if (!stio->top_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);
367 stio->top_name = savestr("top");
369 topstab = stabent(stio->top_name,FALSE);
370 if (!topstab || !stab_form(topstab)) {
371 stio->lines_left = 100000000;
374 stio->top_stab = topstab;
376 if (stio->lines_left >= 0 && stio->page > 0)
377 (void)putc('\f',ofp);
378 stio->lines_left = stio->page_len;
380 format(&toprec,stab_form(stio->top_stab),sp);
381 fputs(toprec.o_str,ofp);
382 stio->lines_left -= toprec.o_lines;
385 fputs(orec->o_str,ofp);
386 stio->lines_left -= orec->o_lines;