CMAIN.C
上传用户:hlzzc88
上传日期:2007-01-06
资源大小:220k
文件大小:13k
源码类别:

编译器/解释器

开发平台:

Others

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1997, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and either the original sources or derived sources 
  11.  * are distributed along with any executables derived from the originals.
  12.  *
  13.  * The author is not responsible for any damages that may arise from use
  14.  * of this software, either idirect or consequential.
  15.  *
  16.  * v1.35 March 1997
  17.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  18.  *
  19.  * Credits to Mathew Brandt for original K&R C compiler
  20.  *
  21.  */
  22. /*
  23.  * The following symbols must be defined on the compile command line:
  24.  *    PROGNAME
  25.  *    ENVNAME
  26.  *    GLBDEFINE
  27.  *   SOURCEXT
  28.  */
  29. #include        <stdio.h>
  30. #include <malloc.h>
  31. #include  <string.h>
  32. #include  <setjmp.h>
  33. #include <signal.h>
  34. #include <stdlib.h>
  35. #include "utype.h"
  36. #include "cmdline.h"
  37. #include        "expr.h"
  38. #include "errors.h"
  39. #include        "c.h"
  40. #include  "diag.h"
  41. #define VERSION 151
  42. typedef struct list {
  43. struct list *link;
  44. void *data;
  45. } LIST;
  46. extern char GLBDEFINE[],SOURCEXT[],ENVNAME[],PROGNAME[];
  47. extern ERRORS *errlist;
  48. extern TABLE    tagtable;
  49. extern int      total_errors;
  50. extern int diagcount;
  51. extern char *errfile;
  52. extern TABLE gsyms;
  53. FILE            *inputFile = 0, *listFile = 0, *outputFile = 0, *cppFile = 0, *errFile = 0;
  54. int stoponerr = 0;
  55. LIST *clist = 0;
  56. LIST *deflist = 0;
  57. int prm_linkreg = TRUE;
  58. int prm_stackcheck = FALSE;
  59. int prm_warning = TRUE;
  60. #ifdef OBJEXT
  61. int prm_asmfile = FALSE;
  62. #else
  63. int prm_asmfile = TRUE;
  64. #endif
  65. int prm_ansi = FALSE;
  66. int prm_listfile = FALSE;
  67. int prm_maxerr = 25;
  68. int prm_diag = FALSE;
  69. int prm_bss = TRUE;
  70. int prm_cppfile = FALSE;
  71. int prm_packing = FALSE;
  72. int prm_revbits = FALSE;
  73. int prm_lines = TRUE;
  74. int prm_cplusplus = FALSE;
  75. int prm_cmangle = TRUE;
  76. int basear = 1, basedr = 1, basefr = 1;
  77. int prm_debug = FALSE;
  78. int version = VERSION;
  79. int prm_errfile = FALSE;
  80. char *prm_searchpath = 0;
  81. jmp_buf ctrlcreturn;
  82. int file_count = 0;
  83. char     *infile, listfile[40],outfile[40],cppfile[40],errorfile[40];
  84. void bool_setup(char select, char *string);
  85. void err_setup(char select, char *string);
  86. void incl_setup(char select, char *string);
  87. void def_setup(char select, char *string);
  88. void codegen_setup(char select, char *string);
  89. void optimize_setup(char select, char *string);
  90. void warning_setup(char select, char *string);
  91. void parsefile(char select, char *string);
  92. /* setup for ARGS.C */
  93. ARGLIST ArgList[] = {
  94.   { 'i', ARG_BOOL, bool_setup },
  95.   { 'e', ARG_BOOL, bool_setup },
  96.   { 'f', ARG_CONCATSTRING, parsefile },
  97.   { 'l', ARG_BOOL, bool_setup },
  98. #ifdef OBJEXT
  99.   { 'v', ARG_BOOL, bool_setup },
  100. #endif
  101.   { 'w', ARG_CONCATSTRING, warning_setup },
  102.   { 'A', ARG_BOOL, bool_setup },
  103.   { 'C', ARG_CONCATSTRING, codegen_setup },
  104.   { 'O', ARG_CONCATSTRING, optimize_setup },
  105.   { 'E', ARG_CONCATSTRING, err_setup },
  106.   { 'I', ARG_CONCATSTRING, incl_setup },
  107. { 'D', ARG_CONCATSTRING, def_setup },
  108. #ifdef OBJEXT
  109.   { 'S', ARG_BOOL, bool_setup },
  110. #endif
  111.   { 0, 0, 0 }
  112. };
  113. void bool_setup(char select, char *string)
  114. /*
  115.  * activation routine (callback) for boolean command line arguments
  116.  */
  117. {
  118. int bool = (int)string;
  119. if (select == 'S')
  120. prm_asmfile = bool;
  121.   if (select == 'l')
  122. prm_listfile = bool;
  123. if (select == 'i')
  124. prm_cppfile = bool;
  125. if (select == 'e')
  126. prm_errfile = bool;
  127. if (select == 'v')
  128. prm_debug = bool;
  129. if (select == 'A')
  130. prm_ansi = bool;
  131. }
  132. void codegen_setup(char select, char *string)
  133. /*
  134.  * activation for code-gen type command line arguments
  135.  */
  136. {
  137. int bool = TRUE;
  138. while (*string) {
  139. switch (*string) {
  140. case 'd':
  141. prm_diag = bool;
  142. break;
  143. case 'p':
  144. prm_packing = bool;
  145. break;
  146. case 'r':
  147. prm_revbits = bool;
  148. break;
  149. case 'b':
  150. prm_bss=bool;
  151. break;
  152. case 'l':
  153. prm_lines = bool;
  154. break;
  155. case 'm':
  156. prm_cmangle = bool;
  157. break;
  158. case 'S':
  159. prm_stackcheck = bool;
  160. break;
  161. case 'R':
  162. prm_linkreg = bool;
  163. break;
  164. case '-':
  165. bool = FALSE;
  166. break;
  167. case '+':
  168. bool = TRUE;
  169. break;
  170. default:
  171. if (!confcodegen(*string,bool)) 
  172. fatal("Illegal codegen parameter ");
  173. }
  174. string++;
  175. }
  176. }
  177. void optimize_setup(char select, char *string)
  178. /*
  179.  * activation for optimizer command line arguments
  180.  */
  181. {
  182. int bool = TRUE;
  183. while (*string) {
  184. switch (*string) {
  185. case 'R':
  186. string++;
  187. while (*string && *string != '+' && *string != '-') {
  188. switch (*string++) {
  189. case 'a':
  190. basear = bool;
  191. break;
  192. case 'd':
  193. basedr = bool;
  194. break;
  195. case 'f':
  196. basefr = bool;
  197. break;
  198. default:
  199. goto errorx;
  200. }
  201. if (!*string)
  202. return;
  203. }
  204. break;
  205. case '-':
  206. bool = FALSE;
  207. break;
  208. case '+':
  209. bool = TRUE;
  210. break;
  211. default:
  212. errorx:
  213. fatal("Illegal optimizer parameter");
  214. }
  215. string++;
  216. }
  217. }
  218. void err_setup(char select, char *string)
  219. /*
  220.  * activation for the max errs argument
  221.  */
  222. {
  223. prm_maxerr = atoi(string);
  224. }
  225. void incl_setup(char select, char * string)
  226. /*
  227.  * activation for include paths
  228.  */
  229. {
  230. if (prm_searchpath)
  231. prm_searchpath = realloc(prm_searchpath,strlen(string)+strlen(prm_searchpath)+1);
  232. else {
  233. prm_searchpath = malloc(strlen(string)+1);
  234. prm_searchpath[0] = 0;
  235. }
  236. strcat(prm_searchpath,string);
  237. }
  238. void def_setup(char select, char *string)
  239. /*
  240.  * activation for command line #defines
  241.  */
  242. {
  243. char *s = malloc(strlen(string)+1);
  244. LIST *l = malloc(sizeof(LIST));
  245. strcpy(s,string);
  246. l->link = deflist;
  247. deflist = l;
  248. l->data = s;
  249. }
  250. void setglbdefs(void)
  251. /*
  252.  * function declares any global defines from the command line and also
  253.  * declares a couple of other macros so we can tell what the compiler is
  254.  * doing
  255.  */
  256. {
  257. LIST *l = deflist;
  258. while (l) {
  259. char *s = l->data;
  260. char *n = s;
  261. while (*s && *s != '=')
  262. s++;
  263. if (*s == '=')
  264. *s++=0;
  265. glbdefine(n,s);
  266. l = l->link;
  267. }
  268. #ifdef CPLUSPLUS
  269. if (prm_cplusplus) {
  270. glbdefine("__cplusplus","");
  271. }
  272. #endif
  273. glbdefine(GLBDEFINE,"");
  274. }
  275. void InsertAnyFile(FILE *inf, FILE *outf, char *filename, char *path, int drive)
  276. /*
  277.  * Insert a file name onto the list of files to process
  278.  */
  279. {
  280.   char *newbuffer, buffer[100],*p = buffer;
  281. LIST *r = &clist;
  282. file_count++;
  283. if (drive != -1) {
  284. *p++ = (char)(drive + 'A');
  285. *p++ = ':';
  286. }
  287. if (path) {
  288. strcpy(p,path);
  289. strcat(p,"\");
  290. }
  291. else
  292. *p = 0;
  293.   /* Allocate buffer and make .C if no extension */
  294. strcat(buffer,filename);
  295.   AddExt(buffer,".C");
  296.   newbuffer = (char *) malloc(strlen(buffer) + 1);
  297.   strcpy(newbuffer,buffer);
  298.   /* Insert file */
  299. while (r->link)
  300. r = r->link;
  301. r->link = malloc(sizeof(LIST));
  302. r = r->link;
  303. r->link = 0;
  304. r->data = newbuffer;
  305. }
  306. void dumperrs(FILE *file);
  307. void setfile(char *buf,char *orgbuf,char *ext)
  308. /*
  309.  * Get rid of a file path an add an extension to the file name
  310.  */
  311. {
  312. char *p = strrchr(orgbuf,'\');
  313. if (!p) p = orgbuf;
  314. else p++;
  315. strcpy(buf,p);
  316. StripExt(buf);
  317. AddExt(buf,ext);
  318. }
  319. int parse_arbitrary(char *string)
  320. /*
  321.  * take a C string and and convert it to ARGC, ARGV format and then run
  322.  * it through the argument parser
  323.  */
  324. {
  325. char *argv[40];
  326. int rv,i;
  327. int argc = 1;
  328. if (!string || !*string)
  329. return 1;
  330. while (1) {
  331. while (*string == ' ') 
  332. string++;
  333. if (!*string)
  334. break;
  335. argv[argc++] = string;
  336. while (*string && *string != ' ') string++;
  337. if (!*string)
  338. break;
  339. *string = 0;
  340. string++;
  341. }
  342.   rv = parse_args(&argc,argv,TRUE);
  343.   for (i= 1; i < argc; i++)
  344. InsertAnyFile(0,0,argv[i],0,-1);
  345. return rv;
  346. }
  347. void parsefile(char select, char *string)
  348. /*
  349.  * parse arguments from an input file
  350.  */
  351. {
  352. FILE *temp;
  353. if (!(temp = fopen(string,"r")))
  354. fatal("Argument file not found");
  355. while (!feof(temp)) {
  356. char buf[256];
  357. buf[0] = 0;
  358. fgets(buf,256,temp);
  359. if (buf[strlen(buf)-1] == 'n')
  360. buf[strlen(buf)-1] = 0;
  361. if (!parse_arbitrary(buf))
  362. break;
  363. }
  364. fclose(temp);
  365. }
  366. void addinclude(void)
  367. /*
  368.  * Look up the INCLUDE environment variable and append it to the
  369.  * search path
  370.  */
  371. {
  372. char *string = getenv("CCINCL");
  373. if (string && string[0]) {
  374. char temp[500];
  375. strcpy(temp,string);
  376. if (prm_searchpath) {
  377. strcat(temp,";");
  378. strcat(temp,prm_searchpath);
  379. free(prm_searchpath);
  380. }
  381. prm_searchpath = malloc(strlen(temp)+1);
  382. strcpy(prm_searchpath,temp);
  383. }
  384. }
  385. int parseenv(char *name)
  386. /*
  387.  * Parse the environment argument string
  388.  */
  389. {
  390. char *string = getenv(name);
  391. return parse_arbitrary(string);
  392. }
  393. void dumperrs(FILE *file)
  394. {
  395. #ifdef DIAGNOSTICS
  396. if (diagcount)
  397. fprintf(file,"%d Diagnostics detectedn",diagcount);
  398. #endif
  399. if (total_errors)
  400. fprintf(file,"%d Total errorsn",total_errors);
  401. if (prm_diag)
  402. mem_summary();
  403. }
  404. void summary(void)
  405. {       
  406. if (prm_listfile) {
  407.     fprintf(listFile,"fn *** global scope symbol table ***nn");
  408.     list_table(&gsyms,0);
  409. if (tagtable.head) {
  410.      fprintf(listFile,"n *** structures and unions ***nn");
  411.      list_table(&tagtable,0);
  412. }
  413. dumperrs(listFile);
  414.   }
  415. }
  416. void ctrlchandler(int aa)
  417. {
  418. longjmp(ctrlcreturn,1);
  419. }
  420. int main(int argc,char *argv[])
  421. {
  422. char buffer[40];
  423. char *p;
  424.   banner("%s Version %d.%02d Copyright (c) 1994-1997, LADsoft",PROGNAME,VERSION/100,VERSION %100);
  425.   outfile[0] = 0;
  426. /* parse the environment and command line */
  427. /* inpout cfg file has already been parsed */
  428.   if (!parseenv(ENVNAME))
  429.     usage(argv[0]);
  430.   if (!parse_args(&argc, argv, TRUE) || (!file_count && argc == 1))
  431.     usage(argv[0]);
  432. /* tack the environment includes in */
  433. addinclude();
  434. /* processor-dependent initialization */
  435. confsetup();
  436.   /* Scan the command line for file names or response files */
  437. { int i;
  438. for (i=1; i <argc; i++) 
  439. InsertAnyFile(0,0,argv[i],0,-1);
  440. }
  441.   /* Set up a ctrl-C handler so we can exit the prog */
  442. signal(SIGINT,ctrlchandler);
  443. if (setjmp(ctrlcreturn))
  444. exit(1);
  445. /* loop through and compile all the files on the file list */
  446. while (clist) {
  447. inasmini();
  448. memini();
  449.   symini();
  450. stmtini();
  451. kwini();
  452. initini();
  453. preprocini();
  454. exprini();
  455. declini();
  456. funcini();
  457. peepini();
  458. outcodeini();
  459. regini();
  460. printf("file: %sn",clist->data);
  461.   strcpy(buffer,clist->data);
  462. #ifdef OBJEXT
  463. if (prm_asmfile)
  464. #endif
  465. setfile(outfile,buffer,SOURCEXT);
  466. #ifdef OBJEXT
  467. else
  468. setfile(outfile,buffer,OBJEXT);
  469. #endif
  470. setfile(cppfile,buffer,".I");
  471. setfile(listfile,buffer,".LST");
  472. setfile(errorfile,buffer,".ERR");
  473. prm_cplusplus = FALSE;
  474.   AddExt(buffer,".C");
  475. #ifdef CPLUSPLUS
  476. p = strrchr(buffer,'.');
  477. if (*(p-1) != '.') {
  478. if (p[1] == 'c' || p[1] == 'C')
  479. if (p[2] == 'p' || p[2] == 'P')
  480. if (p[3] == 'p' || p[3] == 'P')
  481. prm_cplusplus = TRUE;
  482. }
  483. #endif
  484. infile = errfile = litlate(buffer);
  485. if (prm_cppfile) {
  486. if (!(cppFile = fopen(cppfile,"w")))
  487. fatal("Can't open cpp file %s",cppfile);
  488. }
  489.    if (!(inputFile = fopen(infile,"r")))
  490.      fatal("Can't open input file %s",infile);
  491.    if (!(outputFile = fopen(outfile,"w"))) {
  492.      fclose(inputFile);
  493.      fatal("Can't open output file %s",outfile);
  494.   }
  495. if (prm_asmfile)
  496. asm_header();
  497.   if (prm_listfile)
  498.    if (!(listFile = fopen(listfile,"w"))) {
  499.      fclose(inputFile);
  500.     fclose(outputFile);
  501.      fatal("Can't open list file %s",listfile);
  502.    }
  503.   if (prm_errfile)
  504.    if (!(errFile = fopen(errorfile,"w"))) {
  505. fclose(listFile);
  506.      fclose(inputFile);
  507.     fclose(outputFile);
  508.      fatal("Can't open error file %s",errorfile);
  509.    }
  510. initerr();
  511.   initsym();
  512. setglbdefs();
  513.    getch();
  514.    getsym();
  515.   compile();
  516. summary();
  517.    release_global();
  518. dumperrs(stdout);
  519.   fclose(inputFile);
  520. if (prm_asmfile) {
  521.    fclose(outputFile);
  522. }
  523.    if (prm_listfile)
  524.      fclose(listFile);
  525.    if (prm_errfile)
  526.      fclose(errFile);
  527.    if (prm_cppfile)
  528.      fclose(cppFile);
  529. clist = clist->link;
  530. /* Remove the ASM file if there are errors */
  531. if (total_errors)
  532. remove(outfile);
  533. /* Remove the ERR file if no warnings / errors */
  534. if (!errlist && prm_errfile)
  535. remove(errorfile);
  536. /* Flag to stop if there are any errors */
  537. stoponerr |= total_errors;
  538. }
  539.   if (stoponerr)
  540.     return(1);
  541.   else
  542.     return(0);
  543. }