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