input.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 }