Annotation of researchv9/cmd/grap/input.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: #include <ctype.h>
                      3: #include <errno.h>
                      4: #include "grap.h"
                      5: #include "y.tab.h"
                      6: 
                      7: Infile infile[10];
                      8: Infile *curfile = infile;
                      9: 
                     10: #define        MAXSRC  50
                     11: Src    src[MAXSRC];    /* input source stack */
                     12: Src    *srcp   = src;
                     13: 
                     14: pushsrc(type, ptr)     /* new input source */
                     15:        int type;
                     16:        char *ptr;
                     17: {
                     18:        if (++srcp >= src + MAXSRC)
                     19:                fatal("inputs nested too deep");
                     20:        srcp->type = type;
                     21:        srcp->sp = ptr;
                     22:        if (dbg) {
                     23:                printf("\n%3d ", srcp - src);
                     24:                switch (srcp->type) {
                     25:                case File:
                     26:                        printf("push file %s\n", ((Infile *)ptr)->fname);
                     27:                        break;
                     28:                case Macro:
                     29:                        printf("push macro <%s>\n", ptr);
                     30:                        break;
                     31:                case Char:
                     32:                        printf("push char <%c>\n", *ptr);
                     33:                        break;
                     34:                case Thru:
                     35:                        printf("push thru\n");
                     36:                        break;
                     37:                case String:
                     38:                        printf("push string <%s>\n", ptr);
                     39:                        break;
                     40:                case Free:
                     41:                        printf("push free <%s>\n", ptr);
                     42:                        break;
                     43:                default:
                     44:                        fatal("pushed bad type %d\n", srcp->type);
                     45:                }
                     46:        }
                     47: }
                     48: 
                     49: popsrc()       /* restore an old one */
                     50: {
                     51:        if (srcp <= src)
                     52:                fatal("too many inputs popped");
                     53:        if (dbg) {
                     54:                printf("%3d ", srcp - src);
                     55:                switch (srcp->type) {
                     56:                case File:
                     57:                        printf("pop file\n");
                     58:                        break;
                     59:                case Macro:
                     60:                        printf("pop macro\n");
                     61:                        break;
                     62:                case Char:
                     63:                        printf("pop char <%c>\n", *srcp->sp);
                     64:                        break;
                     65:                case Thru:
                     66:                        printf("pop thru\n");
                     67:                        break;
                     68:                case String:
                     69:                        printf("pop string\n");
                     70:                        break;
                     71:                case Free:
                     72:                        printf("pop free\n");
                     73:                        break;
                     74:                default:
                     75:                        fatal("pop weird input %d\n", srcp->type);
                     76:                }
                     77:        }
                     78:        srcp--;
                     79: }
                     80: 
                     81: definition(s)  /* collect definition for s and install */
                     82:        char *s;        /* definitions picked up lexically */
                     83: {
                     84:        char *p;
                     85:        Obj *stp;
                     86: 
                     87:        p = delimstr("definition");
                     88:        stp = lookup(s, 0);
                     89:        if (stp != NULL) {      /* it's there before */
                     90:                if (stp->type != DEFNAME) {
                     91:                        yyerror("%s used as variable and definition\n", s);
                     92:                        return;
                     93:                }
                     94:                free(stp->val);
                     95:        } else {
                     96:                stp = lookup(s, 1);
                     97:                stp->type = DEFNAME;
                     98:        }
                     99:        stp->val = p;
                    100:        dprintf("installing %s as `%s'\n", s, p);
                    101: }
                    102: 
                    103: char *delimstr(s)      /* get body of X ... X */
                    104:        char *s;                /* message if too big */
                    105: {
                    106:        int c, delim, rdelim, n, deep;
                    107:        static char *buf = NULL;
                    108:        static int nbuf = 0;
                    109:        char *p;
                    110: 
                    111:        if (buf == NULL)
                    112:                buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0]));
                    113:        while ((delim = input()) == ' ' || delim == '\t' || delim == '\n')
                    114:                ;
                    115:        rdelim = baldelim(delim, "{}");         /* could be "(){}[]`'" */
                    116:        deep = 1;
                    117:        for (p = buf; ; ) {
                    118:                c = input();
                    119:                if (c == rdelim)
                    120:                        if (--deep == 0)
                    121:                                break;
                    122:                if (c == delim)
                    123:                        deep++;
                    124:                if (p >= buf + nbuf) {
                    125:                        n = p - buf;
                    126:                        buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0]));
                    127:                        p = buf + n;
                    128:                }
                    129:                if (c == EOF)
                    130:                        fatal("end of file in %s %c %.20s... %c", s, delim, buf, delim);
                    131:                *p++ = c;
                    132:        }
                    133:        *p = '\0';
                    134:        dprintf("delimstr %s %c <%s> %c\n", s, delim, buf, delim);
                    135:        return tostring(buf);
                    136: }
                    137: 
                    138: baldelim(c, s) /* replace c by balancing entry in s */
                    139:        int c;
                    140:        char *s;
                    141: {
                    142:        for ( ; *s; s += 2)
                    143:                if (*s == c)
                    144:                        return s[1];
                    145:        return c;
                    146: }
                    147: 
                    148: Arg    args[10];       /* argument frames */
                    149: Arg    *argfp = args;  /* frame pointer */
                    150: int    argcnt;         /* number of arguments seen so far */
                    151: 
                    152: dodef(stp)     /* collect args and switch input to defn */
                    153:        Obj *stp;
                    154: {
                    155:        int i, len;
                    156:        char *p;
                    157:        Arg *ap;
                    158: 
                    159:        ap = argfp+1;
                    160:        if (ap >= args+10)
                    161:                fatal("arguments too deep");
                    162:        argcnt = 0;
                    163:        if (input() != '(')
                    164:                fatal("disaster in dodef\n");
                    165:        if (ap->argval == 0)
                    166:                ap->argval = malloc(1000);
                    167:        for (p = ap->argval; (len = getarg(p)) != -1; p += len) {
                    168:                ap->argstk[argcnt++] = p;
                    169:                if (input() == ')')
                    170:                        break;
                    171:        }
                    172:        for (i = argcnt; i < MAXARGS; i++)
                    173:                ap->argstk[i] = "";
                    174:        if (dbg)
                    175:                for (i = 0; i < argcnt; i++)
                    176:                        printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]);
                    177:        argfp = ap;
                    178:        pushsrc(Macro, stp->val);
                    179: }
                    180: 
                    181: getarg(p)      /* pick up single argument, store in p, return length */
                    182:        char *p;
                    183: {
                    184:        int n, c, npar;
                    185: 
                    186:        n = npar = 0;
                    187:        for ( ;; ) {
                    188:                c = input();
                    189:                if (c == EOF)
                    190:                        fatal("end of file in getarg!\n");
                    191:                if (npar == 0 && (c == ',' || c == ')'))
                    192:                        break;
                    193:                if (c == '"')   /* copy quoted stuff intact */
                    194:                        do {
                    195:                                *p++ = c;
                    196:                                n++;
                    197:                        } while ((c = input()) != '"' && c != EOF);
                    198:                else if (c == '(')
                    199:                        npar++;
                    200:                else if (c == ')')
                    201:                        npar--;
                    202:                n++;
                    203:                *p++ = c;
                    204:        }
                    205:        *p = 0;
                    206:        unput(c);
                    207:        return(n + 1);
                    208: }
                    209: 
                    210: #define        PBSIZE  2000
                    211: char   pbuf[PBSIZE];           /* pushback buffer */
                    212: char   *pb     = pbuf-1;       /* next pushed back character */
                    213: 
                    214: char   ebuf[200];              /* collect input here for error reporting */
                    215: char   *ep     = ebuf;
                    216: 
                    217: int    begin   = 0;
                    218: extern int     thru;
                    219: extern Obj     *thrudef;
                    220: extern char    *untilstr;
                    221: 
                    222: input()
                    223: {
                    224:        register int c;
                    225: 
                    226:        if (thru && begin) {
                    227:                do_thru();
                    228:                begin = 0;
                    229:        }
                    230:        c = nextchar();
                    231:        dprintf(" <%c>", c);
                    232:        if (ep >= ebuf + sizeof ebuf)
                    233:                ep = ebuf;
                    234:        return *ep++ = c;
                    235: }
                    236: 
                    237: nextchar()
                    238: {
                    239:        register int c;
                    240: 
                    241:   loop:
                    242:        switch (srcp->type) {
                    243:        case Free:      /* free string */
                    244:                free(srcp->sp);
                    245:                popsrc();
                    246:                goto loop;
                    247:        case Thru:      /* end of pushed back line */
                    248:                begin = 1;
                    249:                popsrc();
                    250:                c = '\n';
                    251:                break;
                    252:        case Char:
                    253:                if (pb >= pbuf) {
                    254:                        c = *pb--;
                    255:                        popsrc();
                    256:                        break;
                    257:                } else {        /* can't happen? */
                    258:                        popsrc();
                    259:                        goto loop;
                    260:                }
                    261:        case String:
                    262:                c = *srcp->sp++;
                    263:                if (c == '\0') {
                    264:                        popsrc();
                    265:                        goto loop;
                    266:                } else {
                    267:                        if (*srcp->sp == '\0')  /* empty, so pop */
                    268:                                popsrc();
                    269:                        break;
                    270:                }
                    271:        case Macro:
                    272:                c = *srcp->sp++;
                    273:                if (c == '\0') {
                    274:                        if (--argfp < args)
                    275:                                fatal("argfp underflow");
                    276:                        popsrc();
                    277:                        goto loop;
                    278:                } else if (c == '$' && isdigit(*srcp->sp)) {
                    279:                        int n = 0;
                    280:                        while (isdigit(*srcp->sp))
                    281:                                n = 10 * n + *srcp->sp++ - '0';
                    282:                        if (n > 0 && n <= MAXARGS)
                    283:                                pushsrc(String, argfp->argstk[n-1]);
                    284:                        goto loop;
                    285:                }
                    286:                break;
                    287:        case File:
                    288:                c = getc(curfile->fin);
                    289:                if (c == EOF) {
                    290:                        if (curfile == infile)
                    291:                                fatal("end of file inside .G1/.G2");
                    292:                        if (curfile->fin != stdin) {
                    293:                                fclose(curfile->fin);
                    294:                                free(curfile->fname);   /* assumes allocated */
                    295:                        }
                    296:                        curfile--;
                    297:                        printf(".lf %d %s\n", curfile->lineno, curfile->fname);
                    298:                        popsrc();
                    299:                        thru = 0;       /* chicken out */
                    300:                        thrudef = 0;
                    301:                        if (untilstr) {
                    302:                                free(untilstr);
                    303:                                untilstr = 0;
                    304:                        }
                    305:                        goto loop;
                    306:                }
                    307:                if (c == '\n')
                    308:                        curfile->lineno++;
                    309:                break;
                    310:        }
                    311:        return c;
                    312: }
                    313: 
                    314: do_thru()      /* read one line, make into a macro expansion */
                    315: {
                    316:        int c, i, n;
                    317:        char *p;
                    318:        Arg *ap;
                    319: 
                    320:        ap = argfp+1;
                    321:        if (ap >= args+10)
                    322:                fatal("arguments too deep");
                    323:        if (ap->argval == NULL)
                    324:                ap->argval = malloc(1000);
                    325:        p = ap->argval;
                    326:        argcnt = 0;
                    327:        c = nextchar();
                    328:        if (thru == 0) {        /* end of file was seen, so thru is done */
                    329:                unput(c);
                    330:                return;
                    331:        }
                    332:        for ( ; c != '\n' && c != EOF; ) {
                    333:                if (c == ' ' || c == '\t') {
                    334:                        c = nextchar();
                    335:                        continue;
                    336:                }
                    337:                ap->argstk[argcnt++] = p;
                    338:                if (c == '"') {
                    339:                        do {
                    340:                                *p++ = c;
                    341:                                if ((c = nextchar()) == '\\') {
                    342:                                        *p++ = c;
                    343:                                        *p++ = nextchar();
                    344:                                        c = nextchar();
                    345:                                }
                    346:                        } while (c != '"' && c != '\n' && c != EOF);
                    347:                        *p++ = '"';
                    348:                        if (c == '"')
                    349:                                c = nextchar();
                    350:                } else {
                    351:                        do {
                    352:                                *p++ = c;
                    353:                        } while ((c = nextchar())!=' ' && c!='\t' && c!='\n' && c!=',' && c!=EOF);
                    354:                        if (c == ',')
                    355:                                c = nextchar();
                    356:                }
                    357:                *p++ = '\0';
                    358:        }
                    359:        if (c == EOF)
                    360:                fatal("unexpected end of file in do_thru");
                    361:        if (argcnt == 0) {      /* ignore blank line */
                    362:                pushsrc(Thru, (char *) 0);
                    363:                return;
                    364:        }
                    365:        for (i = argcnt; i < MAXARGS; i++)
                    366:                ap->argstk[i] = "";
                    367:        if (dbg)
                    368:                for (i = 0; i < argcnt; i++)
                    369:                        printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]);
                    370:        if (strcmp(ap->argstk[0], ".G2") == 0) {
                    371:                thru = 0;
                    372:                thrudef = 0;
                    373:                pushsrc(String, "\n.G2\n");
                    374:                return;
                    375:        }
                    376:        if (untilstr && strcmp(ap->argstk[0], untilstr) == 0) {
                    377:                thru = 0;
                    378:                thrudef = 0;
                    379:                free(untilstr);
                    380:                untilstr = 0;
                    381:                return;
                    382:        }
                    383:        pushsrc(Thru, (char *) 0);
                    384:        dprintf("do_thru pushing back <%s>\n", thrudef->val);
                    385:        argfp = ap;
                    386:        pushsrc(Macro, thrudef->val);
                    387: }
                    388: 
                    389: unput(c)
                    390: {
                    391:        if (++pb >= pbuf + sizeof pbuf)
                    392:                fatal("pushback overflow\n");
                    393:        if (--ep < ebuf)
                    394:                ep = ebuf + sizeof(ebuf) - 1;
                    395:        *pb = c;
                    396:        pushsrc(Char, pb);
                    397:        return c;
                    398: }
                    399: 
                    400: pbstr(s)
                    401:        char *s;
                    402: {
                    403:        pushsrc(String, s);
                    404: }
                    405: 
                    406: double errcheck(x, s)
                    407:        double x;
                    408:        char *s;
                    409: {
                    410:        extern int errno;
                    411: 
                    412:        if (errno == EDOM) {
                    413:                errno = 0;
                    414:                yyerror("%s argument out of domain", s);
                    415:        } else if (errno == ERANGE) {
                    416:                errno = 0;
                    417:                yyerror("%s result out of range", s);
                    418:        }
                    419:        return x;
                    420: }
                    421: 
                    422: fatal(s, s1, s2, s3, s4)       /* should be a flag on yyerror */
                    423:        char *s, *s1, *s2, *s3, *s4;
                    424: {
                    425:        yyerror(s, s1, s2, s3, s4);
                    426:        if (dbg)
                    427:                abort();
                    428:        else
                    429:                onintr();       /* cleans up temporary */
                    430: }
                    431: 
                    432: yyerror(s, s1, s2, s3, s4)
                    433:        char *s, *s1, *s2, *s3, *s4;
                    434: {
                    435:        extern char *cmdname, *sys_errlist[];
                    436:        extern int errno, sys_nerr;
                    437: 
                    438:        if (synerr)
                    439:                return;
                    440:        fprintf(stderr, "%s: ", cmdname);
                    441:        fprintf(stderr, s, s1, s2, s3, s4);
                    442:        if (errno > 0 && errno < sys_nerr)
                    443:                fprintf(stderr, " (%s)", sys_errlist[errno]);
                    444:        fprintf(stderr, " near line %d, file %s\n",
                    445:                curfile->lineno, curfile->fname);
                    446:        eprint();
                    447:        synerr = 1;
                    448:        errno = 0;
                    449: }
                    450: 
                    451: eprint()       /* try to print context around error */
                    452: {
                    453:        char *p, *q;
                    454:        int c;
                    455: 
                    456:        p = ep - 1;
                    457:        if (p > ebuf && *p == '\n')
                    458:                p--;
                    459:        for ( ; p >= ebuf && *p != '\n'; p--)
                    460:                ;
                    461:        while (*p == '\n')
                    462:                p++;
                    463:        fprintf(stderr, " context is\n\t");
                    464:        for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
                    465:                ;
                    466:        while (p < q)
                    467:                putc(*p++, stderr);
                    468:        fprintf(stderr, " >>> ");
                    469:        while (p < ep)
                    470:                putc(*p++, stderr);
                    471:        fprintf(stderr, " <<< ");
                    472:        while (pb >= pbuf)
                    473:                putc(*pb--, stderr);
                    474:        fgets(ebuf, sizeof ebuf, curfile->fin);
                    475:        fprintf(stderr, "%s", ebuf);
                    476:        pbstr("\n.G2\n");       /* safety first */
                    477:        ep = ebuf;
                    478: }
                    479: 
                    480: yywrap() {;}
                    481: 
                    482: char   *newfile = 0;           /* filename for file copy */
                    483: char   *untilstr = 0;          /* string that terminates a thru */
                    484: int    thru    = 0;            /* 1 if copying thru macro */
                    485: Obj    *thrudef = 0;           /* macro being used */
                    486: 
                    487: copyfile(s)    /* remember file to start reading from */
                    488:        char *s;
                    489: {
                    490:        newfile = s;
                    491: }
                    492: 
                    493: copydef(p)     /* remember macro Obj */
                    494:        Obj *p;
                    495: {
                    496:        thrudef = p;
                    497: }
                    498: 
                    499: Obj *copythru(s)       /* collect the macro name or body for thru */
                    500:        char *s;
                    501: {
                    502:        Obj *p;
                    503:        char *q, *addnewline();
                    504: 
                    505:        p = lookup(s, 0);
                    506:        if (p != NULL) {
                    507:                if (p->type == DEFNAME) {
                    508:                        p->val = addnewline(p->val);
                    509:                        return p;
                    510:                } else
                    511:                        fatal("%s used as define and name", s);
                    512:        }
                    513:        /* have to collect the definition */
                    514:        pbstr(s);       /* first char is the delimiter */
                    515:        q = delimstr("thru body");
                    516:        p = lookup("nameless", 1);
                    517:        if (p != NULL)
                    518:                if (p->val)
                    519:                        free(p->val);
                    520:        p->type = DEFNAME;
                    521:        p->val = q;
                    522:        p->val = addnewline(p->val);
                    523:        dprintf("installing nameless as `%s'\n", p->val);
                    524:        return p;
                    525: }
                    526: 
                    527: char *addnewline(p)    /* add newline to end of p */
                    528:        char *p;
                    529: {
                    530:        int n;
                    531:        extern char *realloc();
                    532: 
                    533:        n = strlen(p);
                    534:        if (p[n-1] != '\n') {
                    535:                p = realloc(p, n+2);
                    536:                p[n] = '\n';
                    537:                p[n+1] = '\0';
                    538:        }
                    539:        return p;
                    540: }
                    541: 
                    542: copyuntil(s)   /* string that terminates a thru */
                    543:        char *s;
                    544: {
                    545:        untilstr = s;
                    546: }
                    547: 
                    548: copy() /* begin input from file, etc. */
                    549: {
                    550:        FILE *fin;
                    551: 
                    552:        if (newfile) {
                    553:                if ((fin = fopen(newfile, "r")) == NULL)
                    554:                        fatal("can't open file %s", newfile);
                    555:                curfile++;
                    556:                curfile->fin = fin;
                    557:                curfile->fname = tostring(newfile);
                    558:                curfile->lineno = 0;
                    559:                printf(".lf 1 %s\n", curfile->fname);
                    560:                pushsrc(File, curfile);
                    561:                newfile = 0;
                    562:        }
                    563:        if (thrudef) {
                    564:                thru = 1;
                    565:                begin = 1;      /* wrong place */
                    566:        }
                    567: }
                    568: 
                    569: char   shellbuf[1000], *shellp;
                    570: 
                    571: shell_init()   /* set up to interpret a shell command */
                    572: {
                    573:        fprintf(tfd, "# shell cmd...\n");
                    574:        sprintf(shellbuf, "sh -c '");
                    575:        shellp = shellbuf + strlen(shellbuf);
                    576: }
                    577: 
                    578: shell_text(s)  /* add string to command being collected */
                    579:        char *s;
                    580: {
                    581:        /* fprintf(tfd, "#add <%s> to <%s>\n", s, shellbuf); */
                    582:        while (*s) {
                    583:                if (*s == '\'') {       /* protect interior quotes */
                    584:                        *shellp++ = '\'';
                    585:                        *shellp++ = '\\';
                    586:                        *shellp++ = '\'';
                    587:                }
                    588:                *shellp++ = *s++;
                    589:        }
                    590: }
                    591: 
                    592: shell_exec()   /* do it */
                    593: {
                    594:        /* fprintf(tfd, "# run <%s>\n", shellbuf); */
                    595:        *shellp++ = '\'';
                    596:        *shellp = '\0';
                    597:        system(shellbuf);
                    598: }

unix.superglobalmegacorp.com

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