perl 3.0 patch #37 (combined patch)
[p5sagit/p5-mst-13.2.git] / form.c
CommitLineData
d9d8d8de 1/* $Header: form.c,v 3.0.1.3 90/10/15 17:26:24 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 $
d9d8d8de 9 * Revision 3.0.1.3 90/10/15 17:26:24 lwall
10 * patch29: added @###.## fields to format
11 *
154e51a4 12 * Revision 3.0.1.2 90/08/09 03:38:40 lwall
13 * patch19: did preliminary work toward debugging packages and evals
14 *
ac58e20f 15 * Revision 3.0.1.1 90/02/28 17:39:34 lwall
16 * patch9: ... in format threw off subsequent field
17 *
a687059c 18 * Revision 3.0 89/10/18 15:17:26 lwall
19 * 3.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);
a687059c 105 if (s = fcmd->f_pre) {
106 while (*s) {
107 if (*s == '\n') {
108 while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
109 d--;
110 if (fcmd->f_flags & FC_NOBLANK) {
111 if (d == orec->o_str || d[-1] == '\n') {
112 orec->o_lines--; /* don't print blank line */
113 linebeg = fcmd->f_next;
114 break;
115 }
116 else if (fcmd->f_flags & FC_REPEAT)
117 nextfcmd = linebeg;
118 }
119 else
120 linebeg = fcmd->f_next;
8d063cd8 121 }
a687059c 122 *d++ = *s++;
8d063cd8 123 }
8d063cd8 124 }
a687059c 125 if (fcmd->f_unparsed)
126 form_parseargs(fcmd);
8d063cd8 127 switch (fcmd->f_type) {
128 case F_NULL:
129 orec->o_lines++;
130 break;
131 case F_LEFT:
a687059c 132 (void)eval(fcmd->f_expr,G_SCALAR,sp);
133 str = stack->ary_array[sp+1];
8d063cd8 134 s = str_get(str);
135 size = fcmd->f_size;
136 CHKLEN(size);
137 chophere = Nullch;
138 while (size && *s && *s != '\n') {
a687059c 139 if (*s == '\t')
140 *s = ' ';
8d063cd8 141 size--;
a687059c 142 if (*s && index(chopset,(*d++ = *s++)))
8d063cd8 143 chophere = s;
a687059c 144 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
145 *s = ' ';
8d063cd8 146 }
147 if (size)
148 chophere = s;
a687059c 149 else if (chophere && chophere < s && *s && index(chopset,*s))
150 chophere = s;
8d063cd8 151 if (fcmd->f_flags & FC_CHOP) {
152 if (!chophere)
153 chophere = s;
154 size += (s - chophere);
155 d -= (s - chophere);
156 if (fcmd->f_flags & FC_MORE &&
157 *chophere && strNE(chophere,"\n")) {
158 while (size < 3) {
159 d--;
160 size++;
161 }
162 while (d[-1] == ' ' && size < fcmd->f_size) {
163 d--;
164 size++;
165 }
166 *d++ = '.';
167 *d++ = '.';
168 *d++ = '.';
ac58e20f 169 size -= 3;
8d063cd8 170 }
a687059c 171 while (*chophere && index(chopset,*chophere))
172 chophere++;
8d063cd8 173 str_chop(str,chophere);
174 }
175 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
176 size = 0; /* no spaces before newline */
177 while (size) {
178 size--;
179 *d++ = ' ';
180 }
181 break;
182 case F_RIGHT:
a687059c 183 (void)eval(fcmd->f_expr,G_SCALAR,sp);
184 str = stack->ary_array[sp+1];
185 t = s = str_get(str);
8d063cd8 186 size = fcmd->f_size;
187 CHKLEN(size);
188 chophere = Nullch;
189 while (size && *s && *s != '\n') {
a687059c 190 if (*s == '\t')
191 *s = ' ';
8d063cd8 192 size--;
a687059c 193 if (*s && index(chopset,*s++))
194 chophere = s;
195 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
196 *s = ' ';
8d063cd8 197 }
198 if (size)
199 chophere = s;
a687059c 200 else if (chophere && chophere < s && *s && index(chopset,*s))
201 chophere = s;
8d063cd8 202 if (fcmd->f_flags & FC_CHOP) {
203 if (!chophere)
204 chophere = s;
205 size += (s - chophere);
8d063cd8 206 s = chophere;
a687059c 207 while (*chophere && index(chopset,*chophere))
208 chophere++;
8d063cd8 209 }
210 tmpchar = *s;
211 *s = '\0';
212 while (size) {
213 size--;
214 *d++ = ' ';
215 }
216 size = s - t;
a687059c 217 (void)bcopy(t,d,size);
8d063cd8 218 d += size;
219 *s = tmpchar;
a687059c 220 if (fcmd->f_flags & FC_CHOP)
221 str_chop(str,chophere);
8d063cd8 222 break;
223 case F_CENTER: {
224 int halfsize;
225
a687059c 226 (void)eval(fcmd->f_expr,G_SCALAR,sp);
227 str = stack->ary_array[sp+1];
228 t = s = str_get(str);
8d063cd8 229 size = fcmd->f_size;
230 CHKLEN(size);
231 chophere = Nullch;
232 while (size && *s && *s != '\n') {
a687059c 233 if (*s == '\t')
234 *s = ' ';
8d063cd8 235 size--;
a687059c 236 if (*s && index(chopset,*s++))
237 chophere = s;
238 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
239 *s = ' ';
8d063cd8 240 }
241 if (size)
242 chophere = s;
a687059c 243 else if (chophere && chophere < s && *s && index(chopset,*s))
244 chophere = s;
8d063cd8 245 if (fcmd->f_flags & FC_CHOP) {
246 if (!chophere)
247 chophere = s;
248 size += (s - chophere);
8d063cd8 249 s = chophere;
a687059c 250 while (*chophere && index(chopset,*chophere))
251 chophere++;
8d063cd8 252 }
253 tmpchar = *s;
254 *s = '\0';
255 halfsize = size / 2;
256 while (size > halfsize) {
257 size--;
258 *d++ = ' ';
259 }
260 size = s - t;
a687059c 261 (void)bcopy(t,d,size);
8d063cd8 262 d += size;
263 *s = tmpchar;
264 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
265 size = 0; /* no spaces before newline */
266 else
267 size = halfsize;
268 while (size) {
269 size--;
270 *d++ = ' ';
271 }
a687059c 272 if (fcmd->f_flags & FC_CHOP)
273 str_chop(str,chophere);
8d063cd8 274 break;
275 }
276 case F_LINES:
a687059c 277 (void)eval(fcmd->f_expr,G_SCALAR,sp);
278 str = stack->ary_array[sp+1];
8d063cd8 279 s = str_get(str);
280 size = str_len(str);
281 CHKLEN(size);
282 orec->o_lines += countlines(s);
a687059c 283 (void)bcopy(s,d,size);
8d063cd8 284 d += size;
a687059c 285 linebeg = fcmd->f_next;
8d063cd8 286 break;
d9d8d8de 287 case F_DECIMAL: {
288 double value;
289
290 (void)eval(fcmd->f_expr,G_SCALAR,sp);
291 str = stack->ary_array[sp+1];
292 /* If the field is marked with ^ and the value is undefined,
293 blank it out. */
294 if ((fcmd->f_flags & FC_CHOP) && !str->str_pok && !str->str_nok) {
295 while (size) {
296 size--;
297 *d++ = ' ';
298 }
299 break;
300 }
301 value = str_gnum(str);
302 size = fcmd->f_size;
303 CHKLEN(size);
304 if (fcmd->f_flags & FC_DP) {
305 sprintf(d, "%#*.*f", size, fcmd->f_decimals, value);
306 } else {
307 sprintf(d, "%*.0f", size, value);
308 }
309 d += size;
310 break;
311 }
8d063cd8 312 }
313 }
154e51a4 314 CHKLEN(1);
8d063cd8 315 *d++ = '\0';
316}
317
318countlines(s)
319register char *s;
320{
321 register int count = 0;
322
323 while (*s) {
324 if (*s++ == '\n')
325 count++;
326 }
327 return count;
328}
329
a687059c 330do_write(orec,stio,sp)
8d063cd8 331struct outrec *orec;
332register STIO *stio;
a687059c 333int sp;
8d063cd8 334{
a687059c 335 FILE *ofp = stio->ofp;
8d063cd8 336
337#ifdef DEBUGGING
338 if (debug & 256)
378cc40b 339 fprintf(stderr,"left=%ld, todo=%ld\n",
340 (long)stio->lines_left, (long)orec->o_lines);
8d063cd8 341#endif
342 if (stio->lines_left < orec->o_lines) {
343 if (!stio->top_stab) {
344 STAB *topstab;
345
346 if (!stio->top_name)
347 stio->top_name = savestr("top");
348 topstab = stabent(stio->top_name,FALSE);
a687059c 349 if (!topstab || !stab_form(topstab)) {
8d063cd8 350 stio->lines_left = 100000000;
351 goto forget_top;
352 }
353 stio->top_stab = topstab;
354 }
a687059c 355 if (stio->lines_left >= 0 && stio->page > 0)
356 (void)putc('\f',ofp);
8d063cd8 357 stio->lines_left = stio->page_len;
358 stio->page++;
a687059c 359 format(&toprec,stab_form(stio->top_stab),sp);
8d063cd8 360 fputs(toprec.o_str,ofp);
361 stio->lines_left -= toprec.o_lines;
362 }
363 forget_top:
364 fputs(orec->o_str,ofp);
365 stio->lines_left -= orec->o_lines;
366}