main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. #include <stdio.h>
  2. #if __STDC__
  3. #include <stdlib.h>
  4. #include <locale.h>
  5. #else
  6. #include <malloc.h>
  7. #endif
  8. #include <ctype.h>
  9. #include <string.h>
  10. #include <time.h>
  11. #include "cc.h"
  12. #define MAXINCPATH 5
  13. int main P((int argc, char ** argv));
  14. void undefine_macro P((char * name));
  15. void define_macro P((char * name));
  16. void print_toks_cpp P((void));
  17. void print_toks_raw P((void));
  18. void define_macro P((char *));
  19. void undefine_macro P((char *));
  20. void cmsg P((char * mtype, char * str));
  21. char * token_txn P((int));
  22. void pr_indent P((int));
  23. void hash_line P((void));
  24. char * include_paths[MAXINCPATH];
  25. char last_name[512] = "";
  26. int last_line = -1;
  27. int debug_mode = 0;
  28. int p_flag = 0;
  29. int exit_code = 0;
  30. char * outfile = 0;
  31. FILE * ofd = 0;
  32. int
  33. main(argc, argv)
  34. int argc;
  35. char ** argv;
  36. {
  37. int ar, i;
  38. char * p;
  39. static char Usage[] = "Usage: cpp -E -0 -Dxxx -Uxxx -Ixxx infile -o outfile";
  40. #ifdef LC_CTYPE
  41. setlocale(LC_CTYPE, "");
  42. #endif
  43. alltok = 1; /* Get all tokens from the cpp. */
  44. for(ar=1; ar<argc; ar++) if( argv[ar][0] == '-') switch(argv[ar][1])
  45. {
  46. case 'd': debug_mode++; break;
  47. case 'T': alltok = 0; break;
  48. case 'A': dialect = DI_ANSI; break;
  49. case 'K': dialect = DI_KNR; break;
  50. /* Some options for describing the code generator. */
  51. case '0': define_macro("__BCC__");
  52. define_macro("__AS386_16__");
  53. define_macro("__8086__");
  54. break;
  55. case '3': define_macro("__BCC__");
  56. define_macro("__AS386_32__");
  57. define_macro("__i386__");
  58. break;
  59. case 'c': define_macro("__CALLER_SAVES__");
  60. break;
  61. case 'f': define_macro("__FIRST_ARG_IN_AX__");
  62. break;
  63. case 'O': define_macro("__OPTIMISED__");
  64. break;
  65. case 'C': /* Keep comments. */
  66. cwarn("-C not implemented");
  67. break;
  68. case 'P': p_flag++;
  69. break;
  70. case 'I':
  71. if (argv[ar][2]) p=argv[ar]+2;
  72. else {
  73. ar++;
  74. if (ar>=argc) cfatal(Usage);
  75. p = argv[ar];
  76. }
  77. for(i=0; i<MAXINCPATH; i++)
  78. if (!include_paths[i]) {
  79. include_paths[i] = p;
  80. break;
  81. }
  82. if (i>=MAXINCPATH)
  83. cfatal("Too many items in include path for CPP");
  84. break;
  85. case 'D':
  86. if (argv[ar][2]) p=argv[ar]+2;
  87. else {
  88. ar++;
  89. if (ar>=argc) cfatal(Usage);
  90. p = argv[ar];
  91. }
  92. define_macro(p);
  93. break;
  94. case 'U':
  95. if (argv[ar][2]) p=argv[ar]+2;
  96. else {
  97. ar++;
  98. if (ar>=argc) cfatal(Usage);
  99. p = argv[ar];
  100. }
  101. undefine_macro(p);
  102. break;
  103. case 'o':
  104. if (argv[ar][2]) p=argv[ar]+2;
  105. else {
  106. ar++;
  107. if (ar>=argc) cfatal(Usage);
  108. p = argv[ar];
  109. }
  110. if (outfile) cfatal(Usage);
  111. outfile = p;
  112. break;
  113. default:
  114. fprintf(stderr, "CPP Unknown option %s\n", argv[ar]);
  115. cfatal(Usage);
  116. } else if (!curfile) {
  117. /* Input file */
  118. curfile = fopen(argv[ar], "r");
  119. c_fname = argv[ar]; c_lineno = 1;
  120. if (!curfile)
  121. cfatal("Cannot open input file");
  122. } else
  123. cfatal(Usage);
  124. if (!curfile)
  125. cfatal(Usage);
  126. /* Define date and time macros. */
  127. if (dialect != DI_KNR) {
  128. time_t now;
  129. char * timep;
  130. char buf[128];
  131. time(&now);
  132. timep = ctime(&now);
  133. /* Yes, well */
  134. sprintf(buf, "__TIME__=\"%.8s\"", timep + 11);
  135. define_macro(buf);
  136. /* US order; Seems to be mandated by standard. */
  137. sprintf(buf, "__DATE__=\"%.3s %.2s %.4s\"", timep + 4, timep + 8, timep + 20);
  138. define_macro(buf);
  139. }
  140. if (outfile) ofd = fopen(outfile, "w");
  141. else ofd = stdout;
  142. if (!ofd)
  143. cfatal("Cannot open output file");
  144. if (debug_mode)
  145. print_toks_raw();
  146. else
  147. print_toks_cpp();
  148. if (outfile) fclose(ofd);
  149. exit(exit_code);
  150. }
  151. void
  152. undefine_macro(name)
  153. char * name;
  154. {
  155. struct define_item * ptr;
  156. ptr = read_entry(0, name);
  157. if (ptr) {
  158. set_entry(0, name, (void*)0);
  159. if (!ptr->in_use) free(ptr);
  160. }
  161. }
  162. void
  163. define_macro(name)
  164. char * name;
  165. {
  166. char * p;
  167. char * value;
  168. struct define_item * ptr;
  169. if ((p=strchr(name, '=')) != 0) {
  170. *p = 0;
  171. value = p+1;
  172. } else
  173. value = "1";
  174. undefine_macro(name);
  175. ptr = malloc(sizeof(struct define_item) + strlen(value));
  176. ptr->name = set_entry(0, name, ptr);
  177. strcpy(ptr->value, value);
  178. ptr->arg_count = -1;
  179. ptr->in_use = 0;
  180. ptr->next = 0;
  181. }
  182. FILE *
  183. open_include(fname, mode, checkrel)
  184. char * fname;
  185. char * mode;
  186. int checkrel;
  187. {
  188. FILE * fd = 0;
  189. int i;
  190. char buf[256], *p;
  191. if( checkrel )
  192. {
  193. strcpy(buf, c_fname);
  194. p = strrchr(buf, '/');
  195. if (p) *++p = 0; else *(p=buf) = 0;
  196. strcpy(p, fname);
  197. fd=fopen(buf, mode);
  198. }
  199. if (!fd) {
  200. for(i=0; i<MAXINCPATH; i++)
  201. if (include_paths[i]) {
  202. strcpy(buf, include_paths[i]);
  203. if (buf[strlen(buf)-1] != '/') strcat(buf, "/");
  204. strcat(buf, fname);
  205. fd=fopen(buf, mode);
  206. if( fd ) break;
  207. }
  208. }
  209. if (!fd) return fd;
  210. c_fname = strdup(buf);
  211. c_lineno = 1;
  212. return fd;
  213. }
  214. /*----------------------------------------------------------------------*/
  215. static int outpos = 0;
  216. void
  217. cmsg(mtype, str)
  218. char * mtype;
  219. char * str;
  220. {
  221. if (c_fname && (*c_fname || c_lineno))
  222. fprintf(stderr, "%s:%d: ", c_fname, c_lineno);
  223. if (mtype && *mtype)
  224. fprintf(stderr, "%s: %s\n", mtype, str);
  225. else
  226. fprintf(stderr, "%s\n", str);
  227. }
  228. void
  229. cfatal(str)
  230. char * str;
  231. {
  232. cmsg("CPP-FATAL error", str);
  233. exit(255);
  234. }
  235. void
  236. cerror(str)
  237. char * str;
  238. {
  239. exit_code = 1;
  240. cmsg("error", str);
  241. }
  242. void
  243. cwarn(str)
  244. char * str;
  245. {
  246. cmsg("warning", str);
  247. }
  248. void
  249. pr_indent(count)
  250. int count;
  251. {
  252. if(count>10) count=10;
  253. while(count>0) {fprintf(ofd, "\t"); count--; }
  254. }
  255. void
  256. hash_line()
  257. {
  258. if( strcmp(last_name, c_fname) != 0 ) last_line = -1;
  259. if( c_lineno != last_line || last_line <= 0 )
  260. {
  261. if( outpos != 0 ) {
  262. fputc('\n', ofd); outpos=0;
  263. if (last_line > 0) last_line++;
  264. }
  265. while( c_lineno > last_line &&
  266. (p_flag || c_lineno < last_line+4) &&
  267. last_line > 0 &&
  268. !debug_mode )
  269. {
  270. fputc('\n', ofd); last_line++;
  271. }
  272. if( !p_flag && (c_lineno != last_line || last_line <= 0 ))
  273. {
  274. fprintf(ofd, "# %d", c_lineno);
  275. if( last_line <= 0 ) fprintf(ofd, " \"%s\"", c_fname);
  276. fprintf(ofd, "\n");
  277. }
  278. strcpy(last_name, c_fname);
  279. last_line = c_lineno;
  280. }
  281. }
  282. void
  283. print_toks_cpp()
  284. {
  285. int i;
  286. int indent=0;
  287. int paren=0;
  288. hash_line();
  289. while( (i=gettok()) != EOF )
  290. {
  291. hash_line();
  292. switch(i)
  293. {
  294. case '\n':
  295. cwarn("newline received from tokeniser!");
  296. break;
  297. case TK_STR:
  298. outpos += fprintf(ofd, "%s", curword);
  299. break;
  300. case TK_COPY:
  301. if( outpos ) { fputc('\n', ofd); last_line++; }
  302. outpos = 0; last_line++;
  303. fprintf(ofd, "#%s\n", curword);
  304. break;
  305. case TK_FILE: sprintf(curword, "\"%s\"", c_fname); if(0) {
  306. case TK_LINE: sprintf(curword, "%d", c_lineno);
  307. }
  308. /*FALLTHROUGH*/
  309. default:
  310. if (!alltok) {
  311. if(i == '}' || i == TK_CASE || i == TK_DEFAULT ) indent--;
  312. if(i ==')') paren--;
  313. if(outpos) { fputc(' ', ofd); outpos++; }
  314. else pr_indent(indent+(paren!=0));
  315. if(i == '{' || i == TK_CASE || i == TK_DEFAULT ) indent++;
  316. if(i ==';') paren=0;
  317. if(i =='(') paren++;
  318. }
  319. outpos += fprintf(ofd, "%s", curword);
  320. if ( i == '"' || i == '\'' )
  321. {
  322. while((i=gettok()) == TK_STR) {
  323. outpos += fprintf(ofd, "%s", curword);
  324. }
  325. if (i != '\n')
  326. outpos += fprintf(ofd, "%s", curword);
  327. }
  328. break;
  329. }
  330. }
  331. if( outpos ) fputc('\n', ofd);
  332. outpos = 0;
  333. }
  334. void
  335. print_toks_raw()
  336. {
  337. int i;
  338. long val;
  339. hash_line();
  340. while( (i=gettok()) != EOF )
  341. {
  342. hash_line();
  343. switch(i)
  344. {
  345. case '"': case '\'':
  346. if (debug_mode < 2) {
  347. fprintf(ofd, "%-16s: %s", "Quoted string", curword);
  348. while((i=gettok()) == TK_STR)
  349. outpos+= fprintf(ofd, "%s", curword);
  350. if ( i == '\n' ) fprintf(ofd, " --> EOL!!\n");
  351. else outpos+= fprintf(ofd, "%s\n", curword);
  352. break;
  353. }
  354. /*FALLTHROUGH*/
  355. default: fprintf(ofd, "%-16s: '", token_txn(i));
  356. {
  357. char *p;
  358. for(p=curword; *p; p++)
  359. if(isprint(*p) && *p != '\'' && *p != '\\')
  360. fputc(*p, ofd);
  361. else if (*p == '\n') fprintf(ofd, "\\n");
  362. else if (*p == '\t') fprintf(ofd, "\\t");
  363. else if (*p == '\v') fprintf(ofd, "\\v");
  364. else if (*p == '\b') fprintf(ofd, "\\b");
  365. else if (*p == '\r') fprintf(ofd, "\\r");
  366. else if (*p == '\f') fprintf(ofd, "\\f");
  367. else if (*p == '\a') fprintf(ofd, "\\a");
  368. else
  369. fprintf(ofd, "\\x%02x", (unsigned char)*p);
  370. }
  371. fprintf(ofd, "'\n");
  372. break;
  373. case TK_NUM:
  374. val = strtoul(curword, (void*)0, 0);
  375. fprintf(ofd, "%-16s: ", token_txn(i));
  376. fprintf(ofd, "%s => %ld\n", curword, val);
  377. break;
  378. case TK_COPY:
  379. fprintf(ofd, "%-16s: ", token_txn(i));
  380. fprintf(ofd, "#%s\n", curword);
  381. break;
  382. case '\n':
  383. fprintf(ofd, "%-16s:\n", "Newline char");
  384. break;
  385. }
  386. }
  387. }
  388. char *
  389. token_txn(token)
  390. int token;
  391. {
  392. char * s = "UNKNOWN";
  393. static char buf[17];
  394. if (token> ' ' && token <= '~')
  395. {
  396. sprintf(buf, "TK_CHAR('%c')", token);
  397. return buf;
  398. }
  399. if (token >= 0 && token < 0x100)
  400. {
  401. sprintf(buf, "TK_CHAR(%d)", token);
  402. return buf;
  403. }
  404. switch(token)
  405. {
  406. case TK_WSPACE : s="TK_WSPACE"; break;
  407. case TK_WORD : s="TK_WORD"; break;
  408. case TK_NUM : s="TK_NUM"; break;
  409. case TK_FLT : s="TK_FLT"; break;
  410. case TK_QUOT : s="TK_QUOT"; break;
  411. case TK_STR : s="TK_STR"; break;
  412. case TK_FILE : s="TK_FILE"; break;
  413. case TK_LINE : s="TK_LINE"; break;
  414. case TK_COPY : s="TK_COPY"; break;
  415. case TK_NE_OP : s="TK_NE_OP"; break;
  416. case TK_MOD_ASSIGN : s="TK_MOD_ASSIGN"; break;
  417. case TK_AND_OP : s="TK_AND_OP"; break;
  418. case TK_AND_ASSIGN : s="TK_AND_ASSIGN"; break;
  419. case TK_MUL_ASSIGN : s="TK_MUL_ASSIGN"; break;
  420. case TK_INC_OP : s="TK_INC_OP"; break;
  421. case TK_ADD_ASSIGN : s="TK_ADD_ASSIGN"; break;
  422. case TK_DEC_OP : s="TK_DEC_OP"; break;
  423. case TK_SUB_ASSIGN : s="TK_SUB_ASSIGN"; break;
  424. case TK_PTR_OP : s="TK_PTR_OP"; break;
  425. case TK_ELLIPSIS : s="TK_ELLIPSIS"; break;
  426. case TK_DIV_ASSIGN : s="TK_DIV_ASSIGN"; break;
  427. case TK_LEFT_OP : s="TK_LEFT_OP"; break;
  428. case TK_LEFT_ASSIGN : s="TK_LEFT_ASSIGN"; break;
  429. case TK_LE_OP : s="TK_LE_OP"; break;
  430. case TK_EQ_OP : s="TK_EQ_OP"; break;
  431. case TK_GE_OP : s="TK_GE_OP"; break;
  432. case TK_RIGHT_OP : s="TK_RIGHT_OP"; break;
  433. case TK_RIGHT_ASSIGN : s="TK_RIGHT_ASSIGN"; break;
  434. case TK_XOR_ASSIGN : s="TK_XOR_ASSIGN"; break;
  435. case TK_OR_ASSIGN : s="TK_OR_ASSIGN"; break;
  436. case TK_OR_OP : s="TK_OR_OP"; break;
  437. case TK_AUTO : s="TK_AUTO"; break;
  438. case TK_BREAK : s="TK_BREAK"; break;
  439. case TK_CASE : s="TK_CASE"; break;
  440. case TK_CHAR : s="TK_CHAR"; break;
  441. case TK_CONST : s="TK_CONST"; break;
  442. case TK_CONTINUE : s="TK_CONTINUE"; break;
  443. case TK_DEFAULT : s="TK_DEFAULT"; break;
  444. case TK_DO : s="TK_DO"; break;
  445. case TK_DOUBLE : s="TK_DOUBLE"; break;
  446. case TK_ELSE : s="TK_ELSE"; break;
  447. case TK_ENUM : s="TK_ENUM"; break;
  448. case TK_EXTERN : s="TK_EXTERN"; break;
  449. case TK_FLOAT : s="TK_FLOAT"; break;
  450. case TK_FOR : s="TK_FOR"; break;
  451. case TK_GOTO : s="TK_GOTO"; break;
  452. case TK_IF : s="TK_IF"; break;
  453. case TK_INT : s="TK_INT"; break;
  454. case TK_LONG : s="TK_LONG"; break;
  455. case TK_REGISTER : s="TK_REGISTER"; break;
  456. case TK_RETURN : s="TK_RETURN"; break;
  457. case TK_SHORT : s="TK_SHORT"; break;
  458. case TK_SIGNED : s="TK_SIGNED"; break;
  459. case TK_SIZEOF : s="TK_SIZEOF"; break;
  460. case TK_STATIC : s="TK_STATIC"; break;
  461. case TK_STRUCT : s="TK_STRUCT"; break;
  462. case TK_SWITCH : s="TK_SWITCH"; break;
  463. case TK_TYPEDEF : s="TK_TYPEDEF"; break;
  464. case TK_UNION : s="TK_UNION"; break;
  465. case TK_UNSIGNED : s="TK_UNSIGNED"; break;
  466. case TK_VOID : s="TK_VOID"; break;
  467. case TK_VOLATILE : s="TK_VOLATILE"; break;
  468. case TK_WHILE : s="TK_WHILE"; break;
  469. }
  470. return s;
  471. }