URI:
       tinput.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tinput.c (5436B)
       ---
            1 #include "e.h"
            2 #include "y.tab.h"
            3 #include <ctype.h>
            4 
            5 Infile        infile[10];
            6 Infile        *curfile = infile;
            7 
            8 #define        MAXSRC        50
            9 Src        src[MAXSRC];        /* input source stack */
           10 Src        *srcp        = src;
           11 
           12 extern int getarg(char *);
           13 extern        void eprint(void);
           14 
           15 void pushsrc(int type, char *ptr)        /* new input source */
           16 {
           17         if (++srcp >= src + MAXSRC)
           18                 ERROR "inputs nested too deep" FATAL;
           19         srcp->type = type;
           20         srcp->sp = ptr;
           21         if (dbg > 1) {
           22                 printf("\n%3ld ", (long)(srcp - src));
           23                 switch (srcp->type) {
           24                 case File:
           25                         printf("push file %s\n", ((Infile *)ptr)->fname);
           26                         break;
           27                 case Macro:
           28                         printf("push macro <%s>\n", ptr);
           29                         break;
           30                 case Char:
           31                         printf("push char <%c>\n", *ptr);
           32                         break;
           33                 case String:
           34                         printf("push string <%s>\n", ptr);
           35                         break;
           36                 case Free:
           37                         printf("push free <%s>\n", ptr);
           38                         break;
           39                 default:
           40                         ERROR "pushed bad type %d\n", srcp->type FATAL;
           41                 }
           42         }
           43 }
           44 
           45 void popsrc(void)        /* restore an old one */
           46 {
           47         if (srcp <= src)
           48                 ERROR "too many inputs popped" FATAL;
           49         if (dbg > 1) {
           50                 printf("%3ld ", (long)(srcp - src));
           51                 switch (srcp->type) {
           52                 case File:
           53                         printf("pop file\n");
           54                         break;
           55                 case Macro:
           56                         printf("pop macro\n");
           57                         break;
           58                 case Char:
           59                         printf("pop char <%c>\n", *srcp->sp);
           60                         break;
           61                 case String:
           62                         printf("pop string\n");
           63                         break;
           64                 case Free:
           65                         printf("pop free\n");
           66                         break;
           67                 default:
           68                         ERROR "pop weird input %d\n", srcp->type FATAL;
           69                 }
           70         }
           71         srcp--;
           72 }
           73 
           74 Arg        args[10];        /* argument frames */
           75 Arg        *argfp = args;        /* frame pointer */
           76 int        argcnt;                /* number of arguments seen so far */
           77 
           78 void dodef(tbl *stp)        /* collect args and switch input to defn */
           79 {
           80         int i, len;
           81         char *p;
           82         Arg *ap;
           83 
           84         ap = argfp+1;
           85         if (ap >= args+10)
           86                 ERROR "more than arguments\n" FATAL;
           87         argcnt = 0;
           88         if (input() != '(')
           89                 ERROR "disaster in dodef\n"FATAL;
           90         if (ap->argval == 0)
           91                 ap->argval = malloc(1000);
           92         for (p = ap->argval; (len = getarg(p)) != -1; p += len) {
           93                 ap->argstk[argcnt++] = p;
           94                 if (input() == ')')
           95                         break;
           96         }
           97         for (i = argcnt; i < MAXARGS; i++)
           98                 ap->argstk[i] = "";
           99         if (dbg)
          100                 for (i = 0; i < argcnt; i++)
          101                         printf("arg %ld.%d = <%s>\n", (long)(ap-args), i+1, ap->argstk[i]);
          102         argfp = ap;
          103         pushsrc(Macro, stp->cval);
          104 }
          105 
          106 int
          107 getarg(char *p)        /* pick up single argument, store in p, return length */
          108 {
          109         int n, c, npar;
          110 
          111         n = npar = 0;
          112         for ( ;; ) {
          113                 c = input();
          114                 if (c == EOF)
          115                         ERROR "end of file in getarg!\n" FATAL;
          116                 if (npar == 0 && (c == ',' || c == ')'))
          117                         break;
          118                 if (c == '"')        /* copy quoted stuff intact */
          119                         do {
          120                                 *p++ = c;
          121                                 n++;
          122                         } while ((c = input()) != '"' && c != EOF);
          123                 else if (c == '(')
          124                         npar++;
          125                 else if (c == ')')
          126                         npar--;
          127                 n++;
          128                 *p++ = c;
          129         }
          130         *p = 0;
          131         unput(c);
          132         return(n + 1);
          133 }
          134 
          135 #define        PBSIZE        2000
          136 char        pbuf[PBSIZE];                /* pushback buffer */
          137 char        *pb        = pbuf-1;        /* next pushed back character */
          138 
          139 char        ebuf[200];                /* collect input here for error reporting */
          140 char        *ep        = ebuf;
          141 
          142 int
          143 input(void)
          144 {
          145         register int c = 0;
          146 
          147   loop:
          148         switch (srcp->type) {
          149         case File:
          150                 c = getc(curfile->fin);
          151                 if (c == EOF) {
          152                         if (curfile == infile)
          153                                 break;
          154                         if (curfile->fin != stdin) {
          155                                 fclose(curfile->fin);
          156                                 free(curfile->fname);        /* assumes allocated */
          157                         }
          158                         curfile--;
          159                         printf(".lf %d %s\n", curfile->lineno, curfile->fname);
          160                         popsrc();
          161                         goto loop;
          162                 }
          163                 if (c == '\n')
          164                         curfile->lineno++;
          165                 break;
          166         case Char:
          167                 if (pb >= pbuf) {
          168                         c = *pb--;
          169                         popsrc();
          170                         break;
          171                 } else {        /* can't happen? */
          172                         popsrc();
          173                         goto loop;
          174                 }
          175         case String:
          176                 c = *srcp->sp++;
          177                 if (c == '\0') {
          178                         popsrc();
          179                         goto loop;
          180                 } else {
          181                         if (*srcp->sp == '\0')        /* empty, so pop */
          182                                 popsrc();
          183                         break;
          184                 }
          185         case Macro:
          186                 c = *srcp->sp++;
          187                 if (c == '\0') {
          188                         if (--argfp < args)
          189                                 ERROR "argfp underflow" FATAL;
          190                         popsrc();
          191                         goto loop;
          192                 } else if (c == '$' && isdigit((unsigned char)*srcp->sp)) {
          193                         int n = 0;
          194                         while (isdigit((unsigned char)*srcp->sp))
          195                                 n = 10 * n + *srcp->sp++ - '0';
          196                         if (n > 0 && n <= MAXARGS)
          197                                 pushsrc(String, argfp->argstk[n-1]);
          198                         goto loop;
          199                 }
          200                 break;
          201         case Free:        /* free string */
          202                 free(srcp->sp);
          203                 popsrc();
          204                 goto loop;
          205         }
          206         if (ep >= ebuf + sizeof ebuf)
          207                 ep = ebuf;
          208         *ep++ = c;
          209         return c;
          210 }
          211 
          212 int
          213 unput(int c)
          214 {
          215         if (++pb >= pbuf + sizeof pbuf)
          216                 ERROR "pushback overflow\n"FATAL;
          217         if (--ep < ebuf)
          218                 ep = ebuf + sizeof(ebuf) - 1;
          219         *pb = c;
          220         pushsrc(Char, pb);
          221         return c;
          222 }
          223 
          224 void pbstr(char *s)
          225 {
          226         pushsrc(String, s);
          227 }
          228 
          229 void error(int die, char *s)
          230 {
          231         extern char *cmdname;
          232 
          233         if (synerr)
          234                 return;
          235         fprintf(stderr, "%s: %s", cmdname, s);
          236         if (errno > 0)
          237                 perror("???");
          238         if (curfile->fin)
          239                 fprintf(stderr, " near %s:%d",
          240                         curfile->fname, curfile->lineno+1);
          241         fprintf(stderr, "\n");
          242         eprint();
          243         synerr = 1;
          244         errno = 0;
          245         if (die) {
          246                 if (dbg)
          247                         abort();
          248                 else
          249                         exit(1);
          250         }
          251 }
          252 
          253 void yyerror(char *s)
          254 {
          255         error(0, s);        /* temporary */
          256 }
          257 
          258 char errbuf[2000];
          259 
          260 void eprint(void)        /* try to print context around error */
          261 {
          262         char *p, *q;
          263 
          264         if (ep == ebuf)
          265                 return;                                /* no context */
          266         p = ep - 1;
          267         if (p > ebuf && *p == '\n')
          268                 p--;
          269         for ( ; p >= ebuf && *p != '\n'; p--)
          270                 ;
          271         while (*p == '\n')
          272                 p++;
          273         fprintf(stderr, " context is\n\t");
          274         for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
          275                 ;
          276         while (p < q)
          277                 putc(*p++, stderr);
          278         fprintf(stderr, " >>> ");
          279         while (p < ep)
          280                 putc(*p++, stderr);
          281         fprintf(stderr, " <<< ");
          282         while (pb >= pbuf)
          283                 putc(*pb--, stderr);
          284         if (curfile->fin)
          285                 fgets(ebuf, sizeof ebuf, curfile->fin);
          286         fprintf(stderr, "%s", ebuf);
          287         pbstr("\n.EN\n");        /* safety first */
          288         ep = ebuf;
          289 }