perl 3.0: (no announcement message available)
[p5sagit/p5-mst-13.2.git] / form.c
CommitLineData
a687059c 1/* $Header: form.c,v 3.0 89/10/18 15:17:26 lwall Locked $
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 $
a687059c 9 * Revision 3.0 89/10/18 15:17:26 lwall
10 * 3.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();
28 line_t oldline = line;
29 int oldsave = savestack->ary_fill;
30
31 str = fcmd->f_unparsed;
32 line = fcmd->f_line;
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");
58 line = oldline;
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;
109 }
110 else
111 linebeg = fcmd->f_next;
8d063cd8 112 }
a687059c 113 *d++ = *s++;
8d063cd8 114 }
8d063cd8 115 }
a687059c 116 if (fcmd->f_unparsed)
117 form_parseargs(fcmd);
8d063cd8 118 switch (fcmd->f_type) {
119 case F_NULL:
120 orec->o_lines++;
121 break;
122 case F_LEFT:
a687059c 123 (void)eval(fcmd->f_expr,G_SCALAR,sp);
124 str = stack->ary_array[sp+1];
8d063cd8 125 s = str_get(str);
126 size = fcmd->f_size;
127 CHKLEN(size);
128 chophere = Nullch;
129 while (size && *s && *s != '\n') {
a687059c 130 if (*s == '\t')
131 *s = ' ';
8d063cd8 132 size--;
a687059c 133 if (*s && index(chopset,(*d++ = *s++)))
8d063cd8 134 chophere = s;
a687059c 135 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
136 *s = ' ';
8d063cd8 137 }
138 if (size)
139 chophere = s;
a687059c 140 else if (chophere && chophere < s && *s && index(chopset,*s))
141 chophere = s;
8d063cd8 142 if (fcmd->f_flags & FC_CHOP) {
143 if (!chophere)
144 chophere = s;
145 size += (s - chophere);
146 d -= (s - chophere);
147 if (fcmd->f_flags & FC_MORE &&
148 *chophere && strNE(chophere,"\n")) {
149 while (size < 3) {
150 d--;
151 size++;
152 }
153 while (d[-1] == ' ' && size < fcmd->f_size) {
154 d--;
155 size++;
156 }
157 *d++ = '.';
158 *d++ = '.';
159 *d++ = '.';
160 }
a687059c 161 while (*chophere && index(chopset,*chophere))
162 chophere++;
8d063cd8 163 str_chop(str,chophere);
164 }
165 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
166 size = 0; /* no spaces before newline */
167 while (size) {
168 size--;
169 *d++ = ' ';
170 }
171 break;
172 case F_RIGHT:
a687059c 173 (void)eval(fcmd->f_expr,G_SCALAR,sp);
174 str = stack->ary_array[sp+1];
175 t = s = str_get(str);
8d063cd8 176 size = fcmd->f_size;
177 CHKLEN(size);
178 chophere = Nullch;
179 while (size && *s && *s != '\n') {
a687059c 180 if (*s == '\t')
181 *s = ' ';
8d063cd8 182 size--;
a687059c 183 if (*s && index(chopset,*s++))
184 chophere = s;
185 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
186 *s = ' ';
8d063cd8 187 }
188 if (size)
189 chophere = s;
a687059c 190 else if (chophere && chophere < s && *s && index(chopset,*s))
191 chophere = s;
8d063cd8 192 if (fcmd->f_flags & FC_CHOP) {
193 if (!chophere)
194 chophere = s;
195 size += (s - chophere);
8d063cd8 196 s = chophere;
a687059c 197 while (*chophere && index(chopset,*chophere))
198 chophere++;
8d063cd8 199 }
200 tmpchar = *s;
201 *s = '\0';
202 while (size) {
203 size--;
204 *d++ = ' ';
205 }
206 size = s - t;
a687059c 207 (void)bcopy(t,d,size);
8d063cd8 208 d += size;
209 *s = tmpchar;
a687059c 210 if (fcmd->f_flags & FC_CHOP)
211 str_chop(str,chophere);
8d063cd8 212 break;
213 case F_CENTER: {
214 int halfsize;
215
a687059c 216 (void)eval(fcmd->f_expr,G_SCALAR,sp);
217 str = stack->ary_array[sp+1];
218 t = s = str_get(str);
8d063cd8 219 size = fcmd->f_size;
220 CHKLEN(size);
221 chophere = Nullch;
222 while (size && *s && *s != '\n') {
a687059c 223 if (*s == '\t')
224 *s = ' ';
8d063cd8 225 size--;
a687059c 226 if (*s && index(chopset,*s++))
227 chophere = s;
228 if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
229 *s = ' ';
8d063cd8 230 }
231 if (size)
232 chophere = s;
a687059c 233 else if (chophere && chophere < s && *s && index(chopset,*s))
234 chophere = s;
8d063cd8 235 if (fcmd->f_flags & FC_CHOP) {
236 if (!chophere)
237 chophere = s;
238 size += (s - chophere);
8d063cd8 239 s = chophere;
a687059c 240 while (*chophere && index(chopset,*chophere))
241 chophere++;
8d063cd8 242 }
243 tmpchar = *s;
244 *s = '\0';
245 halfsize = size / 2;
246 while (size > halfsize) {
247 size--;
248 *d++ = ' ';
249 }
250 size = s - t;
a687059c 251 (void)bcopy(t,d,size);
8d063cd8 252 d += size;
253 *s = tmpchar;
254 if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
255 size = 0; /* no spaces before newline */
256 else
257 size = halfsize;
258 while (size) {
259 size--;
260 *d++ = ' ';
261 }
a687059c 262 if (fcmd->f_flags & FC_CHOP)
263 str_chop(str,chophere);
8d063cd8 264 break;
265 }
266 case F_LINES:
a687059c 267 (void)eval(fcmd->f_expr,G_SCALAR,sp);
268 str = stack->ary_array[sp+1];
8d063cd8 269 s = str_get(str);
270 size = str_len(str);
271 CHKLEN(size);
272 orec->o_lines += countlines(s);
a687059c 273 (void)bcopy(s,d,size);
8d063cd8 274 d += size;
a687059c 275 linebeg = fcmd->f_next;
8d063cd8 276 break;
277 }
278 }
279 *d++ = '\0';
280}
281
282countlines(s)
283register char *s;
284{
285 register int count = 0;
286
287 while (*s) {
288 if (*s++ == '\n')
289 count++;
290 }
291 return count;
292}
293
a687059c 294do_write(orec,stio,sp)
8d063cd8 295struct outrec *orec;
296register STIO *stio;
a687059c 297int sp;
8d063cd8 298{
a687059c 299 FILE *ofp = stio->ofp;
8d063cd8 300
301#ifdef DEBUGGING
302 if (debug & 256)
378cc40b 303 fprintf(stderr,"left=%ld, todo=%ld\n",
304 (long)stio->lines_left, (long)orec->o_lines);
8d063cd8 305#endif
306 if (stio->lines_left < orec->o_lines) {
307 if (!stio->top_stab) {
308 STAB *topstab;
309
310 if (!stio->top_name)
311 stio->top_name = savestr("top");
312 topstab = stabent(stio->top_name,FALSE);
a687059c 313 if (!topstab || !stab_form(topstab)) {
8d063cd8 314 stio->lines_left = 100000000;
315 goto forget_top;
316 }
317 stio->top_stab = topstab;
318 }
a687059c 319 if (stio->lines_left >= 0 && stio->page > 0)
320 (void)putc('\f',ofp);
8d063cd8 321 stio->lines_left = stio->page_len;
322 stio->page++;
a687059c 323 format(&toprec,stab_form(stio->top_stab),sp);
8d063cd8 324 fputs(toprec.o_str,ofp);
325 stio->lines_left -= toprec.o_lines;
326 }
327 forget_top:
328 fputs(orec->o_str,ofp);
329 stio->lines_left -= orec->o_lines;
330}