1 #include <stdio.h> 2 #include <ctype.h> 3 #include "pic.h" 4 #include "y.tab.h" 5 6 extern FILE *yyin; 7 extern int lineno; 8 extern char *filename; 9 extern int synerr; 10 11 definition(s) /* collect definition for s and install */ 12 char *s; /* definitions picked up lexically */ 13 { 14 char buf[4000], *p, *tostring(); 15 int c, delim; 16 struct symtab *stp; 17 18 while ((delim = input()) == ' ' || delim == '\t') 19 ; 20 for (p = buf; (c = input()) != delim; ) { 21 if (p >= buf + sizeof(buf)) { 22 yyerror("definition of %s is too long", s); 23 exit(1); 24 } 25 if (c == EOF) { 26 yyerror("end of file while defining %s", s); 27 exit(1); 28 } 29 *p++ = c; 30 } 31 *p = '\0'; 32 p = tostring(buf); 33 stp = lookup(s); 34 if (stp != NULL) { /* it's there before */ 35 if (stp->s_type != DEFNAME) { 36 yyerror("%s used as variable and definition\n", s); 37 return; 38 } 39 free(stp->s_val.p); 40 stp->s_val.p = p; 41 } else { 42 YYSTYPE u; 43 u.p = p; 44 makevar(tostring(s), DEFNAME, u); 45 } 46 dprintf("installing %s as `%s'\n", s, p); 47 } 48 49 char *argstk[10]; /* pointers to actual arguments in argval */ 50 char argval[1000]; /* arguments stored here end to end */ 51 char *argp; /* current position in argval */ 52 int argcnt; /* number of arguments seen so far */ 53 54 dodef(stp) /* collect args and push back defn for name in table slot n */ 55 struct symtab *stp; 56 { 57 int i, c, len; 58 char *p; 59 60 argcnt = 0; 61 if (input() != '(') 62 yyerror("disaster in dodef\n"); 63 for (argp = argval; (len = getarg(argp)) != -1; argp += len) { 64 argstk[argcnt++] = argp; 65 if (input() == ')') 66 break; 67 } 68 for (i = argcnt; i < 10; i++) 69 argstk[i] = ""; 70 if (dbg) { 71 for (i = 0; i < argcnt; i++) 72 printf("arg %d = %s\n", i, argstk[i]); 73 } 74 75 /* push them back */ 76 for (p = stp->s_val.p; *p; p++) 77 ; /* find the end */ 78 for (--p; p >= stp->s_val.p; p--) { 79 if (*(p-1) == '$') { 80 if (isdigit(*p)) { 81 pbstr(argstk[*p - '0' - 1]); 82 p--; 83 } 84 else 85 unput(*p); 86 } else { 87 unput(*p); 88 } 89 } 90 } 91 92 getarg(p) /* pick up single argument, store in p, return length */ 93 char *p; 94 { 95 int n, c, npar; 96 97 n = npar = 0; 98 for ( ;; ) { 99 c = input(); 100 if (c == EOF) 101 yyerror("end of file in getarg!\n"); 102 if (npar == 0 && (c == ',' || c == ')')) 103 break; 104 if (c == '"') /* copy quoted stuff intact */ 105 do { 106 *p++ = c; 107 n++; 108 } while ((c = input()) != '"' && c != EOF); 109 else if (c == '(') 110 npar++; 111 else if (c == ')') 112 npar--; 113 n++; 114 *p++ = c; 115 } 116 *p = 0; 117 unput(c); 118 return(n + 1); 119 } 120 121 #define PBSIZE 4000 122 char pbuf[PBSIZE]; /* pushback buffer */ 123 char *pb = pbuf-1; /* next pushed back character */ 124 125 char ebuf[200]; /* collect input here for error reporting */ 126 char *ep = ebuf; 127 128 input() 129 { 130 register int c; 131 132 if (pb >= pbuf) { 133 c = *pb--; 134 } else { 135 c = getc(yyin); 136 if (c == '\n') 137 lineno++; 138 else if (c == EOF) { 139 yyerror("end of file inside .PS/.PE"); 140 exit(1); 141 } 142 } 143 if (ep >= ebuf + sizeof ebuf) 144 ep = ebuf; 145 return (*ep++ = c); 146 } 147 148 unput(c) 149 { 150 if (++pb >= pbuf + sizeof pbuf) { 151 yyerror("pushback overflow\n"); 152 exit(1); 153 } 154 if (--ep < ebuf) 155 ep = ebuf + sizeof(ebuf) - 1; 156 return(*pb = c); 157 } 158 159 pbstr(s) 160 char *s; 161 { 162 int n; 163 164 n = strlen(s); 165 while (--n >= 0) 166 unput(s[n]); 167 } 168 169 yyerror(s, s1, s2, s3, s4) 170 char *s, *s1, *s2, *s3, *s4; 171 { 172 if (synerr) 173 return; 174 fprintf(stderr, "pic: "); 175 fprintf(stderr, s, s1, s2, s3, s4); 176 fprintf(stderr, " near line %d, file %s\n", lineno, filename); 177 eprint(); 178 synerr = 1; 179 } 180 181 eprint() /* try to print context around error */ 182 { 183 char *p, *q; 184 int c; 185 186 p = ep - 1; 187 if (p > ebuf && *p == '\n') 188 p--; 189 for ( ; p >= ebuf && *p != '\n'; p--) 190 ; 191 while (*p == '\n') 192 p++; 193 fprintf(stderr, " context is\n\t"); 194 while (p < ep) 195 putc(*p++, stderr); 196 fprintf(stderr, " ^ "); 197 while (pb >= pbuf) 198 putc(*pb--, stderr); 199 fgets(ebuf, sizeof ebuf, yyin); 200 fprintf(stderr, "%s", ebuf); 201 pbstr(".PE\n"); /* safety first */ 202 ep = ebuf; 203 } 204 205 yywrap() {;} 206