1 #include "e.h" 2 #include "y.tab.h" 3 #include <ctype.h> 4 #include <errno.h> 5 6 Infile infile[10]; 7 Infile *curfile = infile; 8 9 #define MAXSRC 50 10 Src src[MAXSRC]; /* input source stack */ 11 Src *srcp = src; 12 13 extern int getarg(char *); 14 extern void eprint(void); 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 > 1) { 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 String: 35 printf("push string <%s>\n", ptr); 36 break; 37 case Free: 38 printf("push free <%s>\n", ptr); 39 break; 40 default: 41 ERROR "pushed bad type %d\n", srcp->type FATAL; 42 } 43 } 44 } 45 46 void popsrc(void) /* restore an old one */ 47 { 48 if (srcp <= src) 49 ERROR "too many inputs popped" FATAL; 50 if (dbg > 1) { 51 printf("%3d ", srcp - src); 52 switch (srcp->type) { 53 case File: 54 printf("pop file\n"); 55 break; 56 case Macro: 57 printf("pop macro\n"); 58 break; 59 case Char: 60 printf("pop char <%c>\n", *srcp->sp); 61 break; 62 case String: 63 printf("pop string\n"); 64 break; 65 case Free: 66 printf("pop free\n"); 67 break; 68 default: 69 ERROR "pop weird input %d\n", srcp->type FATAL; 70 } 71 } 72 srcp--; 73 } 74 75 Arg args[10]; /* argument frames */ 76 Arg *argfp = args; /* frame pointer */ 77 int argcnt; /* number of arguments seen so far */ 78 79 void dodef(tbl *stp) /* collect args and switch input to defn */ 80 { 81 int i, len; 82 char *p; 83 Arg *ap; 84 85 ap = argfp+1; 86 if (ap >= args+10) 87 ERROR "more than arguments\n" FATAL; 88 argcnt = 0; 89 if (input() != '(') 90 ERROR "disaster in dodef\n"FATAL; 91 if (ap->argval == 0) 92 ap->argval = malloc(1000); 93 for (p = ap->argval; (len = getarg(p)) != -1; p += len) { 94 ap->argstk[argcnt++] = p; 95 if (input() == ')') 96 break; 97 } 98 for (i = argcnt; i < MAXARGS; i++) 99 ap->argstk[i] = ""; 100 if (dbg) 101 for (i = 0; i < argcnt; i++) 102 printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]); 103 argfp = ap; 104 pushsrc(Macro, stp->cval); 105 } 106 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 input(void) 143 { 144 register int c = 0; 145 146 loop: 147 switch (srcp->type) { 148 case File: 149 c = getc(curfile->fin); 150 if (c == EOF) { 151 if (curfile == infile) 152 break; 153 if (curfile->fin != stdin) { 154 fclose(curfile->fin); 155 free(curfile->fname); /* assumes allocated */ 156 } 157 curfile--; 158 printf(".lf %d %s\n", curfile->lineno, curfile->fname); 159 popsrc(); 160 goto loop; 161 } 162 if (c == '\n') 163 curfile->lineno++; 164 break; 165 case Char: 166 if (pb >= pbuf) { 167 c = *pb--; 168 popsrc(); 169 break; 170 } else { /* can't happen? */ 171 popsrc(); 172 goto loop; 173 } 174 case String: 175 c = *srcp->sp++; 176 if (c == '\0') { 177 popsrc(); 178 goto loop; 179 } else { 180 if (*srcp->sp == '\0') /* empty, so pop */ 181 popsrc(); 182 break; 183 } 184 case Macro: 185 c = *srcp->sp++; 186 if (c == '\0') { 187 if (--argfp < args) 188 ERROR "argfp underflow" FATAL; 189 popsrc(); 190 goto loop; 191 } else if (c == '$' && isdigit(*srcp->sp)) { 192 int n = 0; 193 while (isdigit(*srcp->sp)) 194 n = 10 * n + *srcp->sp++ - '0'; 195 if (n > 0 && n <= MAXARGS) 196 pushsrc(String, argfp->argstk[n-1]); 197 goto loop; 198 } 199 break; 200 case Free: /* free string */ 201 free(srcp->sp); 202 popsrc(); 203 goto loop; 204 } 205 if (ep >= ebuf + sizeof ebuf) 206 ep = ebuf; 207 *ep++ = c; 208 return c; 209 } 210 211 212 unput(int c) 213 { 214 if (++pb >= pbuf + sizeof pbuf) 215 ERROR "pushback overflow\n"FATAL; 216 if (--ep < ebuf) 217 ep = ebuf + sizeof(ebuf) - 1; 218 *pb = c; 219 pushsrc(Char, pb); 220 return c; 221 } 222 223 void pbstr(char *s) 224 { 225 pushsrc(String, s); 226 } 227 228 void error(int die, char *s) 229 { 230 extern char *cmdname; 231 232 if (synerr) 233 return; 234 fprintf(stderr, "%s: ", cmdname); 235 fprintf(stderr, s); 236 if (errno > 0) 237 perror("???"); 238 if (curfile->fin) 239 fprintf(stderr, " near line %d, file %s", 240 curfile->lineno, curfile->fname); 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[200]; 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 } 290