a "replacement" for awk and sed
[perl.git] / form.c
1 /* $Header: form.c,v 1.0 87/12/18 13:05:07 root Exp $
2  *
3  * $Log:        form.c,v $
4  * Revision 1.0  87/12/18  13:05:07  root
5  * Initial revision
6  * 
7  */
8
9 #include "handy.h"
10 #include "EXTERN.h"
11 #include "search.h"
12 #include "util.h"
13 #include "perl.h"
14
15 /* Forms stuff */
16
17 #define CHKLEN(allow) \
18 if (d - orec->o_str + (allow) >= curlen) { \
19     curlen = d - orec->o_str; \
20     GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \
21     d = orec->o_str + curlen;   /* in case it moves */ \
22     curlen = orec->o_len - 2; \
23 }
24
25 format(orec,fcmd)
26 register struct outrec *orec;
27 register FCMD *fcmd;
28 {
29     register char *d = orec->o_str;
30     register char *s;
31     register int curlen = orec->o_len - 2;
32     register int size;
33     char tmpchar;
34     char *t;
35     CMD mycmd;
36     STR *str;
37     char *chophere;
38
39     mycmd.c_type = C_NULL;
40     orec->o_lines = 0;
41     for (; fcmd; fcmd = fcmd->f_next) {
42         CHKLEN(fcmd->f_presize);
43         for (s=fcmd->f_pre; *s;) {
44             if (*s == '\n') {
45                 while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
46                     d--;
47                 if (fcmd->f_flags & FC_NOBLANK &&
48                   (d == orec->o_str || d[-1] == '\n') ) {
49                     orec->o_lines--;            /* don't print blank line */
50                     break;
51                 }
52             }
53             *d++ = *s++;
54         }
55         switch (fcmd->f_type) {
56         case F_NULL:
57             orec->o_lines++;
58             break;
59         case F_LEFT:
60             str = eval(fcmd->f_expr,Null(char***),(double*)0);
61             s = str_get(str);
62             size = fcmd->f_size;
63             CHKLEN(size);
64             chophere = Nullch;
65             while (size && *s && *s != '\n') {
66                 size--;
67                 if ((*d++ = *s++) == ' ')
68                     chophere = s;
69             }
70             if (size)
71                 chophere = s;
72             if (fcmd->f_flags & FC_CHOP) {
73                 if (!chophere)
74                     chophere = s;
75                 size += (s - chophere);
76                 d -= (s - chophere);
77                 if (fcmd->f_flags & FC_MORE &&
78                   *chophere && strNE(chophere,"\n")) {
79                     while (size < 3) {
80                         d--;
81                         size++;
82                     }
83                     while (d[-1] == ' ' && size < fcmd->f_size) {
84                         d--;
85                         size++;
86                     }
87                     *d++ = '.';
88                     *d++ = '.';
89                     *d++ = '.';
90                 }
91                 s = chophere;
92                 while (*chophere == ' ' || *chophere == '\n')
93                         chophere++;
94                 str_chop(str,chophere);
95             }
96             if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
97                 size = 0;                       /* no spaces before newline */
98             while (size) {
99                 size--;
100                 *d++ = ' ';
101             }
102             break;
103         case F_RIGHT:
104             t = s = str_get(eval(fcmd->f_expr,Null(char***),(double*)0));
105             size = fcmd->f_size;
106             CHKLEN(size);
107             chophere = Nullch;
108             while (size && *s && *s != '\n') {
109                 size--;
110                 if (*s++ == ' ')
111                         chophere = s;
112             }
113             if (size)
114                 chophere = s;
115             if (fcmd->f_flags & FC_CHOP) {
116                 if (!chophere)
117                     chophere = s;
118                 size += (s - chophere);
119                 d -= (s - chophere);
120                 if (fcmd->f_flags & FC_MORE &&
121                   *chophere && strNE(chophere,"\n")) {
122                     while (size < 3) {
123                         d--;
124                         size++;
125                     }
126                     while (d[-1] == ' ' && size < fcmd->f_size) {
127                         d--;
128                         size++;
129                     }
130                     *d++ = '.';
131                     *d++ = '.';
132                     *d++ = '.';
133                 }
134                 s = chophere;
135                 while (*chophere == ' ' || *chophere == '\n')
136                         chophere++;
137                 str_chop(str,chophere);
138             }
139             tmpchar = *s;
140             *s = '\0';
141             while (size) {
142                 size--;
143                 *d++ = ' ';
144             }
145             size = s - t;
146             bcopy(t,d,size);
147             d += size;
148             *s = tmpchar;
149             break;
150         case F_CENTER: {
151             int halfsize;
152
153             t = s = str_get(eval(fcmd->f_expr,Null(char***),(double*)0));
154             size = fcmd->f_size;
155             CHKLEN(size);
156             chophere = Nullch;
157             while (size && *s && *s != '\n') {
158                 size--;
159                 if (*s++ == ' ')
160                         chophere = s;
161             }
162             if (size)
163                 chophere = s;
164             if (fcmd->f_flags & FC_CHOP) {
165                 if (!chophere)
166                     chophere = s;
167                 size += (s - chophere);
168                 d -= (s - chophere);
169                 if (fcmd->f_flags & FC_MORE &&
170                   *chophere && strNE(chophere,"\n")) {
171                     while (size < 3) {
172                         d--;
173                         size++;
174                     }
175                     while (d[-1] == ' ' && size < fcmd->f_size) {
176                         d--;
177                         size++;
178                     }
179                     *d++ = '.';
180                     *d++ = '.';
181                     *d++ = '.';
182                 }
183                 s = chophere;
184                 while (*chophere == ' ' || *chophere == '\n')
185                         chophere++;
186                 str_chop(str,chophere);
187             }
188             tmpchar = *s;
189             *s = '\0';
190             halfsize = size / 2;
191             while (size > halfsize) {
192                 size--;
193                 *d++ = ' ';
194             }
195             size = s - t;
196             bcopy(t,d,size);
197             d += size;
198             *s = tmpchar;
199             if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
200                 size = 0;                       /* no spaces before newline */
201             else
202                 size = halfsize;
203             while (size) {
204                 size--;
205                 *d++ = ' ';
206             }
207             break;
208         }
209         case F_LINES:
210             str = eval(fcmd->f_expr,Null(char***),(double*)0);
211             s = str_get(str);
212             size = str_len(str);
213             CHKLEN(size);
214             orec->o_lines += countlines(s);
215             bcopy(s,d,size);
216             d += size;
217             break;
218         }
219     }
220     *d++ = '\0';
221 }
222
223 countlines(s)
224 register char *s;
225 {
226     register int count = 0;
227
228     while (*s) {
229         if (*s++ == '\n')
230             count++;
231     }
232     return count;
233 }
234
235 do_write(orec,stio)
236 struct outrec *orec;
237 register STIO *stio;
238 {
239     FILE *ofp = stio->fp;
240
241 #ifdef DEBUGGING
242     if (debug & 256)
243         fprintf(stderr,"left=%d, todo=%d\n",stio->lines_left, orec->o_lines);
244 #endif
245     if (stio->lines_left < orec->o_lines) {
246         if (!stio->top_stab) {
247             STAB *topstab;
248
249             if (!stio->top_name)
250                 stio->top_name = savestr("top");
251             topstab = stabent(stio->top_name,FALSE);
252             if (!topstab || !topstab->stab_form) {
253                 stio->lines_left = 100000000;
254                 goto forget_top;
255             }
256             stio->top_stab = topstab;
257         }
258         if (stio->lines_left >= 0)
259             putc('\f',ofp);
260         stio->lines_left = stio->page_len;
261         stio->page++;
262         format(&toprec,stio->top_stab->stab_form);
263         fputs(toprec.o_str,ofp);
264         stio->lines_left -= toprec.o_lines;
265     }
266   forget_top:
267     fputs(orec->o_str,ofp);
268     stio->lines_left -= orec->o_lines;
269 }