preprocess.c 8.7 KB

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