Annotation of coherent/d/bin/m4.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: #include <ctype.h>
                      3: 
                      4: #ifdef MSDOS
                      5: #define        TMPFILE "m4%dXXX"
                      6: #define        TMPMIN  2               /* minimum temp file length */
                      7: #else
                      8: #define        TMPFILE "/tmp/m4%dxxxxxx"
                      9: #define        TMPMIN  6
                     10: #endif
                     11: 
                     12: #define        isletter(c)             (isalpha(c)||c=='_')
                     13: #define        BQUOTE  '`'
                     14: #define        EQUOTE  '\''
                     15: #define        HASHSZ  199
                     16: #define        STRBLK  16              /* block size for dynamic string storage */
                     17: #if STRBLK < 12
                     18:                                   need room for decimal rep of long int
                     19: #endif
                     20: 
                     21: enum   {FUNC, MACD, DSKF, MSTR};
                     22: enum   {EX, MY, DV, MD, AD, SB, EQ, NE, LE, GE, LT, GT, AN, OR, RP, NL};
                     23: 
                     24: typedef        struct {                /* for storing variable-length strings */
                     25:        int     s_refc;         /* references--when zero space is freed */
                     26:        int     s_hash;         /* raw hash value (sum of chars in body) */
                     27:        char    *s_body;        /* start of contents */
                     28:        char    *s_next;        /* end of contents */
                     29:        char    *s_last;        /* end of storage */
                     30: } STRING;
                     31: 
                     32: typedef        union   ifr {                   /* input-source stack frame */
                     33:        struct  {
                     34:                struct  ifr *i_back;
                     35:                char    i_cbuf;         /* unget buffer for lookahead */
                     36:                int     i_type;         /* if type is MSTRing */
                     37:                STRING  *i_pstr;
                     38:                char    *i_pchr;        /* next char */
                     39:        } ifb;
                     40:        struct  {
                     41:                struct  ifr *i_back;
                     42:                char    i_cbuf;
                     43:                int     i_type;         /* if type is DSKFile */
                     44:                FILE    *i_fp;
                     45:        } ifdk;
                     46: } IFRAME;
                     47: 
                     48: typedef        struct  fstk {                  /* file information stack frame */
                     49:        struct  fstk *f_back;
                     50:        STRING  *f_name;                /* pointer to name (NULL if stdin) */
                     51:        int     f_flag;                 /* flag = 0 until EOF is reached */
                     52:        int     f_line;                 /* line counter */
                     53: } FFRAME;
                     54: 
                     55: typedef        struct  ofr {                   /* argument collection stack frame */
                     56:        struct  ofr *o_back;
                     57:        STRING  *o_pstr;
                     58: } OFRAME;
                     59: 
                     60: typedef        struct  ent {                   /* symbol table entry */
                     61:        struct  ent *e_next;
                     62:        int     e_type;                 /* FUNC or MACD */
                     63:        union {
                     64:                int     (*e_pfun)();
                     65:                STRING  *e_pstr;
                     66:        } e_at;
                     67:        STRING  *e_name;
                     68: } ENTRY;
                     69: 
                     70: /*
                     71:  * built in functions
                     72:  */
                     73: extern int     mchangequote(), mdecr(), mdefine(), mdivert(), mdivnum(), mdnl(),
                     74:        mdumpdef(), merrprint(), meval(), mifdef(), mifelse(),
                     75:        minclude(), mincr(), mindex(), mlen(), mmaketemp(), msinclude(),
                     76:        msubstr(), msyscmd(), mtranslit(), mundefine(), mundivert();
                     77:        
                     78: /*
                     79:  * output file info
                     80:  */
                     81: struct {
                     82:        char    *name;
                     83:        FILE    *fp;
                     84: } outfile[10] = {{ NULL, stdout }};
                     85: 
                     86: /*
                     87:  * op table for eval
                     88:  */
                     89: struct opdata {
                     90:        int     optype;
                     91:        char    keychar;
                     92:        char    secchar;
                     93:        int     prec;
                     94: } optable[] = {
                     95: #define        SI      8       /* precedence of unary + and - */
                     96:        EX, '^', '\0', 7,       EX, '*', '*', 7,
                     97:        MY, '*', '\0', 6,       DV, '/', '\0', 6,       MD, '%', '\0', 6,
                     98:        AD, '+', '\0', 5,       SB, '-', '\0', 5,
                     99:        EQ, '=', '=', 4,        GE, '>', '=', 4,        GT, '>', '\0', 4,
                    100:        NE, '!', '=', 4,        LE, '<', '=', 4,        LT, '<', '\0', 4,
                    101: #define        NT      3       /* precedence of unary ! */
                    102:        AN, '&', '&', 2,        AN, '&', '\0', 2,
                    103:        OR, '|', '|', 1,        OR, '|', '\0', 1,
                    104:        RP, ')', '\0', 10,      NL, '\0', '\0', 0
                    105: #define        LP      0       /* precedence of open paren */
                    106: };
                    107: 
                    108: ENTRY  *e_root[HASHSZ];        /* pointers to symbol table hash buckets */
                    109: OFRAME *ostkptr;               /* output stack pointer */
                    110: IFRAME *istkptr;               /* input stack pointer */
                    111: FFRAME *fstkptr;               /* file info stack pointer */
                    112: FILE   *offp = stdout;         /* current output file pointer */
                    113: int    ofnum;                  /* current diversion number */
                    114: int    lstdchr = '\n';         /* last char from stdin */
                    115: int    single;                 /* single argument flag */
                    116: int    dnlflag;                /* delete to newline flag */
                    117: 
                    118: char   bqt = BQUOTE;
                    119: char   eqt = EQUOTE;
                    120: extern char    *alloc();
                    121: STRING *makestr();
                    122: 
                    123: main(argc, argv)
                    124: int argc;
                    125: char *argv[];
                    126: {
                    127: #ifdef MSDOS
                    128:        msdoscvt("m4", &argc, &argv);
                    129: #endif
                    130:        buildin("changequote", mchangequote);
                    131:        buildin("decr", mdecr);
                    132:        buildin("define", mdefine);
                    133:        buildin("divert", mdivert);
                    134:        buildin("divnum", mdivnum);
                    135:        buildin("dnl", mdnl);
                    136:        buildin("dumpdef", mdumpdef);
                    137:        buildin("errprint", merrprint);
                    138:        buildin("eval", meval);
                    139:        buildin("ifdef", mifdef);
                    140:        buildin("ifelse", mifelse);
                    141:        buildin("include", minclude);
                    142:        buildin("incr", mincr);
                    143:        buildin("index", mindex);
                    144:        buildin("len", mlen);
                    145:        buildin("maketemp", mmaketemp);
                    146:        buildin("sinclude", msinclude);
                    147:        buildin("substr", msubstr);
                    148:        buildin("syscmd", msyscmd);
                    149:        buildin("translit", mtranslit);
                    150:        buildin("undefine", mundefine);
                    151:        buildin("undivert", mundivert);
                    152: 
                    153:        single = (argc == 2);
                    154:        if (argc > 1) {
                    155:                while (--argc)
                    156:                        if (pushfile(*++argv))
                    157:                                process(0);
                    158:                        else
                    159:                                errorp(0, "cannot open %s", *argv);
                    160:        } else {
                    161:                pushfile("-");
                    162:                process(0);
                    163:        }
                    164:        mdivert(NULL);
                    165:        mundivert(NULL);
                    166:        exit(0);
                    167: }
                    168: 
                    169: process(pct)
                    170: int pct;
                    171: {
                    172:        char lc = '\0';
                    173:        register int c, qct = 0;
                    174:        int i;
                    175:        STRING  *a[10];
                    176:        register STRING *b;
                    177:        ENTRY *e, *find();
                    178: 
                    179:        for (c=nxch(); pct && isspace(c); c=nxch())
                    180:                ;
                    181:        while (c != '\0') {
                    182:                if (qct)
                    183:                        if (c == eqt) {
                    184:                                if (--qct)
                    185:                                        outputc(c);
                    186:                        } else {
                    187:                                if (c == bqt)
                    188:                                        ++qct;
                    189:                                outputc(c);
                    190:                        }
                    191:                else if (c == bqt)
                    192:                        ++qct;
                    193:                else if (c==')' && pct && !--pct || c==',' && pct==1)
                    194:                        return (c);
                    195:                else if (isletter(c) && !isletter(lc) && !isdigit(lc)) {
                    196:                        b = makestr();
                    197:                        do {
                    198:                                appendstr(b, c);
                    199:                                lc = c;
                    200:                                c = nxch();
                    201:                        } while (isletter(c) || isdigit(c));
                    202:                        if ((e=find(b)) == NULL) {
                    203:                                outputs(b->s_body);
                    204:                                decstr(b);
                    205:                                continue;
                    206:                        }
                    207:                        for (i=9; i; a[i--]=NULL)
                    208:                                ;
                    209:                        a[0] = b;
                    210:                        if (c != '(') {
                    211:                                istkptr->i_cbuf = c;
                    212:                                if (c=='\n' && istkptr->i_type==DSKF)
                    213:                                        if (fstkptr->f_flag)
                    214:                                                --fstkptr->f_back->f_line;
                    215:                                        else
                    216:                                                --fstkptr->f_line;
                    217:                        } else do {
                    218:                                pushout(b=makestr());
                    219:                                c = process(1);
                    220:                                if (i++<9 && strlen(b->s_body))
                    221:                                        a[i] = b;
                    222:                                else
                    223:                                        decstr(b);
                    224:                                popout();
                    225:                        } while (c != ')');
                    226:                        if (e->e_type == MACD)
                    227:                                macro(e->e_at.e_pstr, a);
                    228:                        else
                    229:                                (*e->e_at.e_pfun)(a);
                    230:                        for (i = 0; i < 10; i++)
                    231:                                decstr(a[i]);
                    232:                        c = '\0';
                    233:                } else {
                    234:                        if (c=='(' && pct)
                    235:                                ++pct;
                    236:                        outputc(c);
                    237:                }
                    238:                lc = c;
                    239:                c = nxch();
                    240:        }
                    241:        if (pct)
                    242:                errorp(1, "unexpected EOF");
                    243:        return (c);
                    244: }
                    245: 
                    246: macro(ps, pps)
                    247: STRING *ps, **pps;
                    248: {
                    249:        STRING *x;
                    250:        register char *b, *v;
                    251: 
                    252:        x = makestr();
                    253:        b = ps->s_body;
                    254:        while (*b) {
                    255:                if (*b != '$')
                    256:                        appendstr(x, *b++);
                    257:                else if (!isdigit(*++b))
                    258:                        appendstr(x, '$');
                    259:                else if (ps = pps[*b++ - '0'])
                    260:                        for (v = ps->s_body; *v; v++)
                    261:                                appendstr(x, *v);
                    262:        }
                    263:        pushstr(x);
                    264:        decstr(x);
                    265: }
                    266: 
                    267: pushfile(s)
                    268: char *s;
                    269: {
                    270:        FILE *fp, *fopen();
                    271:        register STRING *a = NULL;
                    272:        register FFRAME *ftemp = fstkptr;
                    273:        char c;
                    274: 
                    275:        if (ftemp!=NULL && ftemp->f_flag) {
                    276:                decstr(ftemp->f_name);
                    277:                fstkptr = ftemp->f_back;
                    278:                free(ftemp);
                    279:        }
                    280:        if ( strcmp(s, "-") == 0 )
                    281:                fp = stdin;
                    282:        else if ( (fp = fopen(s, "r")) == NULL )
                    283:                return (0);
                    284:        pushinp(DSKF);
                    285:        istkptr->i_fp = fp;
                    286:        ftemp = (FFRAME *)alloc(sizeof(FFRAME));
                    287:        ftemp->f_back = fstkptr;
                    288:        ftemp->f_line = 1;
                    289:        ftemp->f_flag = 0;
                    290:        if (fp!=stdin && !(fstkptr==NULL && single)) {
                    291:                a = makestr();
                    292:                while (c = *s++)
                    293:                        appendstr(a, c);
                    294:        }
                    295:        ftemp->f_name = a;
                    296:        fstkptr = ftemp;
                    297:        return (1);
                    298: }
                    299: 
                    300: pushstr(a)
                    301: STRING *a;
                    302: {
                    303:        if (a==NULL || *a->s_body=='\0')
                    304:                return;
                    305:        pushinp(MSTR);
                    306:        istkptr->i_pstr = a;
                    307:        istkptr->i_pchr = a->s_body;
                    308:        ++a->s_refc;
                    309: }
                    310: 
                    311: pushnum(x)
                    312: long x;
                    313: {
                    314:        register STRING *a;
                    315: 
                    316:        a = makestr();
                    317:        sprintf(a->s_body, "%ld", x);
                    318:        pushstr(a);
                    319:        decstr(a);
                    320: }
                    321: 
                    322: pushinp(t)
                    323: char t;
                    324: {
                    325:        IFRAME *itemp;
                    326: 
                    327:        itemp = istkptr;
                    328:        istkptr = (IFRAME *)alloc(sizeof(IFRAME));
                    329:        istkptr->i_back = itemp;
                    330:        istkptr->i_type = t;
                    331:        istkptr->i_cbuf = '\0';
                    332: }
                    333: 
                    334: popinp()
                    335: {
                    336:        IFRAME *itemp;
                    337: 
                    338:        itemp = istkptr;
                    339:        switch (istkptr->i_type) {
                    340:        case MSTR:
                    341:                decstr(istkptr->i_pstr);
                    342:                break;
                    343:        case DSKF:
                    344:                if (istkptr->i_fp != stdin)
                    345:                        fclose(istkptr->i_fp);
                    346:                fstkptr->f_flag = 1;
                    347:                break;
                    348:        }
                    349:        istkptr = istkptr->i_back;
                    350:        free(itemp);
                    351:        return (istkptr != NULL);
                    352: }
                    353: 
                    354: pushout(b)
                    355: STRING *b;
                    356: {
                    357:        OFRAME *otemp;
                    358: 
                    359:        otemp = (OFRAME *)alloc(sizeof(OFRAME));
                    360:        otemp->o_back = ostkptr;
                    361:        otemp->o_pstr = b;
                    362:        ostkptr = otemp;
                    363:        ++b->s_refc;
                    364: }
                    365: 
                    366: popout()
                    367: {
                    368:        OFRAME *otemp;
                    369: 
                    370:        otemp = ostkptr;
                    371:        ostkptr = ostkptr->o_back;
                    372:        decstr(otemp->o_pstr);
                    373:        free(otemp);
                    374: }
                    375: 
                    376: nxch()
                    377: {
                    378:        register int c;
                    379:        FFRAME *ftemp;
                    380: 
                    381:        if (istkptr == NULL)
                    382:                return ('\0');
                    383:        if ((ftemp = fstkptr)->f_flag) {
                    384:                decstr(ftemp->f_name);
                    385:                fstkptr = ftemp->f_back;
                    386:                free(ftemp);
                    387:        }
                    388:        switch (istkptr->i_type) {
                    389:        case DSKF:
                    390:                if (c=istkptr->i_cbuf)
                    391:                        istkptr->i_cbuf = '\0';
                    392:                else
                    393:                        c = getc(istkptr->i_fp);
                    394:                if (istkptr->i_fp == stdin)
                    395:                        lstdchr = c;
                    396:                if (c == EOF)
                    397:                        c = '\0';
                    398:                else if (c == '\n')
                    399:                        if (fstkptr->f_flag)
                    400:                                ++fstkptr->f_back->f_line;
                    401:                        else
                    402:                                ++fstkptr->f_line;
                    403:                break;
                    404:        case MSTR:
                    405:                if (c=istkptr->i_cbuf)
                    406:                        istkptr->i_cbuf = '\0';
                    407:                else
                    408:                        c = *istkptr->i_pchr++;
                    409:                break;
                    410:        }
                    411:        if (c == '\0')
                    412:                return (popinp()? nxch() : c);
                    413:        else if (!dnlflag)
                    414:                return (c);
                    415:        if (c == '\n')
                    416:                dnlflag = 0;
                    417:        return (nxch());
                    418: }
                    419: 
                    420: outputc(c)
                    421: char c;
                    422: {
                    423:        if (ostkptr != NULL)
                    424:                appendstr(ostkptr->o_pstr, c);
                    425:        else
                    426:                outc(c);
                    427: }
                    428: 
                    429: outc(c)
                    430: char c;
                    431: {
                    432:        if (offp != NULL)
                    433:                putc(c, offp);
                    434: }
                    435: 
                    436: 
                    437: STRING *
                    438: makestr()
                    439: {
                    440:        register STRING *a;
                    441: 
                    442:        a = (STRING *)alloc(sizeof(STRING));
                    443:        a->s_body = a->s_next = (STRING *)alloc(STRBLK);
                    444:        a->s_last = a->s_body + STRBLK - 1;
                    445:        a->s_refc = 1;
                    446:        a->s_hash = 0;
                    447:        *a->s_next = '\0';
                    448:        return (a);
                    449: }
                    450: 
                    451: appendstr(a, c)
                    452: STRING *a;
                    453: char c;
                    454: {
                    455:        register char *r, *s, *t;
                    456:        int size;
                    457: 
                    458:        if (a->s_next < a->s_last) {
                    459:                *a->s_next++ = c;
                    460:                *a->s_next = '\0';
                    461:        } else {
                    462:                r = s = alloc(size = a->s_last - (t = a->s_body) + 1 + STRBLK);
                    463:                while (*s++ = *t++)
                    464:                        ;
                    465:                *(a->s_next = s) = '\0';
                    466:                *--s = c;
                    467:                free(a->s_body);
                    468:                a->s_last = (a->s_body = r) + size - 1;
                    469:        }
                    470:        a->s_hash += c;
                    471: }
                    472: 
                    473: decstr(a)
                    474: STRING *a;
                    475: {
                    476:        if (a == NULL)
                    477:                return;
                    478:        if (--a->s_refc)
                    479:                return;
                    480:        free(a->s_body);
                    481:        free(a);
                    482: }
                    483: 
                    484: cmpstr(a, b)
                    485: STRING *a, *b;
                    486: {
                    487:        if (a==NULL && b==NULL)
                    488:                return (1);
                    489:        if (a==NULL && b!=NULL || a!=NULL && b==NULL)
                    490:                return (0);
                    491:        return (!strcmp(a->s_body, b->s_body));
                    492: }
                    493: 
                    494: outputs(s)
                    495: char *s;
                    496: {
                    497:        register char *t, c;
                    498: 
                    499:        for (t = s; c = *t++; outputc(c))
                    500:                ;
                    501: }
                    502: 
                    503: ENTRY  *
                    504: find(a)
                    505: STRING *a;
                    506: {
                    507:        register ENTRY *e;
                    508:        register int hash;
                    509: 
                    510:        hash = a->s_hash;
                    511:        for (e = e_root[hash % HASHSZ]; e != NULL; e = e->e_next)
                    512:                if (e->e_name->s_hash == hash
                    513:                &&  strcmp(e->e_name->s_body, a->s_body) == 0)
                    514:                        return (e);
                    515:        return (NULL);
                    516: }
                    517: 
                    518: buildin(s, f)
                    519: char *s;
                    520: int (*f)();
                    521: {
                    522:        STRING *a;
                    523:        register int hash;
                    524:        register ENTRY *e;
                    525: 
                    526:        a = makestr();
                    527:        while (*s)
                    528:                appendstr(a, *s++);
                    529:        hash = a->s_hash % HASHSZ;
                    530:        e = (ENTRY *)alloc(sizeof(ENTRY));
                    531:        e->e_next = e_root[hash];
                    532:        e->e_type = FUNC;
                    533:        e->e_at.e_pfun = f;
                    534:        e->e_name = a;
                    535:        e_root[hash] = e;
                    536: }
                    537: 
                    538: char   *
                    539: alloc(n)
                    540: int n;
                    541: {
                    542:        char *x;
                    543: 
                    544:        if ((x=malloc(n)) != NULL)
                    545:                return(x);
                    546:        errorp(1, "out of space");
                    547: }
                    548: 
                    549: /* VARARGS */
                    550: errorp(f, x)
                    551: int f;
                    552: {
                    553:        fprintf(stderr, "m4: ");
                    554:        if (fstkptr != NULL) {
                    555:                if (fstkptr->f_name != NULL)
                    556:                        fprintf(stderr, "%s: ", fstkptr->f_name->s_body);
                    557:                fprintf(stderr, "%d: ", fstkptr->f_line);
                    558:        }
                    559:        fprintf(stderr, "%r", &x);
                    560:        putc('\n', stderr);
                    561:        if (f) {
                    562:                while (lstdchr!=EOF && lstdchr!='\n')
                    563:                        lstdchr = getchar();
                    564:                exit(1);
                    565:        }
                    566: }
                    567: 
                    568: mchangequote(pps)
                    569: STRING **pps;
                    570: {
                    571:        bqt = pps[1]? *pps[1]->s_body : BQUOTE;
                    572:        eqt = pps[2]? *pps[2]->s_body : EQUOTE;
                    573: }
                    574: 
                    575: mdefine(pps)
                    576: STRING **pps;
                    577: {
                    578:        ENTRY *find();
                    579:        register ENTRY *e;
                    580:        register char *s;
                    581:        register int hash;
                    582:        int c;
                    583:        static char illmac[] = "illegal macro name: %s";
                    584: 
                    585:        if (pps[1]==NULL || !isletter(*pps[1]->s_body)) {
                    586:                errorp(0, illmac, pps[1]!=NULL? pps[1]->s_body : NULL);
                    587:                return;
                    588:        }
                    589:        s = pps[1]->s_body + 1;
                    590:        while (c = *s++)
                    591:                if (!(isletter(c)||isdigit(c))) {
                    592:                        errorp(0, illmac, pps[1]->s_body);
                    593:                        return;
                    594:                }
                    595:        if (e = find(pps[1])) {
                    596:                if (e->e_type == MACD)
                    597:                        decstr(e->e_at.e_pstr);
                    598:        } else {
                    599:                e = (ENTRY *)alloc(sizeof(ENTRY));
                    600:                e->e_next = e_root[hash = pps[1]->s_hash % HASHSZ];
                    601:                e->e_name = pps[1];
                    602:                ++pps[1]->s_refc;
                    603:                e_root[hash] = e;
                    604:        }
                    605:        e->e_type = MACD;
                    606:        if (pps[2]) {
                    607:                e->e_at.e_pstr = pps[2];
                    608:                ++pps[2]->s_refc;
                    609:        } else
                    610:                e->e_at.e_pstr = makestr();
                    611: }
                    612: 
                    613: mdivert(pps)
                    614: STRING **pps;
                    615: {
                    616:        char *fn;
                    617: 
                    618:        if (pps == NULL)
                    619:                ofnum = 0;
                    620:        else
                    621:                ofnum = (pps[1] != NULL)? atoi(pps[1]->s_body) : 0;
                    622:        if (ofnum>0 && ofnum<=9) {
                    623:                if (outfile[ofnum].fp == NULL) {
                    624:                        outfile[ofnum].name = fn = alloc(15);
                    625:                        sprintf(fn, TMPFILE, ofnum);
                    626:                        mktemp(fn);
                    627:                        if ((outfile[ofnum].fp=fopen(fn,"w"))==NULL)
                    628:                                errorp(1, "m4: /tmp open error\n");
                    629:                }
                    630:        }
                    631:        if (ofnum>=0 && ofnum<=9)
                    632:                offp = outfile[ofnum].fp;
                    633:        else
                    634:                offp = NULL;
                    635: }
                    636: 
                    637: mdivnum()
                    638: {
                    639:        pushnum((long)ofnum);
                    640: }
                    641: 
                    642: mdnl()
                    643: {
                    644:        dnlflag = 1;
                    645: }
                    646: 
                    647: mdumpdef(pps)
                    648: STRING **pps;
                    649: {
                    650:        ENTRY *find();
                    651:        register ENTRY *e;
                    652:        register int i, f = 0;
                    653:        int hash;
                    654: 
                    655:        for (i = 1; i <= 9; ++i)
                    656:                if (pps[i] != NULL) {
                    657:                        if (e=find(pps[i]))
                    658:                                outdef(e);
                    659:                        f = 1;
                    660:                }
                    661:        if (!f)
                    662:                for (hash = 0; hash < HASHSZ; ++hash)
                    663:                        for (e = e_root[hash]; e; e = e->e_next) {
                    664:                                outputc(bqt);
                    665:                                outputs(e->e_name->s_body);
                    666:                                outputc(eqt);
                    667:                                outputc('\t');
                    668:                                outdef(e);
                    669:                                outputc('\n');
                    670:                        }
                    671: }
                    672: 
                    673: outdef(e)
                    674: ENTRY *e;
                    675: {
                    676:        if (e->e_type == MACD) {
                    677:                outputc(bqt);
                    678:                outputs(e->e_at.e_pstr->s_body);
                    679:                outputc(eqt);
                    680:        }
                    681: }
                    682: 
                    683: merrprint(pps)
                    684: STRING **pps;
                    685: {
                    686:        register int i;
                    687: 
                    688:        for (i=1; i<=9; i++)
                    689:                if (pps[i])
                    690:                        fprintf(stderr, pps[i]->s_body);
                    691: }
                    692: 
                    693: meval(pps)
                    694: STRING **pps;
                    695: {
                    696:        long calc();
                    697:        char *s;
                    698: 
                    699:        if (pps[1] == NULL)
                    700:                pushnum((long)0);
                    701:        else {
                    702:                s = pps[1]->s_body;
                    703:                pushnum(calc(0, &s));
                    704:        }
                    705: }
                    706: 
                    707: long
                    708: calc(pr, ps)
                    709: int pr;
                    710: char **ps;
                    711: {
                    712:        register struct opdata *opptr;
                    713:        register char c;
                    714:        char *s;
                    715:        long val1, val2, l;
                    716:        int oplength;
                    717: 
                    718:        for (s = *ps; isspace(*s); ++s)
                    719:                ;
                    720:        if (isdigit(c=*s++))
                    721:                for (val1 = c - '0'; isdigit(c = *s); ++s)
                    722:                        val1 = 10 * val1 + c - '0';
                    723:        else switch (c) {
                    724:        case '+':
                    725:                val1 = calc(SI, &s);
                    726:                break;
                    727:        case '-':
                    728:                val1 =-calc(SI, &s);
                    729:                break;
                    730:        case '!':
                    731:                val1 =!calc(NT, &s);
                    732:                break;
                    733:        case '(':
                    734:                val1 = calc(LP, &s);
                    735:                break;
                    736:        default:
                    737:                if (c == '\0')
                    738:                        errorp(0, "eval: missing value");
                    739:                else
                    740:                        errorp(0, "eval: invalid expression");
                    741:                s = NULL;
                    742:        }
                    743:        if ((*ps = s) == NULL)
                    744:                return (0);
                    745:        for (;;) {
                    746:                while (s!=NULL && isspace(c = *s))
                    747:                        ++s;
                    748:                oplength = 1;
                    749:                for (opptr = optable; s != NULL; ++opptr)
                    750:                        if (c != opptr->keychar) {
                    751:                                if (opptr->keychar == '\0')
                    752:                                        s = NULL;
                    753:                        } else if (opptr->secchar=='\0') {
                    754:                                break;
                    755:                        } else if (opptr->secchar == *(s+1)) {
                    756:                                ++oplength;
                    757:                                break;
                    758:                        }
                    759:                if ((*ps = s) == NULL) {
                    760:                        errorp(0, "eval: missing or unknown operator");
                    761:                        return (0);
                    762:                }
                    763:                if (opptr->prec <= pr)
                    764:                        return (val1);
                    765:                *ps = s += oplength;
                    766:                if (c == ')')
                    767:                        return (val1);
                    768:                val2 = calc(opptr->prec, &s);
                    769:                if ((*ps = s) == NULL)
                    770:                        return (0);
                    771:                switch (opptr->optype) {
                    772:                case EX:
                    773:                        if (val2 < 0)
                    774:                                val1 = 0;
                    775:                        else {
                    776:                                for (l = 1; val2; --val2)
                    777:                                        l *= val1;
                    778:                                val1 = l;
                    779:                        }
                    780:                        break;
                    781:                case MY:
                    782:                        val1 *= val2;
                    783:                        break;
                    784:                case DV:
                    785:                        val1 /= val2;
                    786:                        break;
                    787:                case MD:
                    788:                        val1 %= val2;
                    789:                        break;
                    790:                case AD:
                    791:                        val1 += val2;
                    792:                        break;
                    793:                case SB:
                    794:                        val1 -= val2;
                    795:                        break;
                    796:                case EQ:
                    797:                        val1 = (val1 == val2);
                    798:                        break;
                    799:                case NE:
                    800:                        val1 = (val1 != val2);
                    801:                        break;
                    802:                case GE:
                    803:                        val1 = (val1 >= val2);
                    804:                        break;
                    805:                case LE:
                    806:                        val1 = (val1 <= val2);
                    807:                        break;
                    808:                case GT:
                    809:                        val1 = (val1 > val2);
                    810:                        break;
                    811:                case LT:
                    812:                        val1 = (val1 < val2);
                    813:                        break;
                    814:                case AN:
                    815:                        val1 = (val1 && val2);
                    816:                        break;
                    817:                case OR:
                    818:                        val1 = (val1 || val2);
                    819:                        break;
                    820:                }
                    821:        }
                    822: }
                    823: 
                    824: mifdef(pps)
                    825: STRING **pps;
                    826: {
                    827:        ENTRY *find();
                    828: 
                    829:        if (pps[1] && find(pps[1])) {
                    830:                pushstr(pps[2]);
                    831:        } else
                    832:                pushstr(pps[3]);
                    833: }
                    834: 
                    835: mifelse(pps)
                    836: STRING **pps;
                    837: {
                    838:        if (cmpstr(pps[1], pps[2]))
                    839:                pushstr(pps[3]);
                    840:        else if (moreargs(pps, 5))
                    841:                if (cmpstr(pps[4], pps[5]))
                    842:                        pushstr(pps[6]);
                    843:                else if (moreargs(pps, 8))
                    844:                        if (cmpstr(pps[7], pps[8]))
                    845:                                pushstr(pps[9]);
                    846:                        else
                    847:                                return;
                    848:                else
                    849:                        pushstr(pps[7]);
                    850:        else
                    851:                pushstr(pps[4]);
                    852: }
                    853: 
                    854: moreargs(pps, n)
                    855: STRING **pps;
                    856: register int n;
                    857: {
                    858:        register int i;
                    859: 
                    860:        for (i=n; i<=9; i++)
                    861:                if (pps[i] != NULL)
                    862:                        return (1);
                    863:        return (0);
                    864: }
                    865: 
                    866: minclude(pps)
                    867: STRING **pps;
                    868: {
                    869:        if (msinclude(pps))
                    870:                return;
                    871:        errorp(1, "cannot open %s", pps[1]!=NULL? pps[1]->s_body : NULL);
                    872: }
                    873: 
                    874: mincr(pps)
                    875: STRING **pps;
                    876: {
                    877:        long atol();
                    878: 
                    879:        pushnum((long)((pps[1] != NULL)? atol(pps[1]->s_body)+1 : 1));
                    880: }
                    881: 
                    882: mdecr(pps)
                    883: STRING **pps;
                    884: {
                    885:        long atol();
                    886: 
                    887:        pushnum((long)((pps[1] != NULL)? atol(pps[1]->s_body)-1 : -1));
                    888: }
                    889: 
                    890: mindex(pps)
                    891: STRING **pps;
                    892: {
                    893:        register char *pc, *pf;
                    894:        register int ln;
                    895:        long v;
                    896:        char *index();
                    897: 
                    898:        if (pps[2] == NULL)
                    899:                v = 0;
                    900:        else if (pps[1] == NULL)
                    901:                v = -1;
                    902:        else {
                    903:                pc = pps[1]->s_body;
                    904:                ln = strlen(pf = pps[2]->s_body);
                    905:                while ((pc=index(pc, *pf))!=NULL && strncmp(pc, pf, ln))
                    906:                        ++pc;
                    907:                v = (pc != NULL)? (long)(pc-pps[1]->s_body) : -1;
                    908:        }
                    909:        pushnum(v);
                    910: }
                    911: 
                    912: mlen(pps)
                    913: STRING **pps;
                    914: {
                    915:        pushnum((long)((pps[1] != NULL)? pps[1]->s_next-pps[1]->s_body : 0));
                    916: }
                    917: 
                    918: mmaketemp(pps)
                    919: STRING **pps;
                    920: {
                    921:        register char *pc;
                    922:        if (pps[1]==NULL || strlen(pc = pps[1]->s_body)<TMPMIN)
                    923:                return;
                    924:        mktemp(pc);
                    925:        pushstr(pps[1]);
                    926: }
                    927: 
                    928: msinclude(pps)
                    929: STRING **pps;
                    930: {
                    931:        return (pushfile((pps[1] != NULL)? pps[1]->s_body : NULL));
                    932: }
                    933: 
                    934: msubstr(pps)
                    935: STRING **pps;
                    936: {
                    937:        register char *pc, *pb, *pe;
                    938:        int len, n, s;
                    939:        STRING *a;
                    940: 
                    941:        if (pps[1] == NULL)
                    942:                return;
                    943:        len = strlen(pc = pps[1]->s_body);
                    944:        if (pps[2] == NULL) {
                    945:                n = (pps[3] != NULL)? atoi(pps[3]->s_body) : len;
                    946:                s = (n>0)? 0 : -1;
                    947:        } else {
                    948:                s = atoi(pps[2]->s_body);
                    949:                n = (pps[3] != NULL)? atoi(pps[3]->s_body) : (s>0)? len : -len;
                    950:        }
                    951:        if (n == 0)
                    952:                return;
                    953:        pe = pc + len;
                    954:        if (s < 0)
                    955:                s += len;
                    956:        if (n < 0) {
                    957:                s += n + 1;
                    958:                n = -n;
                    959:        }
                    960:        a = makestr();
                    961:        for (pb = pc + s; n--; ++pb)
                    962:                if (pb>=pc && pb<=pe)
                    963:                        appendstr(a, *pb);
                    964:        pushstr(a);
                    965:        decstr(a);
                    966: }
                    967: 
                    968: msyscmd(pps)
                    969: STRING **pps;
                    970: {
                    971:        if (pps[1])
                    972:                system(pps[1]->s_body);
                    973: }
                    974: 
                    975: mtranslit(pps)
                    976: STRING **pps;
                    977: {
                    978:        register char *pc, *pt, *pr;
                    979:        char c = '\0';
                    980:        STRING *a;
                    981: 
                    982:        if (pps[1]==NULL || pps[2]==NULL)
                    983:                return;
                    984:        a = makestr();
                    985:        pc = pps[1]->s_body;
                    986:        do {
                    987:                pt = pps[2]->s_body;
                    988:                pr = (pps[3] != NULL)? pps[3]->s_body : &c;
                    989:                do {
                    990:                        if (*pc == *pt)
                    991:                                break;
                    992: 
                    993:                        if (*pr)
                    994:                                ++pr;
                    995:                } while (*++pt);
                    996:                if (*pt) {
                    997:                        if (*pr)
                    998:                                appendstr(a, *pr);
                    999:                } else
                   1000:                        appendstr(a, *pc);
                   1001:        } while (*++pc);
                   1002:        pushstr(a);
                   1003:        decstr(a);
                   1004: }
                   1005: 
                   1006: mundefine(pps)
                   1007: STRING **pps;
                   1008: {
                   1009:        register ENTRY *e, *ep = NULL;
                   1010:        register int hash;
                   1011: 
                   1012:        if (pps[1] == NULL)
                   1013:                return;
                   1014:        hash = pps[1]->s_hash;
                   1015:        for (e = e_root[hash % HASHSZ]; e != NULL; e = e->e_next)
                   1016:                if (e->e_name->s_hash == hash
                   1017:                &&  strcmp(e->e_name->s_body, pps[1]->s_body) == 0)
                   1018:                        break;
                   1019:                else
                   1020:                        ep = e;
                   1021:        if (e == NULL)
                   1022:                return;
                   1023:        if (e->e_type == MACD)
                   1024:                decstr(e->e_at.e_pstr);
                   1025:        decstr(e->e_name);
                   1026:        if (ep != NULL)
                   1027:                ep->e_next = e->e_next;
                   1028:        else
                   1029:                e_root[hash % HASHSZ] = e->e_next;
                   1030:        free(e);
                   1031: }
                   1032: 
                   1033: mundivert(pps)
                   1034: STRING **pps;
                   1035: {
                   1036:        register i, f = 0;
                   1037: 
                   1038:        if (pps)
                   1039:                for (i = 1; i <= 9; i++)
                   1040:                        if (pps[i]) {
                   1041:                                undiv(atoi(pps[i]->s_body));
                   1042:                                f = 1;
                   1043:                        }
                   1044:        if (pps==NULL || f==0)
                   1045:                for (i = 1; i <= 9; i++)
                   1046:                        undiv(i);
                   1047: }
                   1048: 
                   1049: undiv(n)
                   1050: register int n;
                   1051: {
                   1052:        register int c;
                   1053:        register FILE *fp;
                   1054: 
                   1055:        if (n>0 && n<=9 && (fp=outfile[n].fp) != NULL && ofnum!=n) {
                   1056:                fclose(fp);
                   1057:                if ((fp=fopen(outfile[n].name, "r")) == NULL)
                   1058:                        errorp(1, "cannot open %s", outfile[n].name);
                   1059:                while ((c=getc(fp)) != EOF)
                   1060:                        outc(c);
                   1061:                fclose(fp);
                   1062:                unlink(outfile[n].name);
                   1063:                free(outfile[n].name);
                   1064:                outfile[n].name = outfile[n].fp = NULL;
                   1065:        }
                   1066: }

unix.superglobalmegacorp.com

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