cpp.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <stdio.h>
  4. #include "cpp.h"
  5. #define OUTS 16384
  6. char outbuf[OUTS];
  7. char *outp = outbuf;
  8. Source *cursource;
  9. int nerrs;
  10. struct token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" };
  11. char *curtime;
  12. int incdepth;
  13. int ifdepth;
  14. int ifsatisfied[NIF];
  15. int skipping;
  16. int
  17. main(int argc, char **argv)
  18. {
  19. Tokenrow tr;
  20. long t;
  21. char ebuf[BUFSIZ];
  22. setbuf(stderr, ebuf);
  23. t = time(NULL);
  24. curtime = ctime(t);
  25. maketokenrow(3, &tr);
  26. expandlex();
  27. setup(argc, argv);
  28. fixlex();
  29. iniths();
  30. genline();
  31. process(&tr);
  32. flushout();
  33. fflush(stderr);
  34. exits(nerrs? "errors" : 0);
  35. return 0;
  36. }
  37. void
  38. process(Tokenrow *trp)
  39. {
  40. int anymacros = 0;
  41. for (;;) {
  42. if (trp->tp >= trp->lp) {
  43. trp->tp = trp->lp = trp->bp;
  44. outp = outbuf;
  45. anymacros |= gettokens(trp, 1);
  46. trp->tp = trp->bp;
  47. }
  48. if (trp->tp->type == END) {
  49. if (--incdepth>=0) {
  50. if (cursource->ifdepth)
  51. error(ERROR,
  52. "Unterminated conditional in #include");
  53. unsetsource();
  54. cursource->line += cursource->lineinc;
  55. trp->tp = trp->lp;
  56. genline();
  57. continue;
  58. }
  59. if (ifdepth)
  60. error(ERROR, "Unterminated #if/#ifdef/#ifndef");
  61. break;
  62. }
  63. if (trp->tp->type==SHARP) {
  64. trp->tp += 1;
  65. control(trp);
  66. } else if (!skipping && anymacros)
  67. expandrow(trp, NULL);
  68. if (skipping)
  69. setempty(trp);
  70. puttokens(trp);
  71. anymacros = 0;
  72. cursource->line += cursource->lineinc;
  73. if (cursource->lineinc>1) {
  74. genline();
  75. }
  76. }
  77. }
  78. void
  79. control(Tokenrow *trp)
  80. {
  81. Nlist *np;
  82. Token *tp;
  83. tp = trp->tp;
  84. if (tp->type!=NAME) {
  85. if (tp->type==NUMBER)
  86. goto kline;
  87. if (tp->type != NL)
  88. error(ERROR, "Unidentifiable control line");
  89. return; /* else empty line */
  90. }
  91. if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) {
  92. error(WARNING, "Unknown preprocessor control %t", tp);
  93. return;
  94. }
  95. if (skipping) {
  96. if ((np->flag&ISKW)==0)
  97. return;
  98. switch (np->val) {
  99. case KENDIF:
  100. if (--ifdepth<skipping)
  101. skipping = 0;
  102. --cursource->ifdepth;
  103. setempty(trp);
  104. return;
  105. case KIFDEF:
  106. case KIFNDEF:
  107. case KIF:
  108. if (++ifdepth >= NIF)
  109. error(FATAL, "#if too deeply nested");
  110. ++cursource->ifdepth;
  111. return;
  112. case KELIF:
  113. case KELSE:
  114. if (ifdepth<=skipping)
  115. break;
  116. return;
  117. default:
  118. return;
  119. }
  120. }
  121. switch (np->val) {
  122. case KDEFINE:
  123. dodefine(trp);
  124. break;
  125. case KUNDEF:
  126. tp += 1;
  127. if (tp->type!=NAME || trp->lp - trp->bp != 4) {
  128. error(ERROR, "Syntax error in #undef");
  129. break;
  130. }
  131. if ((np = lookup(tp, 0))) {
  132. if (np->flag&ISUNCHANGE) {
  133. error(ERROR, "#defined token %t can't be undefined", tp);
  134. return;
  135. }
  136. np->flag &= ~ISDEFINED;
  137. }
  138. break;
  139. case KPRAGMA:
  140. return;
  141. case KIFDEF:
  142. case KIFNDEF:
  143. case KIF:
  144. if (++ifdepth >= NIF)
  145. error(FATAL, "#if too deeply nested");
  146. ++cursource->ifdepth;
  147. ifsatisfied[ifdepth] = 0;
  148. if (eval(trp, np->val))
  149. ifsatisfied[ifdepth] = 1;
  150. else
  151. skipping = ifdepth;
  152. break;
  153. case KELIF:
  154. if (ifdepth==0) {
  155. error(ERROR, "#elif with no #if");
  156. return;
  157. }
  158. if (ifsatisfied[ifdepth]==2)
  159. error(ERROR, "#elif after #else");
  160. if (eval(trp, np->val)) {
  161. if (ifsatisfied[ifdepth])
  162. skipping = ifdepth;
  163. else {
  164. skipping = 0;
  165. ifsatisfied[ifdepth] = 1;
  166. }
  167. } else
  168. skipping = ifdepth;
  169. break;
  170. case KELSE:
  171. if (ifdepth==0 || cursource->ifdepth==0) {
  172. error(ERROR, "#else with no #if");
  173. return;
  174. }
  175. if (ifsatisfied[ifdepth]==2)
  176. error(ERROR, "#else after #else");
  177. if (trp->lp - trp->bp != 3)
  178. error(ERROR, "Syntax error in #else");
  179. skipping = ifsatisfied[ifdepth]? ifdepth: 0;
  180. ifsatisfied[ifdepth] = 2;
  181. break;
  182. case KENDIF:
  183. if (ifdepth==0 || cursource->ifdepth==0) {
  184. error(ERROR, "#endif with no #if");
  185. return;
  186. }
  187. --ifdepth;
  188. --cursource->ifdepth;
  189. if (trp->lp - trp->bp != 3)
  190. error(WARNING, "Syntax error in #endif");
  191. break;
  192. case KERROR:
  193. trp->tp = tp+1;
  194. error(WARNING, "#error directive: %r", trp);
  195. break;
  196. case KLINE:
  197. trp->tp = tp+1;
  198. expandrow(trp, "<line>");
  199. tp = trp->bp+2;
  200. kline:
  201. if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
  202. || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){
  203. error(ERROR, "Syntax error in #line");
  204. return;
  205. }
  206. cursource->line = atol((char*)tp->t)-1;
  207. if (cursource->line<0 || cursource->line>=32768)
  208. error(WARNING, "#line specifies number out of range");
  209. tp = tp+1;
  210. if (tp+1<trp->lp)
  211. cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
  212. return;
  213. case KDEFINED:
  214. error(ERROR, "Bad syntax for control line");
  215. break;
  216. case KINCLUDE:
  217. doinclude(trp);
  218. trp->lp = trp->bp;
  219. return;
  220. case KEVAL:
  221. eval(trp, np->val);
  222. break;
  223. default:
  224. error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
  225. break;
  226. }
  227. setempty(trp);
  228. return;
  229. }
  230. void *
  231. domalloc(int size)
  232. {
  233. void *p = malloc(size);
  234. if (p==NULL)
  235. error(FATAL, "Out of memory from malloc");
  236. return p;
  237. }
  238. void
  239. dofree(void *p)
  240. {
  241. free(p);
  242. }
  243. void
  244. error(enum errtype type, char *string, ...)
  245. {
  246. va_list ap;
  247. char *cp, *ep;
  248. Token *tp;
  249. Tokenrow *trp;
  250. Source *s;
  251. int i;
  252. void *p;
  253. fprintf(stderr, "cpp: ");
  254. for (s=cursource; s; s=s->next)
  255. if (*s->filename)
  256. fprintf(stderr, "%s:%d ", s->filename, s->line);
  257. va_start(ap, string);
  258. for (ep=string; *ep; ep++) {
  259. if (*ep=='%') {
  260. switch (*++ep) {
  261. case 's':
  262. cp = va_arg(ap, char *);
  263. fprintf(stderr, "%s", cp);
  264. break;
  265. case 'd':
  266. i = va_arg(ap, int);
  267. fprintf(stderr, "%d", i);
  268. break;
  269. case 'p':
  270. p = va_arg(ap, void *);
  271. fprintf(stderr, "%p", p);
  272. break;
  273. case 't':
  274. tp = va_arg(ap, Token *);
  275. fprintf(stderr, "%.*s", tp->len, tp->t);
  276. break;
  277. case 'r':
  278. trp = va_arg(ap, Tokenrow *);
  279. for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
  280. if (tp>trp->tp && tp->wslen)
  281. fputc(' ', stderr);
  282. fprintf(stderr, "%.*s", tp->len, tp->t);
  283. }
  284. break;
  285. default:
  286. fputc(*ep, stderr);
  287. break;
  288. }
  289. } else
  290. fputc(*ep, stderr);
  291. }
  292. va_end(ap);
  293. fputc('\n', stderr);
  294. if (type==FATAL)
  295. exits("error");
  296. if (type!=WARNING)
  297. nerrs = 1;
  298. fflush(stderr);
  299. }