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