preprocess.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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. void Xflush()
  29. {
  30. sys_write(STDOUT, _obuf, OBUFSIZE);
  31. }
  32. extern char options[];
  33. /* #pragma directives are saved here and passed to the compiler later on.
  34. */
  35. struct prag_info {
  36. int pr_linnr;
  37. char *pr_fil;
  38. char *pr_text;
  39. };
  40. static struct prag_info *pragma_tab;
  41. static int pragma_nr;
  42. static char *SkipComment(char *op, int *lineno);
  43. void preprocess(char *fn);
  44. void do_pragma()
  45. {
  46. int size = ITEXTSIZE;
  47. char *cur_line = Malloc((unsigned)size);
  48. char *c_ptr = cur_line;
  49. int c = GetChar();
  50. int delim = 0;
  51. while(c != '\n') {
  52. if (c_ptr + 1 - cur_line == size) {
  53. cur_line = Realloc(cur_line, (unsigned)(size + ITEXTSIZE));
  54. c_ptr = cur_line + size - 1;
  55. size += ITEXTSIZE;
  56. }
  57. if (delim) {
  58. if (c == delim) {
  59. delim = 0;
  60. }
  61. else if (c == '\\') {
  62. *c_ptr++ = c;
  63. c = GetChar();
  64. if (c == '\n') break;
  65. }
  66. }
  67. else if (c == '\'' || c == '"') {
  68. delim = c;
  69. }
  70. else if (c == '/') {
  71. if ((c = GetChar()) != '*' || InputLevel) {
  72. *c_ptr++ = '/';
  73. }
  74. else {
  75. skipcomment();
  76. continue;
  77. }
  78. }
  79. *c_ptr++ = c;
  80. c = GetChar();
  81. }
  82. *c_ptr = '\0';
  83. if (!pragma_nr) {
  84. pragma_tab = (struct prag_info *)Malloc(sizeof(struct prag_info));
  85. } else {
  86. pragma_tab = (struct prag_info *)Realloc((char *)pragma_tab
  87. , (unsigned)(sizeof(struct prag_info) * (pragma_nr+1)));
  88. }
  89. if (delim) {
  90. error("unclosed opening %c", delim);
  91. }
  92. pragma_tab[pragma_nr].pr_linnr = LineNumber;
  93. pragma_tab[pragma_nr].pr_fil = FileName;
  94. pragma_tab[pragma_nr].pr_text = cur_line;
  95. pragma_nr++;
  96. LineNumber++;
  97. }
  98. char Xbuf[256];
  99. void preprocess(char *fn)
  100. {
  101. int c;
  102. char *op = _obuf;
  103. 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. 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. 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(*(unsigned char *)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. int i = 0;
  151. int LiNo = LineNumber;
  152. char *FiNam = FileName;
  153. while (i < pragma_nr) {
  154. 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. 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. char *tg = &buf[0];
  305. char *maxpos = &buf[idfsize];
  306. 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 *SkipComment(char *op, int *lineno)
  384. {
  385. char *ob = &_obuf[OBUFSIZE];
  386. int c, oldc = '\0';
  387. NoUnstack++;
  388. if (options['C']) {
  389. echo('/');
  390. echo('*');
  391. }
  392. c = GetChar();
  393. for(;;) {
  394. if (c == EOI) {
  395. newline();
  396. flush((int)(op - _obuf));
  397. op = 0;
  398. break;
  399. }
  400. if (options['C']) {
  401. echo(c);
  402. }
  403. if (c == '\n') {
  404. ++LineNumber;
  405. ++*lineno;
  406. if (!options['C']) {
  407. echo(c);
  408. }
  409. }
  410. if (c == '*') {
  411. c = GetChar();
  412. if (c == '/') {
  413. if (options['C']) {
  414. echo(c);
  415. }
  416. break; /* for(;;) */
  417. } else if (oldc == '/') {
  418. warning("comment inside comment ?");
  419. }
  420. oldc = '*';
  421. } else {
  422. oldc = c;
  423. c = GetChar();
  424. }
  425. }
  426. NoUnstack--;
  427. return op;
  428. }