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

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

unix.superglobalmegacorp.com

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