0
|
1 /* fmtcompile.c - "compile" format strings for fmtscan */
|
|
2 #ifndef lint
|
12
|
3 static char ident[] = "@(#)$Id: fmtcompile.c,v 1.1.1.1 2005/04/18 14:46:06 kono Exp $";
|
0
|
4 #endif /* lint */
|
|
5
|
|
6 #include "../h/mh.h"
|
|
7 #include "../h/addrsbr.h"
|
|
8 #include "../h/formatsbr.h"
|
|
9 #include "../zotnet/tws.h"
|
|
10 #include "../h/fmtcompile.h"
|
|
11 #include <ctype.h>
|
|
12 #include <stdio.h>
|
|
13 #include <sys/types.h>
|
|
14 #include <sys/stat.h>
|
|
15
|
|
16 static struct format *formatvec; /* array to hold formats */
|
|
17 static struct format *next_fp; /* next free format slot */
|
|
18 static struct format *fp; /* current format slot */
|
|
19 static struct comp *cm; /* most recent comp ref */
|
|
20 static struct ftable *ftbl; /* most recent func ref */
|
|
21 static int ncomp;
|
|
22 static int infunction; /* function nesting cnt */
|
|
23
|
|
24 extern char *getusr();
|
|
25 extern struct mailname fmt_mnull;
|
|
26
|
|
27 struct ftable {
|
|
28 char *name; /* function name */
|
|
29 char type; /* argument type */
|
|
30 #define TF_COMP 0 /* component expected */
|
|
31 #define TF_NUM 1 /* number expected */
|
|
32 #define TF_STR 2 /* string expected */
|
|
33 #define TF_EXPR 3 /* component or func. expected */
|
|
34 #define TF_NONE 4 /* no argument */
|
|
35 #define TF_MYBOX 5 /* special - get current user's mbox */
|
|
36 #define TF_NOW 6 /* special - get current unix time */
|
|
37 #define TF_EXPR_SV 7 /* like expr but save current str reg */
|
|
38 #define TF_NOP 8 /* like expr but no result */
|
|
39 char f_type; /* fmt type */
|
|
40 char extra; /* arg. type dependent extra info */
|
|
41 char flags;
|
|
42 #define TFL_PUTS 1 /* implicit putstr if top level */
|
|
43 #define TFL_PUTN 2 /* implicit putnum if top level */
|
|
44 };
|
|
45
|
|
46 static struct ftable functable[] = {
|
|
47 "nonzero", TF_EXPR, FT_V_NE, FT_IF_V_NE, 0,
|
|
48 "zero", TF_EXPR, FT_V_EQ, FT_IF_V_EQ, 0,
|
|
49 "eq", TF_NUM, FT_V_EQ, FT_IF_V_EQ, 0,
|
|
50 "ne", TF_NUM, FT_V_NE, FT_IF_V_NE, 0,
|
|
51 "gt", TF_NUM, FT_V_GT, FT_IF_V_GT, 0,
|
|
52 "null", TF_EXPR, FT_S_NULL, FT_IF_S_NULL, 0,
|
|
53 "nonnull", TF_EXPR, FT_S_NONNULL, FT_IF_S, 0,
|
|
54 "match", TF_STR, FT_V_MATCH, FT_IF_MATCH, 0,
|
|
55 "amatch", TF_STR, FT_V_AMATCH, FT_IF_AMATCH, 0,
|
|
56
|
|
57 "putstr", TF_EXPR, FT_STR, 0, 0,
|
|
58 "putstrf", TF_EXPR, FT_STRF, 0, 0,
|
|
59 "putnum", TF_EXPR, FT_NUM, 0, 0,
|
|
60 "putnumf", TF_EXPR, FT_NUMF, 0, 0,
|
|
61 "putaddr", TF_STR, FT_PUTADDR, 0, 0,
|
|
62 "void", TF_NOP, 0, 0, 0,
|
|
63
|
|
64 "comp", TF_COMP, FT_LS_COMP, 0, TFL_PUTS,
|
|
65 "lit", TF_STR, FT_LS_LIT, 0, TFL_PUTS,
|
|
66 "getenv", TF_STR, FT_LS_GETENV, 0, TFL_PUTS,
|
|
67 "profile", TF_STR, FT_LS_MFIND, 0, TFL_PUTS,
|
|
68 "trim", TF_EXPR, FT_LS_TRIM, 0, 0,
|
|
69 "compval", TF_COMP, FT_LV_COMP, 0, TFL_PUTN,
|
|
70 "compflag", TF_COMP, FT_LV_COMPFLAG, 0, TFL_PUTN,
|
|
71 "num", TF_NUM, FT_LV_LIT, 0, TFL_PUTN,
|
|
72 "msg", TF_NONE, FT_LV_DAT, 0, TFL_PUTN,
|
|
73 "cur", TF_NONE, FT_LV_DAT, 1, TFL_PUTN,
|
|
74 "size", TF_NONE, FT_LV_DAT, 2, TFL_PUTN,
|
|
75 "width", TF_NONE, FT_LV_DAT, 3, TFL_PUTN,
|
|
76 "unseen", TF_NONE, FT_LV_DAT, 4, TFL_PUTN,
|
|
77 "dat", TF_NUM, FT_LV_DAT, 0, TFL_PUTN,
|
|
78 "strlen", TF_NONE, FT_LV_STRLEN, 0, TFL_PUTN,
|
|
79 "me", TF_MYBOX, FT_LS_LIT, 0, TFL_PUTS,
|
|
80 "plus", TF_NUM, FT_LV_PLUS_L, 0, TFL_PUTN,
|
|
81 "minus", TF_NUM, FT_LV_MINUS_L, 0, TFL_PUTN,
|
|
82 "divide", TF_NUM, FT_LV_DIVIDE_L, 0, TFL_PUTN,
|
|
83 "modulo", TF_NUM, FT_LV_MODULO_L, 0, TFL_PUTN,
|
|
84 "charleft", TF_NONE, FT_LV_CHAR_LEFT, 0, TFL_PUTN,
|
|
85 "timenow", TF_NOW, FT_LV_LIT, 0, TFL_PUTN,
|
|
86
|
|
87 "month", TF_COMP, FT_LS_MONTH, FT_PARSEDATE, TFL_PUTS,
|
|
88 "lmonth", TF_COMP, FT_LS_LMONTH, FT_PARSEDATE, TFL_PUTS,
|
|
89 "tzone", TF_COMP, FT_LS_ZONE, FT_PARSEDATE, TFL_PUTS,
|
|
90 "day", TF_COMP, FT_LS_DAY, FT_PARSEDATE, TFL_PUTS,
|
|
91 "weekday", TF_COMP, FT_LS_WEEKDAY, FT_PARSEDATE, TFL_PUTS,
|
|
92 "tws", TF_COMP, FT_LS_822DATE, FT_PARSEDATE, TFL_PUTS,
|
|
93 "sec", TF_COMP, FT_LV_SEC, FT_PARSEDATE, TFL_PUTN,
|
|
94 "min", TF_COMP, FT_LV_MIN, FT_PARSEDATE, TFL_PUTN,
|
|
95 "hour", TF_COMP, FT_LV_HOUR, FT_PARSEDATE, TFL_PUTN,
|
|
96 "mday", TF_COMP, FT_LV_MDAY, FT_PARSEDATE, TFL_PUTN,
|
|
97 "mon", TF_COMP, FT_LV_MON, FT_PARSEDATE, TFL_PUTN,
|
|
98 "year", TF_COMP, FT_LV_YEAR, FT_PARSEDATE, TFL_PUTN,
|
|
99 "yday", TF_COMP, FT_LV_YDAY, FT_PARSEDATE, TFL_PUTN,
|
|
100 "wday", TF_COMP, FT_LV_WDAY, FT_PARSEDATE, TFL_PUTN,
|
|
101 "zone", TF_COMP, FT_LV_ZONE, FT_PARSEDATE, TFL_PUTN,
|
|
102 "clock", TF_COMP, FT_LV_CLOCK, FT_PARSEDATE, TFL_PUTN,
|
|
103 "rclock", TF_COMP, FT_LV_RCLOCK, FT_PARSEDATE, TFL_PUTN,
|
|
104 "sday", TF_COMP, FT_LV_DAYF, FT_PARSEDATE, TFL_PUTN,
|
|
105 "szone", TF_COMP, FT_LV_ZONEF, FT_PARSEDATE, TFL_PUTN,
|
|
106 "dst", TF_COMP, FT_LV_DST, FT_PARSEDATE, TFL_PUTN,
|
|
107 "pretty", TF_COMP, FT_LS_PRETTY, FT_PARSEDATE, TFL_PUTS,
|
|
108 "nodate", TF_COMP, FT_LV_COMPFLAG, FT_PARSEDATE, TFL_PUTN,
|
|
109 "date2local", TF_COMP, FT_LOCALDATE, FT_PARSEDATE, 0,
|
|
110 "date2gmt", TF_COMP, FT_GMTDATE, FT_PARSEDATE, 0,
|
|
111
|
|
112 "pers", TF_COMP, FT_LS_PERS, FT_PARSEADDR, TFL_PUTS,
|
|
113 "mbox", TF_COMP, FT_LS_MBOX, FT_PARSEADDR, TFL_PUTS,
|
|
114 "host", TF_COMP, FT_LS_HOST, FT_PARSEADDR, TFL_PUTS,
|
|
115 "path", TF_COMP, FT_LS_PATH, FT_PARSEADDR, TFL_PUTS,
|
|
116 "gname", TF_COMP, FT_LS_GNAME, FT_PARSEADDR, TFL_PUTS,
|
|
117 "note", TF_COMP, FT_LS_NOTE, FT_PARSEADDR, TFL_PUTS,
|
|
118 "addr", TF_COMP, FT_LS_ADDR, FT_PARSEADDR, TFL_PUTS,
|
|
119 "proper", TF_COMP, FT_LS_822ADDR, FT_PARSEADDR, TFL_PUTS,
|
|
120 "type", TF_COMP, FT_LV_HOSTTYPE, FT_PARSEADDR, TFL_PUTN,
|
|
121 "ingrp", TF_COMP, FT_LV_INGRPF, FT_PARSEADDR, TFL_PUTN,
|
|
122 "nohost", TF_COMP, FT_LV_NOHOSTF, FT_PARSEADDR, TFL_PUTN,
|
|
123 "formataddr", TF_EXPR_SV, FT_FORMATADDR, FT_FORMATADDR, 0,
|
|
124 "friendly", TF_COMP, FT_LS_FRIENDLY, FT_PARSEADDR, TFL_PUTS,
|
|
125
|
|
126 "mymbox", TF_COMP, FT_LV_COMPFLAG, FT_MYMBOX, TFL_PUTN,
|
|
127 "addtoseq", TF_STR, FT_ADDTOSEQ, 0, 0,
|
|
128 #ifdef MIME_HEADERS
|
|
129 "hencode", TF_EXPR, FT_LS_HENCODE, 0, TFL_PUTS,
|
|
130 "hdecode", TF_EXPR, FT_LS_HDECODE, 0, TFL_PUTS,
|
|
131 #endif /* MIME_HEADERS */
|
|
132
|
|
133 (char *)0, 0, 0, 0, 0
|
|
134 };
|
|
135
|
|
136
|
|
137 time_t time ();
|
|
138
|
|
139 static struct ftable *lookup(name)
|
|
140 register char *name;
|
|
141 {
|
|
142 register struct ftable *t = functable;
|
|
143 register char *nm;
|
|
144 register char c = *name;
|
|
145
|
|
146 while (nm = t->name) {
|
|
147 if (*nm == c && strcmp (nm, name) == 0)
|
|
148 return (ftbl = t);
|
|
149
|
|
150 t++;
|
|
151 }
|
|
152 return (struct ftable *)0;
|
|
153 }
|
|
154
|
|
155
|
|
156 #define NEWCOMP(cm,name)\
|
|
157 cm = ((struct comp *)calloc(1, sizeof (struct comp)));\
|
|
158 cm->c_name = name; ncomp++;\
|
|
159 i = CHASH(name); cm->c_next = wantcomp[i]; wantcomp[i] = cm;
|
|
160
|
|
161 #define NEWFMT (next_fp++)
|
|
162 #define NEW(type,fill,wid)\
|
|
163 fp=NEWFMT; fp->f_type=(type); fp->f_fill=(fill); fp->f_width=(wid);
|
|
164
|
|
165 #define ADDC(name)\
|
|
166 FINDCOMP( cm, name );\
|
|
167 if ( ! cm ) {\
|
|
168 NEWCOMP(cm,name);\
|
|
169 }\
|
|
170 fp->f_comp = cm;
|
|
171
|
|
172 #define LV( type, value ) NEW(type,0,0); fp->f_value = (value);
|
|
173 #define LS( type, str ) NEW(type,0,0); fp->f_text = (str);
|
|
174 #define PUTCOMP( comp ) NEW(FT_COMP,0,0); ADDC(comp);
|
|
175 #define PUTLIT( str ) NEW(FT_LIT,0,0); fp->f_text = (str);
|
|
176 #define PUTC( c ) NEW(FT_CHAR,0,0); fp->f_char = (c);
|
|
177
|
|
178 static char *compile();
|
|
179 static char *do_spec();
|
|
180 static char *do_name();
|
|
181 static char *do_func();
|
|
182 static char *do_expr();
|
|
183 static char *do_if();
|
|
184 static char *do_loop();
|
|
185
|
|
186 static char *format_string;
|
|
187 static char *usr_fstring; /* for CERROR */
|
|
188
|
|
189 #define CERROR(str) compile_error (str, cp)
|
|
190
|
|
191 static void
|
|
192 compile_error(str, cp)
|
|
193 char *str;
|
|
194 char *cp;
|
|
195 {
|
|
196 int errpos = cp - format_string;
|
|
197 int errctx = errpos > 20 ? 20 : errpos;
|
|
198 int i;
|
|
199
|
|
200 #ifdef JAPAN
|
|
201 errpos = cp - format_string + (*cp ? 1 : 0);
|
|
202 errctx = errpos > 20 ? 20 : errpos;
|
|
203 usr_fstring[errpos] = '\0';
|
|
204 while ((errctx < errpos) && ml_ismlchar(usr_fstring[errpos-errctx]))
|
|
205 errctx++;
|
|
206 for (i = errpos-errctx; i < errpos; i++)
|
|
207 if (iscntrl((usr_fstring[i] & 0x7f)))
|
|
208 usr_fstring[i] = '_';
|
|
209 advise(NULLCP, "\"%s\": format compile error - %s",
|
|
210 &usr_fstring[errpos-errctx], str);
|
|
211 adios (NULLCP, "%*s", errctx + 1 - (*cp ? 1 : 0), "^");
|
|
212 #else /* JAPAN */
|
|
213 usr_fstring[errpos] = '\0';
|
|
214 for (i = errpos-errctx; i < errpos; i++)
|
|
215 #ifdef LOCALE
|
|
216 if (iscntrl(usr_fstring[i] & 0x7f))
|
|
217 #else
|
|
218 if (usr_fstring[i] < 32)
|
|
219 #endif
|
|
220 usr_fstring[i] = '_';
|
|
221 advise(NULLCP, "\"%s\": format compile error - %s",
|
|
222 &usr_fstring[errpos-errctx], str);
|
|
223 adios (NULLCP, "%*s", errctx+1, "^");
|
|
224 #endif /* JAPAN */
|
|
225 }
|
|
226
|
|
227 /*
|
|
228 * Compile format string "fstring" into format list "fmt".
|
|
229 * Return the number of header components found in the format
|
|
230 * string.
|
|
231 */
|
|
232 fmt_compile( fstring, fmt )
|
|
233 register char *fstring;
|
|
234 struct format **fmt;
|
|
235 {
|
|
236 register char *cp;
|
|
237 int i;
|
|
238
|
|
239 if (format_string)
|
|
240 (void) free (format_string);
|
|
241 format_string = getcpy (fstring);
|
|
242 usr_fstring = fstring;
|
|
243
|
|
244 /* init the component hash table. */
|
|
245 for (i = 0; i < sizeof(wantcomp)/sizeof(wantcomp[0]); i++)
|
|
246 wantcomp[i] = 0;
|
|
247
|
|
248 bzero ((char *) &fmt_mnull, sizeof fmt_mnull);
|
|
249
|
|
250 /* it takes at least 4 char to generate one format so we
|
|
251 * allocate a worst-case format array using 1/4 the length
|
|
252 * of the format string. We actually need twice this much
|
|
253 * to handle both pre-processing (e.g., address parsing) and
|
|
254 * normal processing.
|
|
255 */
|
|
256 i = strlen(fstring)/2 + 1;
|
|
257 next_fp = formatvec = (struct format *)calloc ((unsigned) i,
|
|
258 sizeof(struct format));
|
|
259 if (next_fp == NULL)
|
|
260 adios (NULLCP, "unable to allocate format storage");
|
|
261
|
|
262 ncomp = 0;
|
|
263 infunction = 0;
|
|
264
|
|
265 cp = compile(format_string);
|
|
266 if (*cp) {
|
|
267 CERROR("extra '%>', '%|' or '%?'");
|
|
268 }
|
|
269 LV(FT_DONE,0); /* really done */
|
|
270 *fmt = formatvec;
|
|
271
|
|
272 return (ncomp);
|
|
273 }
|
|
274
|
|
275 static char *compile (sp)
|
|
276 register char *sp;
|
|
277 {
|
|
278 register char *cp = sp;
|
|
279 register int c;
|
|
280
|
|
281 for (;;) {
|
|
282 sp = cp;
|
|
283 while ((c = *cp) && c != '%')
|
|
284 cp++;
|
|
285 *cp = 0;
|
|
286 switch (cp-sp) {
|
|
287 case 0:
|
|
288 break;
|
|
289 case 1:
|
|
290 PUTC(*sp);
|
|
291 break;
|
|
292 default:
|
|
293 PUTLIT(sp);
|
|
294 break;
|
|
295 }
|
|
296 if (c == 0)
|
|
297 return (cp);
|
|
298
|
|
299 switch (c = *++cp) {
|
|
300 case '%':
|
|
301 PUTC (*cp);
|
|
302 cp++;
|
|
303 break;
|
|
304
|
|
305 case '|':
|
|
306 case '>':
|
|
307 case '?':
|
|
308 case ']':
|
|
309 return (cp);
|
|
310
|
|
311 case '<':
|
|
312 cp = do_if(++cp);
|
|
313 break;
|
|
314
|
|
315 case '[': /* ] */
|
|
316 cp = do_loop(++cp);
|
|
317 break;
|
|
318
|
|
319 case ';': /* comment line */
|
|
320 cp++;
|
|
321 while ((c = *cp++) && c != '\n')
|
|
322 continue;
|
|
323 break;
|
|
324
|
|
325 default:
|
|
326 cp = do_spec(cp);
|
|
327 break;
|
|
328 }
|
|
329 }
|
|
330 }
|
|
331
|
|
332
|
|
333 static char *do_spec(sp)
|
|
334 register char *sp;
|
|
335 {
|
|
336 register char *cp = sp;
|
|
337 register int c;
|
|
338 #ifndef lint
|
|
339 register int ljust = 0;
|
|
340 #endif /* not lint */
|
|
341 register int wid = 0;
|
|
342 register char fill = ' ';
|
|
343
|
|
344 c = *cp++;
|
|
345 if (c == '-') {
|
|
346 ljust++;
|
|
347 c = *cp++;
|
|
348 }
|
|
349 if (c == '0') {
|
|
350 fill = c;
|
|
351 c = *cp++;
|
|
352 }
|
|
353 while (isdigit(c)) {
|
|
354 wid = wid*10 + (c - '0');
|
|
355 c = *cp++;
|
|
356 }
|
|
357 if (c == '{') {
|
|
358 cp = do_name(cp, 0);
|
|
359 if (! infunction)
|
|
360 fp->f_type = wid? FT_COMPF : FT_COMP;
|
|
361 }
|
|
362 else if (c == '(') {
|
|
363 cp = do_func(cp);
|
|
364 if (! infunction) {
|
|
365 if (ftbl->flags & TFL_PUTS) {
|
|
366 LV( wid? FT_STRF : FT_STR, ftbl->extra);
|
|
367 }
|
|
368 else if (ftbl->flags & TFL_PUTN) {
|
|
369 LV( wid? FT_NUMF : FT_NUM, ftbl->extra);
|
|
370 }
|
|
371 }
|
|
372 }
|
|
373 else {
|
|
374 CERROR("component or function name expected");
|
|
375 }
|
|
376 if (ljust)
|
|
377 wid = -wid;
|
|
378 fp->f_width = wid;
|
|
379 fp->f_fill = fill;
|
|
380
|
|
381 return (cp);
|
|
382 }
|
|
383
|
|
384 static char *do_name(sp, preprocess)
|
|
385 char *sp;
|
|
386 int preprocess;
|
|
387 {
|
|
388 register char *cp = sp;
|
|
389 register int c;
|
|
390 register int i;
|
|
391 static int primed = 0;
|
|
392
|
|
393 while (isalnum(c = *cp++) || c == '-' || c == '_')
|
|
394 ;
|
|
395 if (c != '}') {
|
|
396 CERROR("'}' expected");
|
|
397 }
|
|
398 cp[-1] = '\0';
|
|
399 PUTCOMP(sp);
|
|
400 switch (preprocess) {
|
|
401
|
|
402 case FT_PARSEDATE:
|
|
403 if (cm->c_type & CT_ADDR) {
|
|
404 CERROR("component used as both date and address");
|
|
405 }
|
|
406 if (! (cm->c_type & CT_DATE)) {
|
|
407 cm->c_tws = (struct tws *)
|
|
408 calloc((unsigned) 1, sizeof *cm -> c_tws);
|
|
409 fp->f_type = preprocess;
|
|
410 PUTCOMP(sp);
|
|
411 cm->c_type |= CT_DATE;
|
|
412 }
|
|
413 break;
|
|
414
|
|
415 case FT_MYMBOX:
|
|
416 if (!primed) {
|
|
417 (void) ismymbox ((struct mailname *) 0);
|
|
418 primed++;
|
|
419 }
|
|
420 cm->c_type |= CT_MYMBOX;
|
|
421 /* fall through */
|
|
422 case FT_PARSEADDR:
|
|
423 if (cm->c_type & CT_DATE) {
|
|
424 CERROR("component used as both date and address");
|
|
425 }
|
|
426 if (! (cm->c_type & CT_ADDRPARSE)) {
|
|
427 cm->c_mn = &fmt_mnull;
|
|
428 fp->f_type = preprocess;
|
|
429 PUTCOMP(sp);
|
|
430 cm->c_type |= (CT_ADDR | CT_ADDRPARSE);
|
|
431 }
|
|
432 break;
|
|
433
|
|
434 case FT_FORMATADDR:
|
|
435 if (cm->c_type & CT_DATE) {
|
|
436 CERROR("component used as both date and address");
|
|
437 }
|
|
438 cm->c_type |= CT_ADDR;
|
|
439 break;
|
|
440 }
|
|
441 return (cp);
|
|
442 }
|
|
443
|
|
444 static char *do_func(sp)
|
|
445 char *sp;
|
|
446 {
|
|
447 register char *cp = sp;
|
|
448 register int c;
|
|
449 register struct ftable *t;
|
|
450 register int n;
|
|
451 int mflag; /* minus sign in NUM */
|
|
452
|
|
453 infunction++;
|
|
454
|
|
455 while (isalnum(c = *cp++))
|
|
456 ;
|
|
457 if (c != '(' && c != '{' && c != ' ' && c != ')') {
|
|
458 CERROR("'(', '{', ' ' or ')' expected");
|
|
459 }
|
|
460 cp[-1] = '\0';
|
|
461 if ((t = lookup (sp)) == 0) {
|
|
462 CERROR("unknown function");
|
|
463 }
|
|
464 if (isspace(c))
|
|
465 c = *cp++;
|
|
466
|
|
467 switch (t->type) {
|
|
468
|
|
469 case TF_COMP:
|
|
470 if (c != '{') {
|
|
471 CERROR("component name expected");
|
|
472 }
|
|
473 cp = do_name(cp, t->extra);
|
|
474 fp->f_type = t->f_type;
|
|
475 c = *cp++;
|
|
476 break;
|
|
477
|
|
478 case TF_NUM:
|
|
479 if (mflag = (c == '-'))
|
|
480 c = *cp++;
|
|
481 n = 0;
|
|
482 while (isdigit(c)) {
|
|
483 n = n*10 + (c - '0');
|
|
484 c = *cp++;
|
|
485 }
|
|
486 if (mflag)
|
|
487 n = (-n);
|
|
488 LV(t->f_type,n);
|
|
489 break;
|
|
490
|
|
491 case TF_STR:
|
|
492 sp = cp - 1;
|
|
493 while (c && c != ')')
|
|
494 c = *cp++;
|
|
495 cp[-1] = '\0';
|
|
496 LS(t->f_type,sp);
|
|
497 break;
|
|
498
|
|
499 case TF_NONE:
|
|
500 LV(t->f_type,t->extra);
|
|
501 break;
|
|
502
|
|
503 case TF_MYBOX:
|
|
504 LS(t->f_type, getusr());
|
|
505 break;
|
|
506
|
|
507 case TF_NOW:
|
|
508 LV(t->f_type, time((time_t *) 0));
|
|
509 break;
|
|
510
|
|
511 case TF_EXPR_SV:
|
|
512 LV(FT_SAVESTR, 0);
|
|
513 /* fall through */
|
|
514 case TF_EXPR:
|
|
515 *--cp = c;
|
|
516 cp = do_expr(cp, t->extra);
|
|
517 LV(t->f_type, 0);
|
|
518 c = *cp++;
|
|
519 ftbl = t;
|
|
520 break;
|
|
521
|
|
522 case TF_NOP:
|
|
523 *--cp = c;
|
|
524 cp = do_expr(cp, t->extra);
|
|
525 c = *cp++;
|
|
526 ftbl = t;
|
|
527 break;
|
|
528 }
|
|
529 if (c != ')') {
|
|
530 CERROR("')' expected");
|
|
531 }
|
|
532 --infunction;
|
|
533 return (cp);
|
|
534 }
|
|
535
|
|
536 static char *do_expr (sp, preprocess)
|
|
537 char *sp;
|
|
538 {
|
|
539 register char *cp = sp;
|
|
540 register int c;
|
|
541
|
|
542 if ((c = *cp++) == '{') {
|
|
543 cp = do_name (cp, preprocess);
|
|
544 fp->f_type = FT_LS_COMP;
|
|
545 } else if (c == '(') {
|
|
546 cp = do_func (cp);
|
|
547 } else if (c == ')') {
|
|
548 return (--cp);
|
|
549 } else if (c == '%' && *cp == '<') {
|
|
550 cp = do_if (cp+1);
|
|
551 } else {
|
|
552 CERROR ("'(', '{', '%<' or ')' expected");
|
|
553 }
|
|
554 return (cp);
|
|
555 }
|
|
556
|
|
557 static char *do_loop(sp)
|
|
558 register char *sp;
|
|
559 {
|
|
560 register char *cp = sp;
|
|
561 struct format *floop;
|
|
562
|
|
563 floop = next_fp;
|
|
564 cp = compile (cp);
|
|
565 if (*cp++ != ']')
|
|
566 CERROR ("']' expected");
|
|
567
|
|
568 LV(FT_DONE, 1); /* not yet done */
|
|
569 LV(FT_GOTO, 0);
|
|
570 fp->f_skip = floop - fp; /* skip backwards */
|
|
571
|
|
572 return cp;
|
|
573 }
|
|
574
|
|
575 static char *do_if(sp)
|
|
576 register char *sp;
|
|
577 {
|
|
578 register char *cp = sp;
|
|
579 register struct format *fexpr,
|
|
580 *fif = (struct format *)NULL;
|
|
581 register int c = '<';
|
|
582
|
|
583 for (;;) {
|
|
584 if (c == '<') { /* doing an IF */
|
|
585 if ((c = *cp++) == '{') /*}*/{
|
|
586 cp = do_name(cp, 0);
|
|
587 fp->f_type = FT_LS_COMP;
|
|
588 LV (FT_IF_S, 0);
|
|
589 }
|
|
590 else if (c == '(') {
|
|
591 cp = do_func(cp);
|
|
592 /* see if we can merge the load and the "if" */
|
|
593 if (ftbl->f_type >= IF_FUNCS)
|
|
594 fp->f_type = ftbl->extra;
|
|
595 else {
|
|
596 LV (FT_IF_V_NE, 0);
|
|
597 }
|
|
598 }
|
|
599 else {
|
|
600 CERROR("'(' or '{' expected"); /*}*/
|
|
601 }
|
|
602 }
|
|
603
|
|
604 fexpr = fp; /* loc of [ELS]IF */
|
|
605 cp = compile (cp); /* compile IF TRUE stmts */
|
|
606 if (fif)
|
|
607 fif->f_skip = next_fp - fif;
|
|
608
|
|
609 if ((c = *cp++) == '|') { /* the last ELSE */
|
|
610 LV(FT_GOTO, 0);
|
|
611 fif = fp; /* loc of GOTO */
|
|
612 fexpr->f_skip = next_fp - fexpr;
|
|
613
|
|
614 fexpr = (struct format *)NULL;/* no extra ENDIF */
|
|
615
|
|
616 cp = compile (cp); /* compile ELSE stmts */
|
|
617 fif->f_skip = next_fp - fif;
|
|
618 c = *cp++;
|
|
619 }
|
|
620 else if (c == '?') { /* another ELSIF */
|
|
621 LV(FT_GOTO, 0);
|
|
622 fif = fp; /* loc of GOTO */
|
|
623 fexpr->f_skip = next_fp - fexpr;
|
|
624
|
|
625 c = '<'; /* impersonate an IF */
|
|
626 continue;
|
|
627 }
|
|
628 break;
|
|
629 }
|
|
630
|
|
631 if (c != '>') {
|
|
632 CERROR("'>' expected.");
|
|
633 }
|
|
634
|
|
635 if (fexpr) /* IF ... [ELSIF ...] ENDIF */
|
|
636 fexpr->f_skip = next_fp - fexpr;
|
|
637
|
|
638 return (cp);
|
|
639 }
|