preprocess.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. /* $Id$ */
  6. /* PREPROCESSOR DRIVER */
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <system.h>
  10. #include <alloc.h>
  11. #include "input.h"
  12. #include "obufsize.h"
  13. #include "arith.h"
  14. #include "LLlex.h"
  15. #include "class.h"
  16. #include "macro.h"
  17. #include "idf.h"
  18. #include "idfsize.h"
  19. #include "bits.h"
  20. #include "ln_prefix.h"
  21. #include "textsize.h"
  22. char _obuf[OBUFSIZE];
  23. #ifdef DOBITS
  24. char bits[128];
  25. #endif
  26. extern int InputLevel;
  27. extern char *sprint();
  28. Xflush()
  29. {
  30. sys_write(STDOUT, _obuf, OBUFSIZE);
  31. }
  32. static char *SkipComment();
  33. extern char options[];
  34. /* #pragma directives are saved here and passed to the compiler later on.
  35. */
  36. struct prag_info {
  37. int pr_linnr;
  38. char *pr_fil;
  39. char *pr_text;
  40. };
  41. static struct prag_info *pragma_tab;
  42. static int pragma_nr;
  43. do_pragma()
  44. {
  45. register int size = ITEXTSIZE;
  46. char *cur_line = Malloc((unsigned)size);
  47. register char *c_ptr = cur_line;
  48. register int c = GetChar();
  49. register int delim = 0;
  50. while(c != '\n') {
  51. if (c_ptr + 1 - cur_line == size) {
  52. cur_line = Realloc(cur_line, (unsigned)(size + ITEXTSIZE));
  53. c_ptr = cur_line + size - 1;
  54. size += ITEXTSIZE;
  55. }
  56. if (delim) {
  57. if (c == delim) {
  58. delim = 0;
  59. }
  60. else if (c == '\\') {
  61. *c_ptr++ = c;
  62. c = GetChar();
  63. if (c == '\n') break;
  64. }
  65. }
  66. else if (c == '\'' || c == '"') {
  67. delim = c;
  68. }
  69. else if (c == '/') {
  70. if ((c = GetChar()) != '*' || InputLevel) {
  71. *c_ptr++ = '/';
  72. }
  73. else {
  74. skipcomment();
  75. continue;
  76. }
  77. }
  78. *c_ptr++ = c;
  79. c = GetChar();
  80. }
  81. *c_ptr = '\0';
  82. if (!pragma_nr) {
  83. pragma_tab = (struct prag_info *)Malloc(sizeof(struct prag_info));
  84. } else {
  85. pragma_tab = (struct prag_info *)Realloc((char *)pragma_tab
  86. , (unsigned)(sizeof(struct prag_info) * (pragma_nr+1)));
  87. }
  88. if (delim) {
  89. error("unclosed opening %c", delim);
  90. }
  91. pragma_tab[pragma_nr].pr_linnr = LineNumber;
  92. pragma_tab[pragma_nr].pr_fil = FileName;
  93. pragma_tab[pragma_nr].pr_text = cur_line;
  94. pragma_nr++;
  95. LineNumber++;
  96. }
  97. char Xbuf[256];
  98. preprocess(fn)
  99. char *fn;
  100. {
  101. register int c;
  102. register char *op = _obuf;
  103. register char *ob = &_obuf[OBUFSIZE];
  104. int lineno = 0;
  105. int startline;
  106. #define flush(X) (sys_write(STDOUT,_obuf,X))
  107. #define echo(ch) if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch);
  108. #define newline() op--; while (op >= _obuf && (*op == ' ' || *op == '\t')) op--; op++; echo('\n')
  109. if (!options['P']) {
  110. /* Generate a line directive communicating the
  111. source filename
  112. */
  113. register char *p = Xbuf;
  114. sprint(p, "%s 1 \"%s\"\n",
  115. LINE_PREFIX,
  116. FileName);
  117. while (*p) {
  118. echo(*p++);
  119. }
  120. }
  121. #define do_line_dir(lineno, fn) \
  122. if (lineno != LineNumber || fn != FileName) { \
  123. fn = FileName; \
  124. lineno = LineNumber; \
  125. if (! options['P']) { \
  126. register char *p = Xbuf; \
  127. sprint(Xbuf, "%s %d \"%s\"\n", \
  128. LINE_PREFIX, \
  129. (int)LineNumber, \
  130. FileName); \
  131. op--; \
  132. while (op >= _obuf \
  133. && (class(*op) == STSKIP \
  134. || *op == '\n')) op--; \
  135. op++; \
  136. newline(); \
  137. while (*p) { \
  138. echo(*p++); \
  139. } \
  140. } \
  141. }
  142. for (;;) {
  143. LineNumber++;
  144. lineno++;
  145. startline = 1;
  146. c = GetChar();
  147. while (startline) {
  148. /* first flush the saved pragma's */
  149. if (pragma_nr) {
  150. register int i = 0;
  151. int LiNo = LineNumber;
  152. char *FiNam = FileName;
  153. while (i < pragma_nr) {
  154. register char *c_ptr = "#pragma";
  155. LineNumber = pragma_tab[i].pr_linnr;
  156. FileName = pragma_tab[i].pr_fil;
  157. do_line_dir(lineno, fn);
  158. while (*c_ptr) { echo(*c_ptr++); }
  159. c_ptr = pragma_tab[i].pr_text;
  160. while (*c_ptr) { echo(*c_ptr++); }
  161. newline(); lineno++;
  162. free(pragma_tab[i].pr_text);
  163. i++;
  164. }
  165. free((char *) pragma_tab);
  166. pragma_tab = (struct prag_info *)0;
  167. pragma_nr = 0;
  168. LineNumber = LiNo;
  169. FileName = FiNam;
  170. do_line_dir(lineno, fn);
  171. }
  172. while (class(c) == STSKIP || c == '/') {
  173. if (c == '/') {
  174. if (!InputLevel) {
  175. c = GetChar();
  176. if (c == '*') {
  177. op = SkipComment(op, &lineno);
  178. if (!op) return;
  179. if (!options['C']) { echo(' '); }
  180. c = GetChar();
  181. continue;
  182. }
  183. UnGetChar();
  184. c = '/';
  185. }
  186. break;
  187. }
  188. echo(c);
  189. c = GetChar();
  190. }
  191. if (c == '#') {
  192. domacro();
  193. lineno++;
  194. newline();
  195. do_line_dir(lineno, fn);
  196. c = GetChar();
  197. } else startline = 0;
  198. }
  199. do_line_dir(lineno, fn);
  200. for (;;) {
  201. /* illegal character */
  202. if (c & 0200) {
  203. if (c == EOI) {
  204. newline();
  205. flush((int)(op-_obuf));
  206. return;
  207. }
  208. fatal("non-ascii character read");
  209. }
  210. /* comments */
  211. if (c == '/' && !InputLevel) {
  212. c = GetChar();
  213. if (c == '*') {
  214. op = SkipComment(op, &lineno);
  215. if (!op) return;
  216. if (!options['C']) { echo(' '); }
  217. c = GetChar();
  218. continue;
  219. }
  220. echo('/');
  221. continue;
  222. }
  223. /* switch on character */
  224. switch(class(c)) {
  225. case STNL:
  226. newline();
  227. break;
  228. case STSTR:
  229. case STCHAR:
  230. {
  231. register int stopc = c;
  232. int escaped;
  233. do {
  234. escaped = 0;
  235. echo(c);
  236. c = GetChar();
  237. if (c == '\n') {
  238. /* the compiler will complain */
  239. break;
  240. }
  241. else if (c == EOI) {
  242. newline();
  243. flush((int)(op-_obuf));
  244. return;
  245. }
  246. if (c == '\\') {
  247. echo(c);
  248. c = GetChar();
  249. if (c == '\n') {
  250. ++LineNumber;
  251. lineno++;
  252. } else escaped = 1;
  253. }
  254. } while (escaped || c != stopc);
  255. echo(c);
  256. if (c == '\n')
  257. break; /* Don't eat # */
  258. c = GetChar();
  259. continue;
  260. }
  261. case STNUM:
  262. /* The following code is quit ugly. This because
  263. * ..3 == . .3 , whereas ...3 == ... 3
  264. */
  265. echo(c);
  266. if (c == '.') {
  267. c = GetChar();
  268. if (c == '.') {
  269. if ((c = GetChar()) == '.') {
  270. echo('.'); echo('.');
  271. c = GetChar();
  272. continue;
  273. }
  274. UnGetChar();
  275. c = '.';
  276. continue;
  277. } else if (!is_dig(c)) {
  278. continue;
  279. } else { echo(c); }
  280. }
  281. c = GetChar();
  282. while (in_idf(c) || c == '.') {
  283. echo(c);
  284. if (c == 'e' || c == 'E') {
  285. c = GetChar();
  286. if (c == '+' || c == '-') {
  287. echo(c);
  288. c = GetChar();
  289. }
  290. } else c = GetChar();
  291. }
  292. continue;
  293. case STELL:
  294. c = GetChar();
  295. UnGetChar();
  296. if (c == '"' || c == '\'') {
  297. echo('L');
  298. continue;
  299. }
  300. c = 'L';
  301. case STIDF: {
  302. extern int idfsize; /* ??? */
  303. char buf[IDFSIZE + 1];
  304. register char *tg = &buf[0];
  305. register char *maxpos = &buf[idfsize];
  306. register struct idf *idef;
  307. int NoExpandNext = 0;
  308. #define tstmac(bx) if (!(bits[c] & bx)) goto nomac
  309. #define cpy *tg++ = c
  310. #define load c = GetChar(); if (!in_idf(c)) goto endidf
  311. /* unstack macro's when allowed. */
  312. if (Unstacked)
  313. EnableMacros();
  314. if (c == NOEXPM) {
  315. NoExpandNext = 1;
  316. c = GetChar();
  317. }
  318. #ifdef DOBITS
  319. cpy; tstmac(bit0); load;
  320. cpy; tstmac(bit1); load;
  321. cpy; tstmac(bit2); load;
  322. cpy; tstmac(bit3); load;
  323. cpy; tstmac(bit4); load;
  324. cpy; tstmac(bit5); load;
  325. cpy; tstmac(bit6); load;
  326. cpy; tstmac(bit7); load;
  327. #endif
  328. for(;;) {
  329. if (tg < maxpos) {
  330. cpy;
  331. }
  332. load;
  333. }
  334. endidf:
  335. if (c != EOF) UnGetChar();
  336. *tg = '\0'; /* mark the end of the identifier */
  337. if ((idef = findidf(buf))
  338. && idef->id_macro
  339. && ReplaceMacros && !NoExpandNext) {
  340. if (replace(idef)) {
  341. echo(' ');
  342. c = GetChar();
  343. continue;
  344. }
  345. tg = buf;
  346. while (*tg) {
  347. echo(*tg++);
  348. }
  349. c = GetChar();
  350. if (in_idf(c)) { echo(' '); }
  351. continue;
  352. }
  353. nomac:
  354. *tg = '\0';
  355. tg = buf;
  356. while (*tg) {
  357. echo(*tg++);
  358. }
  359. c = GetChar();
  360. while (in_idf(c)) {
  361. echo(c);
  362. c = GetChar();
  363. }
  364. continue;
  365. }
  366. case STMSPEC:
  367. if (InputLevel) {
  368. echo(' '); /* seperate tokens */
  369. c = GetChar();
  370. continue;
  371. }
  372. /* else fallthrough */
  373. default:
  374. echo(c);
  375. c = GetChar();
  376. continue;
  377. }
  378. break;
  379. }
  380. }
  381. /*NOTREACHED*/
  382. }
  383. static char *
  384. SkipComment(op, lineno)
  385. char *op;
  386. int *lineno;
  387. {
  388. char *ob = &_obuf[OBUFSIZE];
  389. register int c, oldc = '\0';
  390. NoUnstack++;
  391. if (options['C']) {
  392. echo('/');
  393. echo('*');
  394. }
  395. c = GetChar();
  396. for(;;) {
  397. if (c == EOI) {
  398. newline();
  399. flush((int)(op - _obuf));
  400. op = 0;
  401. break;
  402. }
  403. if (options['C']) {
  404. echo(c);
  405. }
  406. if (c == '\n') {
  407. ++LineNumber;
  408. ++*lineno;
  409. if (!options['C']) {
  410. echo(c);
  411. }
  412. }
  413. if (c == '*') {
  414. c = GetChar();
  415. if (c == '/') {
  416. if (options['C']) {
  417. echo(c);
  418. }
  419. break; /* for(;;) */
  420. } else if (oldc == '/') {
  421. warning("comment inside comment ?");
  422. }
  423. oldc = '*';
  424. } else {
  425. oldc = c;
  426. c = GetChar();
  427. }
  428. }
  429. NoUnstack--;
  430. return op;
  431. }