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