Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / sbr / RCS / fmtcompile.c,v
1 head    1.17;
2 access;
3 symbols;
4 locks
5         shettich:1.17; strict;
6 comment @ * @;
7
8
9 1.17
10 date    93.08.19.21.05.42;      author jromine; state Exp;
11 branches;
12 next    1.16;
13
14 1.16
15 date    93.06.12.06.46.16;      author jromine; state Exp;
16 branches;
17 next    1.15;
18
19 1.15
20 date    92.12.15.00.20.22;      author jromine; state Exp;
21 branches;
22 next    1.14;
23
24 1.14
25 date    92.10.26.22.45.35;      author jromine; state Exp;
26 branches;
27 next    1.13;
28
29 1.13
30 date    92.02.09.21.42.12;      author jromine; state Exp;
31 branches;
32 next    1.12;
33
34 1.12
35 date    92.02.09.07.09.49;      author jromine; state Exp;
36 branches;
37 next    1.11;
38
39 1.11
40 date    92.02.05.04.57.21;      author jromine; state Exp;
41 branches;
42 next    1.10;
43
44 1.10
45 date    92.01.23.23.10.58;      author jromine; state Exp;
46 branches;
47 next    1.9;
48
49 1.9
50 date    91.01.10.08.35.40;      author mh;      state Exp;
51 branches;
52 next    1.8;
53
54 1.8
55 date    91.01.09.22.33.06;      author mh;      state Exp;
56 branches;
57 next    1.7;
58
59 1.7
60 date    91.01.09.22.19.43;      author mh;      state Exp;
61 branches;
62 next    1.6;
63
64 1.6
65 date    91.01.09.16.31.16;      author mh;      state Exp;
66 branches;
67 next    1.5;
68
69 1.5
70 date    90.12.27.17.19.13;      author mh;      state Exp;
71 branches;
72 next    1.4;
73
74 1.4
75 date    90.04.05.15.32.23;      author sources; state Exp;
76 branches;
77 next    1.3;
78
79 1.3
80 date    90.04.05.14.49.56;      author sources; state Exp;
81 branches;
82 next    1.2;
83
84 1.2
85 date    90.02.21.15.51.02;      author sources; state Exp;
86 branches;
87 next    1.1;
88
89 1.1
90 date    90.02.21.15.46.42;      author sources; state Exp;
91 branches;
92 next    ;
93
94
95 desc
96 @@
97
98
99 1.17
100 log
101 @allow "_" in header field names
102 @
103 text
104 @/* fmtcompile.c - "compile" format strings for fmtscan */
105 #ifndef lint
106 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.16 1993/06/12 06:46:16 jromine Exp jromine $";
107 #endif  /* lint */
108
109 #include "../h/mh.h"
110 #include "../h/addrsbr.h"
111 #include "../h/formatsbr.h"
112 #include "../zotnet/tws.h"
113 #include "../h/fmtcompile.h"
114 #include <ctype.h>
115 #include <stdio.h>
116 #include <sys/types.h>
117 #include <sys/stat.h>
118
119 static struct format *formatvec;        /* array to hold formats */
120 static struct format *next_fp;          /* next free format slot */
121 static struct format *fp;               /* current format slot */
122 static struct comp *cm;                 /* most recent comp ref */
123 static struct ftable *ftbl;             /* most recent func ref */
124 static int ncomp;
125 static int infunction;                  /* function nesting cnt */
126
127 extern char *getusr();
128 extern struct mailname fmt_mnull;
129
130 struct ftable {
131     char        *name;          /* function name */
132     char        type;           /* argument type */
133 #define         TF_COMP 0           /* component expected */
134 #define         TF_NUM  1           /* number expected */
135 #define         TF_STR  2           /* string expected */
136 #define         TF_EXPR 3           /* component or func. expected */
137 #define         TF_NONE 4           /* no argument */
138 #define         TF_MYBOX 5          /* special - get current user's mbox */
139 #define         TF_NOW  6           /* special - get current unix time */
140 #define         TF_EXPR_SV 7        /* like expr but save current str reg */
141 #define         TF_NOP  8           /* like expr but no result */
142     char        f_type;         /* fmt type */
143     char        extra;          /* arg. type dependent extra info */
144     char        flags;
145 #define         TFL_PUTS  1         /* implicit putstr if top level */
146 #define         TFL_PUTN  2         /* implicit putnum if top level */
147 };
148
149 static struct ftable functable[] = {
150     "nonzero",  TF_EXPR,        FT_V_NE,        FT_IF_V_NE,     0,
151     "zero",     TF_EXPR,        FT_V_EQ,        FT_IF_V_EQ,     0,
152     "eq",       TF_NUM,         FT_V_EQ,        FT_IF_V_EQ,     0,
153     "ne",       TF_NUM,         FT_V_NE,        FT_IF_V_NE,     0,
154     "gt",       TF_NUM,         FT_V_GT,        FT_IF_V_GT,     0,
155     "null",     TF_EXPR,        FT_S_NULL,      FT_IF_S_NULL,   0,
156     "nonnull",  TF_EXPR,        FT_S_NONNULL,   FT_IF_S,        0,
157     "match",    TF_STR,         FT_V_MATCH,     FT_IF_MATCH,    0,
158     "amatch",   TF_STR,         FT_V_AMATCH,    FT_IF_AMATCH,   0,
159
160     "putstr",   TF_EXPR,        FT_STR,         0,              0,
161     "putstrf",  TF_EXPR,        FT_STRF,        0,              0,
162     "putnum",   TF_EXPR,        FT_NUM,         0,              0,
163     "putnumf",  TF_EXPR,        FT_NUMF,        0,              0,
164     "putaddr",  TF_STR,         FT_PUTADDR,     0,              0,
165     "void",     TF_NOP,         0,              0,              0,
166
167     "comp",     TF_COMP,        FT_LS_COMP,     0,              TFL_PUTS,
168     "lit",      TF_STR,         FT_LS_LIT,      0,              TFL_PUTS,
169     "getenv",   TF_STR,         FT_LS_GETENV,   0,              TFL_PUTS,
170     "profile",  TF_STR,         FT_LS_MFIND,    0,              TFL_PUTS,
171     "trim",     TF_EXPR,        FT_LS_TRIM,     0,              0,
172     "compval",  TF_COMP,        FT_LV_COMP,     0,              TFL_PUTN,
173     "compflag", TF_COMP,        FT_LV_COMPFLAG, 0,              TFL_PUTN,
174     "num",      TF_NUM,         FT_LV_LIT,      0,              TFL_PUTN,
175     "msg",      TF_NONE,        FT_LV_DAT,      0,              TFL_PUTN,
176     "cur",      TF_NONE,        FT_LV_DAT,      1,              TFL_PUTN,
177     "size",     TF_NONE,        FT_LV_DAT,      2,              TFL_PUTN,
178     "width",    TF_NONE,        FT_LV_DAT,      3,              TFL_PUTN,
179     "unseen",   TF_NONE,        FT_LV_DAT,      4,              TFL_PUTN,
180     "dat",      TF_NUM,         FT_LV_DAT,      0,              TFL_PUTN,
181     "strlen",   TF_NONE,        FT_LV_STRLEN,   0,              TFL_PUTN,
182     "me",       TF_MYBOX,       FT_LS_LIT,      0,              TFL_PUTS,
183     "plus",     TF_NUM,         FT_LV_PLUS_L,   0,              TFL_PUTN,
184     "minus",    TF_NUM,         FT_LV_MINUS_L,  0,              TFL_PUTN,
185     "divide",   TF_NUM,         FT_LV_DIVIDE_L, 0,              TFL_PUTN,
186     "modulo",   TF_NUM,         FT_LV_MODULO_L, 0,              TFL_PUTN,
187     "charleft", TF_NONE,        FT_LV_CHAR_LEFT, 0,             TFL_PUTN,
188     "timenow",  TF_NOW,         FT_LV_LIT,      0,              TFL_PUTN,
189
190     "month",    TF_COMP,        FT_LS_MONTH,    FT_PARSEDATE,   TFL_PUTS,
191     "lmonth",   TF_COMP,        FT_LS_LMONTH,   FT_PARSEDATE,   TFL_PUTS,
192     "tzone",    TF_COMP,        FT_LS_ZONE,     FT_PARSEDATE,   TFL_PUTS,
193     "day",      TF_COMP,        FT_LS_DAY,      FT_PARSEDATE,   TFL_PUTS,
194     "weekday",  TF_COMP,        FT_LS_WEEKDAY,  FT_PARSEDATE,   TFL_PUTS,
195     "tws",      TF_COMP,        FT_LS_822DATE,  FT_PARSEDATE,   TFL_PUTS,
196     "sec",      TF_COMP,        FT_LV_SEC,      FT_PARSEDATE,   TFL_PUTN,
197     "min",      TF_COMP,        FT_LV_MIN,      FT_PARSEDATE,   TFL_PUTN,
198     "hour",     TF_COMP,        FT_LV_HOUR,     FT_PARSEDATE,   TFL_PUTN,
199     "mday",     TF_COMP,        FT_LV_MDAY,     FT_PARSEDATE,   TFL_PUTN,
200     "mon",      TF_COMP,        FT_LV_MON,      FT_PARSEDATE,   TFL_PUTN,
201     "year",     TF_COMP,        FT_LV_YEAR,     FT_PARSEDATE,   TFL_PUTN,
202     "yday",     TF_COMP,        FT_LV_YDAY,     FT_PARSEDATE,   TFL_PUTN,
203     "wday",     TF_COMP,        FT_LV_WDAY,     FT_PARSEDATE,   TFL_PUTN,
204     "zone",     TF_COMP,        FT_LV_ZONE,     FT_PARSEDATE,   TFL_PUTN,
205     "clock",    TF_COMP,        FT_LV_CLOCK,    FT_PARSEDATE,   TFL_PUTN,
206     "rclock",   TF_COMP,        FT_LV_RCLOCK,   FT_PARSEDATE,   TFL_PUTN,
207     "sday",     TF_COMP,        FT_LV_DAYF,     FT_PARSEDATE,   TFL_PUTN,
208     "szone",    TF_COMP,        FT_LV_ZONEF,    FT_PARSEDATE,   TFL_PUTN,
209     "dst",      TF_COMP,        FT_LV_DST,      FT_PARSEDATE,   TFL_PUTN,
210     "pretty",   TF_COMP,        FT_LS_PRETTY,   FT_PARSEDATE,   TFL_PUTS,
211     "nodate",   TF_COMP,        FT_LV_COMPFLAG, FT_PARSEDATE,   TFL_PUTN,
212     "date2local", TF_COMP,      FT_LOCALDATE,   FT_PARSEDATE,   0,
213     "date2gmt", TF_COMP,        FT_GMTDATE,     FT_PARSEDATE,   0,
214
215     "pers",     TF_COMP,        FT_LS_PERS,     FT_PARSEADDR,   TFL_PUTS,
216     "mbox",     TF_COMP,        FT_LS_MBOX,     FT_PARSEADDR,   TFL_PUTS,
217     "host",     TF_COMP,        FT_LS_HOST,     FT_PARSEADDR,   TFL_PUTS,
218     "path",     TF_COMP,        FT_LS_PATH,     FT_PARSEADDR,   TFL_PUTS,
219     "gname",    TF_COMP,        FT_LS_GNAME,    FT_PARSEADDR,   TFL_PUTS,
220     "note",     TF_COMP,        FT_LS_NOTE,     FT_PARSEADDR,   TFL_PUTS,
221     "addr",     TF_COMP,        FT_LS_ADDR,     FT_PARSEADDR,   TFL_PUTS,
222     "proper",   TF_COMP,        FT_LS_822ADDR,  FT_PARSEADDR,   TFL_PUTS,
223     "type",     TF_COMP,        FT_LV_HOSTTYPE, FT_PARSEADDR,   TFL_PUTN,
224     "ingrp",    TF_COMP,        FT_LV_INGRPF,   FT_PARSEADDR,   TFL_PUTN,
225     "nohost",   TF_COMP,        FT_LV_NOHOSTF,  FT_PARSEADDR,   TFL_PUTN,
226     "formataddr", TF_EXPR_SV,   FT_FORMATADDR,  FT_FORMATADDR,  0,
227     "friendly", TF_COMP,        FT_LS_FRIENDLY, FT_PARSEADDR,   TFL_PUTS,
228
229     "mymbox",   TF_COMP,        FT_LV_COMPFLAG, FT_MYMBOX,      TFL_PUTN,
230     "addtoseq", TF_STR,         FT_ADDTOSEQ,    0,              0,
231
232     (char *)0,  0,              0,              0,              0    
233 };
234
235
236 long time ();
237
238 static struct ftable *lookup(name)
239     register char *name;
240 {
241     register struct ftable *t = functable;
242     register char *nm;
243     register char c = *name;
244
245     while (nm = t->name) {
246         if (*nm == c && strcmp (nm, name) == 0)
247             return (ftbl = t);
248
249         t++;
250     }
251     return (struct ftable *)0;
252 }
253
254
255 #define NEWCOMP(cm,name)\
256         cm = ((struct comp *)calloc(1, sizeof (struct comp)));\
257         cm->c_name = name; ncomp++;\
258         i = CHASH(name); cm->c_next = wantcomp[i]; wantcomp[i] = cm;
259
260 #define NEWFMT (next_fp++)
261 #define NEW(type,fill,wid)\
262         fp=NEWFMT; fp->f_type=(type); fp->f_fill=(fill); fp->f_width=(wid);
263
264 #define ADDC(name)\
265         FINDCOMP( cm, name );\
266         if ( ! cm ) {\
267             NEWCOMP(cm,name);\
268         }\
269         fp->f_comp = cm;
270
271 #define LV( type, value )       NEW(type,0,0); fp->f_value = (value);
272 #define LS( type, str )         NEW(type,0,0); fp->f_text = (str);
273 #define PUTCOMP( comp )         NEW(FT_COMP,0,0); ADDC(comp);
274 #define PUTLIT( str )           NEW(FT_LIT,0,0); fp->f_text = (str);
275 #define PUTC( c )               NEW(FT_CHAR,0,0); fp->f_char = (c);
276
277 static char *compile();
278 static char *do_spec();
279 static char *do_name();
280 static char *do_func();
281 static char *do_expr();
282 static char *do_if();
283 static char *do_loop();
284
285 static char *format_string;
286 static char *usr_fstring;       /* for CERROR */
287
288 #define CERROR(str) compile_error (str, cp)
289
290 static void
291 compile_error(str, cp)
292     char *str;
293     char *cp;
294 {
295     int errpos = cp - format_string;
296     int errctx = errpos > 20 ? 20 : errpos;
297     int i;
298
299     usr_fstring[errpos] = '\0';
300     for (i = errpos-errctx; i < errpos; i++)
301 #ifdef LOCALE
302         if (iscntrl(usr_fstring[i]))
303 #else
304         if (usr_fstring[i] < 32)
305 #endif
306             usr_fstring[i] = '_';
307     advise(NULLCP, "\"%s\": format compile error - %s",
308            &usr_fstring[errpos-errctx], str);
309     adios (NULLCP, "%*s", errctx+1, "^");
310 }
311
312 /*
313  * Compile format string "fstring" into format list "fmt".
314  * Return the number of header components found in the format
315  * string.
316  */
317 fmt_compile( fstring, fmt )
318     register char *fstring;
319     struct format **fmt;
320 {
321     register char *cp;
322     int i;
323
324     if (format_string)
325         (void) free (format_string);
326     format_string = getcpy (fstring);
327     usr_fstring = fstring;
328
329     /* init the component hash table. */
330     for (i = 0; i < sizeof(wantcomp)/sizeof(wantcomp[0]); i++)
331         wantcomp[i] = 0;
332
333     bzero ((char *) &fmt_mnull, sizeof fmt_mnull);
334
335     /* it takes at least 4 char to generate one format so we
336      * allocate a worst-case format array using 1/4 the length
337      * of the format string.  We actually need twice this much
338      * to handle both pre-processing (e.g., address parsing) and
339      * normal processing.
340      */
341     i = strlen(fstring)/2 + 1;
342     next_fp = formatvec = (struct format *)calloc ((unsigned) i,
343                                                    sizeof(struct format));
344     if (next_fp == NULL)
345         adios (NULLCP, "unable to allocate format storage");
346
347     ncomp = 0;
348     infunction = 0;
349
350     cp = compile(format_string);
351     if (*cp) {
352         CERROR("extra '%>', '%|' or '%?'");
353     }
354     LV(FT_DONE,0);              /* really done */
355     *fmt = formatvec;
356
357     return (ncomp);
358 }
359
360 static char *compile (sp)
361     register char *sp;
362 {
363     register char *cp = sp;
364     register int  c;
365
366     for (;;) {
367         sp = cp;
368         while ((c = *cp) && c != '%')
369             cp++;
370         *cp = 0;
371         switch (cp-sp) {
372         case 0:
373             break;
374         case 1:
375             PUTC(*sp);
376             break;
377         default:
378             PUTLIT(sp);
379             break;
380         }
381         if (c == 0)
382             return (cp);
383
384         switch (c = *++cp) {
385         case '%':
386             PUTC (*cp);
387             cp++;
388             break;
389
390         case '|':
391         case '>':
392         case '?':
393         case ']':
394             return (cp);
395
396         case '<':
397             cp = do_if(++cp);
398             break;
399
400         case '[':       /* ] */
401             cp = do_loop(++cp);
402             break;
403
404         case ';':       /* comment line */
405             cp++;
406             while ((c = *cp++) && c != '\n')
407                 continue;
408             break;
409
410         default:
411             cp = do_spec(cp);
412             break;
413         }
414     }
415 }
416
417
418 static char *do_spec(sp)
419     register char *sp;
420 {
421     register char *cp = sp;
422     register int c;
423 #ifndef lint
424     register int ljust = 0;
425 #endif  /* not lint */
426     register int wid = 0;
427     register char fill = ' ';
428
429     c = *cp++;
430     if (c == '-') {
431         ljust++;
432         c = *cp++;
433     }
434     if (c == '0') {
435         fill = c;
436         c = *cp++;
437     }
438     while (isdigit(c)) {
439         wid = wid*10 + (c - '0');
440         c = *cp++;
441     }
442     if (c == '{') {
443         cp = do_name(cp, 0);
444         if (! infunction)
445             fp->f_type = wid? FT_COMPF : FT_COMP;
446     }
447     else if (c == '(') {
448         cp = do_func(cp);
449         if (! infunction) {
450             if (ftbl->flags & TFL_PUTS) {
451                 LV( wid? FT_STRF : FT_STR, ftbl->extra);
452             }
453             else if (ftbl->flags & TFL_PUTN) {
454                 LV( wid? FT_NUMF : FT_NUM, ftbl->extra);
455             }
456         }
457     }
458     else {
459         CERROR("component or function name expected");
460     }
461     if (ljust)
462         wid = -wid;
463     fp->f_width = wid;
464     fp->f_fill = fill;
465
466     return (cp);
467 }
468
469 static char *do_name(sp, preprocess)
470     char *sp;
471     int  preprocess;
472 {
473     register char *cp = sp;
474     register int c;
475     register int i;
476     static int primed = 0;
477
478     while (isalnum(c = *cp++) || c == '-' || c == '_')
479         ;
480     if (c != '}') {
481         CERROR("'}' expected");
482     }
483     cp[-1] = '\0';
484     PUTCOMP(sp);
485     switch (preprocess) {
486
487     case FT_PARSEDATE:
488         if (cm->c_type & CT_ADDR) {
489             CERROR("component used as both date and address");
490         }
491         if (! (cm->c_type & CT_DATE)) {
492             cm->c_tws = (struct tws *)
493                                 calloc((unsigned) 1, sizeof *cm -> c_tws);
494             fp->f_type = preprocess;
495             PUTCOMP(sp);
496             cm->c_type |= CT_DATE;
497         }
498         break;
499
500     case FT_MYMBOX:
501         if (!primed) {
502             (void) ismymbox ((struct mailname *) 0);
503             primed++;
504         }
505         cm->c_type |= CT_MYMBOX;
506         /* fall through */
507     case FT_PARSEADDR:
508         if (cm->c_type & CT_DATE) {
509             CERROR("component used as both date and address");
510         }
511         if (! (cm->c_type & CT_ADDRPARSE)) {
512             cm->c_mn = &fmt_mnull;
513             fp->f_type = preprocess;
514             PUTCOMP(sp);
515             cm->c_type |= (CT_ADDR | CT_ADDRPARSE);
516         }
517         break;
518
519     case FT_FORMATADDR:
520         if (cm->c_type & CT_DATE) {
521             CERROR("component used as both date and address");
522         }
523         cm->c_type |= CT_ADDR;
524         break;
525     }
526     return (cp);
527 }
528
529 static char *do_func(sp)
530     char *sp;
531 {
532     register char *cp = sp;
533     register int c;
534     register struct ftable *t;
535     register int n;
536     int mflag;          /* minus sign in NUM */
537
538     infunction++;
539
540     while (isalnum(c = *cp++)) 
541         ;
542     if (c != '(' && c != '{' && c != ' ' && c != ')') {
543         CERROR("'(', '{', ' ' or ')' expected");
544     }
545     cp[-1] = '\0';
546     if ((t = lookup (sp)) == 0) {
547         CERROR("unknown function");
548     }
549     if (isspace(c))
550         c = *cp++;
551
552     switch (t->type) {
553
554     case TF_COMP:
555         if (c != '{') {
556             CERROR("component name expected");
557         }
558         cp = do_name(cp, t->extra);
559         fp->f_type = t->f_type;
560         c = *cp++;
561         break;
562
563     case TF_NUM:
564         if (mflag = (c == '-'))
565             c = *cp++;
566         n = 0;
567         while (isdigit(c)) {
568             n = n*10 + (c - '0');
569             c = *cp++;
570         }
571         if (mflag)
572             n = (-n);
573         LV(t->f_type,n);
574         break;
575
576     case TF_STR:
577         sp = cp - 1;
578         while (c && c != ')')
579             c = *cp++;
580         cp[-1] = '\0';
581         LS(t->f_type,sp);
582         break;
583
584     case TF_NONE:
585         LV(t->f_type,t->extra);
586         break;
587
588     case TF_MYBOX:
589         LS(t->f_type, getusr());
590         break;
591
592     case TF_NOW:
593         LV(t->f_type, time((long *) 0));
594         break;
595
596     case TF_EXPR_SV:
597         LV(FT_SAVESTR, 0);
598         /* fall through */
599     case TF_EXPR:
600         *--cp = c;
601         cp = do_expr(cp, t->extra);
602         LV(t->f_type, 0);
603         c = *cp++;
604         ftbl = t;
605         break;
606
607     case TF_NOP:
608         *--cp = c;
609         cp = do_expr(cp, t->extra);
610         c = *cp++;
611         ftbl = t;
612         break;
613     }
614     if (c != ')') {
615         CERROR("')' expected");
616     }
617     --infunction;
618     return (cp);
619 }
620
621 static char *do_expr (sp, preprocess)
622     char *sp;
623 {
624     register char *cp = sp;
625     register int  c;
626
627     if ((c = *cp++) == '{') {
628         cp = do_name (cp, preprocess);
629         fp->f_type = FT_LS_COMP;
630     } else if (c == '(') {
631         cp = do_func (cp);
632     } else if (c == ')') {
633         return (--cp);
634     } else if (c == '%' && *cp == '<') {
635         cp = do_if (cp+1);
636     } else {
637         CERROR ("'(', '{', '%<' or ')' expected");
638     }
639     return (cp);
640 }
641
642 static char *do_loop(sp)
643     register char *sp;
644 {
645     register char *cp = sp;
646     struct format *floop;
647
648     floop = next_fp;
649     cp = compile (cp);
650     if (*cp++ != ']')
651         CERROR ("']' expected");
652
653     LV(FT_DONE, 1);             /* not yet done */
654     LV(FT_GOTO, 0);
655     fp->f_skip = floop - fp;    /* skip backwards */
656
657     return cp;
658 }
659
660 static char *do_if(sp)
661     register char *sp;
662 {
663     register char *cp = sp;
664     register struct format *fexpr,
665                            *fif = (struct format *)NULL;
666     register int c = '<';
667
668     for (;;) {
669         if (c == '<') {                 /* doing an IF */
670             if ((c = *cp++) == '{') /*}*/{
671                 cp = do_name(cp, 0);
672                 fp->f_type = FT_LS_COMP;
673                 LV (FT_IF_S, 0);
674             }
675             else if (c == '(') {
676                 cp = do_func(cp);
677                 /* see if we can merge the load and the "if" */
678                 if (ftbl->f_type >= IF_FUNCS)
679                     fp->f_type = ftbl->extra;
680                 else {
681                     LV (FT_IF_V_NE, 0);
682                 }
683             }
684             else {
685                 CERROR("'(' or '{' expected");  /*}*/
686             }
687         }
688
689         fexpr = fp;                     /* loc of [ELS]IF */
690         cp = compile (cp);              /* compile IF TRUE stmts */
691         if (fif)
692             fif->f_skip = next_fp - fif;
693
694         if ((c = *cp++) == '|') {       /* the last ELSE */
695             LV(FT_GOTO, 0);
696             fif = fp;                   /* loc of GOTO */
697             fexpr->f_skip = next_fp - fexpr;
698
699             fexpr = (struct format *)NULL;/* no extra ENDIF */
700
701             cp = compile (cp);          /* compile ELSE stmts */
702             fif->f_skip = next_fp - fif;
703             c = *cp++;
704         }
705         else if (c == '?') {            /* another ELSIF */
706             LV(FT_GOTO, 0);
707             fif = fp;                   /* loc of GOTO */
708             fexpr->f_skip = next_fp - fexpr;
709
710             c = '<';                    /* impersonate an IF */
711             continue;
712         }
713         break;
714     }
715
716     if (c != '>') {
717         CERROR("'>' expected.");
718     }
719
720     if (fexpr)                          /* IF ... [ELSIF ...] ENDIF */
721         fexpr->f_skip = next_fp - fexpr;
722
723     return (cp);
724 }
725 @
726
727
728 1.16
729 log
730 @add %(profile xxx) to return m_find(xxx)
731 @
732 text
733 @d3 1
734 a3 1
735 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.15 1992/12/15 00:20:22 jromine Exp jromine $";
736 d375 1
737 a375 1
738     while (isalnum(c = *cp++) || c == '-') 
739 @
740
741
742 1.15
743 log
744 @endif sugar
745 @
746 text
747 @d3 1
748 a3 1
749 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.14 1992/10/26 22:45:35 jromine Exp jromine $";
750 d67 1
751 @
752
753
754 1.14
755 log
756 @LOCALE
757 @
758 text
759 @d3 2
760 a4 2
761 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.13 1992/02/09 21:42:12 jromine Exp jromine $";
762 #endif  lint
763 d321 1
764 a321 1
765 #endif  not lint
766 @
767
768
769 1.13
770 log
771 @allow comment lines with '%; ... \n'
772 @
773 text
774 @d3 1
775 a3 1
776 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.12 1992/02/09 07:09:49 jromine Exp jromine $";
777 d197 3
778 d201 1
779 @
780
781
782 1.12
783 log
784 @fix bug in %(zero)/%(nonzero) (actually, all TF_EXPR
785 formats which include a IF_V_... test
786 add %(modulo n)
787 put Van Jacobson changes under "options LBL"
788 @
789 text
790 @d3 1
791 a3 1
792 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.11 1992/02/05 04:57:21 jromine Exp $";
793 d294 6
794 @
795
796
797 1.11
798 log
799 @add unseen - uses dat[5]
800 @
801 text
802 @d3 1
803 a3 1
804 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.10 1992/01/23 23:10:58 jromine Exp jromine $";
805 d82 1
806 a125 1
807 #ifdef  VAN
808 a126 1
809 #endif
810 d422 1
811 d450 2
812 d457 2
813 d488 1
814 a488 1
815         LV(t->f_type, t->extra);
816 @
817
818
819 1.10
820 log
821 @new formatsbr changes under JLR
822 @
823 text
824 @d3 1
825 a3 1
826 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.9 1991/01/10 08:35:40 mh Exp jromine $";
827 d75 1
828 @
829
830
831 1.9
832 log
833 @cleanup
834 jlr
835 @
836 text
837 @d3 1
838 a3 1
839 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.8 91/01/09 22:33:06 mh Exp Locker: mh $";
840 d66 1
841 d179 1
842 d246 1
843 a246 1
844     NEW(FT_DONE,0,0);
845 d285 1
846 d292 4
847 d521 18
848 @
849
850
851 1.8
852 log
853 @use '%?' as ELSIF
854 jlr
855 @
856 text
857 @d3 1
858 a3 1
859 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.7 91/01/09 22:19:43 mh Exp Locker: mh $";
860 d520 2
861 a521 1
862     register struct format *fexpr, *fif = (struct format *)NULL;
863 d525 1
864 a525 1
865         if (c == '<') {
866 d550 1
867 a550 1
868         if ((c = *cp++) == '|') {       /* another ELSE/ELSIF */
869 d553 1
870 a553 1
871             fexpr->f_skip = next_fp - fexpr;    /* next stmt */
872 d555 1
873 a555 1
874             fexpr = (struct format *)NULL;
875 d557 1
876 a557 1
877             cp = compile (cp);  /* compile ELSE stmts */
878 d564 1
879 a564 1
880             fexpr->f_skip = next_fp - fexpr;    /* next stmt */
881 d566 1
882 a566 1
883             c = '<';                    /* impresonate an IF */
884 d576 1
885 a576 1
886     if (fexpr)
887 @
888
889
890 1.7
891 log
892 @jlr
893 @
894 text
895 @d3 1
896 a3 1
897 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.6 91/01/09 16:31:16 mh Exp Locker: mh $";
898 d242 1
899 a242 1
900         CERROR("extra '%>' or '%|'");
901 d282 1
902 a553 6
903             if ((c = *cp) == '<') {
904                 cp++;
905                 continue;
906             }
907             else if (c == '\\')         /* allow quoted '<' chars */
908                 cp++;
909 d559 8
910 @
911
912
913 1.6
914 log
915 @allow "ELSEIF" with "%|<"
916 jlr
917 @
918 text
919 @d3 1
920 a3 1
921 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.5 90/12/27 17:19:13 mh Exp Locker: mh $";
922 d557 2
923 @
924
925
926 1.5
927 log
928 @add "addr" address format.
929 jlr
930 @
931 text
932 @d3 1
933 a3 1
934 static char ident[] = "@@(#)$Id: fmtcompile.c,v 1.4 90/04/05 15:32:23 sources Exp Locker: mh $";
935 d519 2
936 a520 2
937     register struct format *fexpr, *fif, *felse;
938     register int c;
939 d522 19
940 a540 12
941     if ((c = *cp++) == '{') {
942         cp = do_name(cp, 0);
943         fp->f_type = FT_LS_COMP;
944         LV (FT_IF_S, 0);
945     }
946     else if (c == '(') {
947         cp = do_func(cp);
948         /* see if we can merge the load and the "if" */
949         if (ftbl->f_type >= IF_FUNCS)
950             fp->f_type = ftbl->extra;
951         else {
952             LV (FT_IF_V_NE, 0);
953 d542 22
954 a564 15
955     else  {
956         CERROR("'(' or '{' expected");
957     }
958     fexpr = fp;
959     cp = compile (cp);
960     if ((c = *cp++) == '|') {
961         LV(FT_GOTO, 0);
962         fif = fp;
963         felse = next_fp;
964         cp = compile(cp);
965         fif->f_skip = next_fp - fif;
966         c = *cp++;
967     }
968     else
969         felse = next_fp;
970 d569 3
971 a571 1
972     fexpr->f_skip = felse - fexpr;
973 @
974
975
976 1.4
977 log
978 @add ID
979 @
980 text
981 @d3 1
982 a3 1
983 static char ident[] = "@@(#)$Id:$";
984 d114 1
985 @
986
987
988 1.3
989 log
990 @add ID
991 @
992 text
993 @d3 1
994 a3 1
995 static char ident[] = "$Id:";
996 @
997
998
999 1.2
1000 log
1001 @Fixes from Van Jacobson
1002 @
1003 text
1004 @d2 3
1005 @
1006
1007
1008 1.1
1009 log
1010 @Initial revision
1011 @
1012 text
1013 @d63 1
1014 d76 1
1015 d98 2
1016 a99 1
1017     "dst",      TF_COMP,        FT_LV_TZONEF,   FT_PARSEDATE,   TFL_PUTN,
1018 d102 2
1019 d119 3
1020 d180 2
1021 a181 1
1022 static compile_error (str, cp)
1023 d305 1
1024 a305 3
1025 #ifndef lint
1026         ljust++;                /* should do something with this */
1027 #endif  not lint
1028 d335 2
1029 @