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

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

unix.superglobalmegacorp.com

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