Annotation of 43BSD/contrib/mh/sbr/fmtcompile.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.