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