input.c 5.3 KB

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