home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 332 / hcc / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-27  |  8.7 KB  |  534 lines

  1. /* Copyright (c) 1988,1989 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    main.c
  12.  *
  13.  *    Main routine, error handling, keyword lookup.
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include "param.h"
  18. #include "nodes.h"
  19. #include "tok.h"
  20.  
  21. int lineno;
  22. int nmerrors;
  23. int oflags[26];
  24. int xflags[26];
  25. int pflag = 0;            /* enable profiling */
  26. static int anydebug;
  27. #define debug oflags['z'-'a']
  28.  
  29. FILE *input;
  30. FILE *output;
  31. #if CC68
  32. FILE *fopenb();
  33. #define fopen fopenb
  34. #endif
  35. char *inname;
  36.  
  37. #if NEEDBUF
  38. char my_ibuf[BUFSIZ];
  39. #endif
  40.  
  41. #ifdef MINIX
  42. #define strchr    index
  43. #endif
  44.  
  45. NODEP cur;
  46.  
  47. #define MAXPREDEF    20
  48.  
  49. struct def {
  50.     char *dname, *dval;
  51. } defines[MAXPREDEF] = {
  52.     {"MC68000"},
  53.     {"mc68000"},
  54.     {"SOZOBON"},
  55. #ifdef FOR_AMIGA
  56.     {"AMIGA"},
  57.     {"AMIGADOS"},
  58. #else
  59.     {"ATARI_ST"},
  60. #ifdef MINIX
  61.     {"MINIX"},
  62. #else
  63.     {"TOS"},
  64. #endif
  65. #endif
  66. };
  67. static int npred = 4;
  68.  
  69. #ifdef MINIX
  70. char    tmpdir[128] = ".";        /* where the output goes */
  71. #endif
  72.  
  73. main(argc, argv)
  74. char **argv;
  75. {
  76.     char    *p, *getenv();
  77.     int shownames;
  78.     int i;
  79.  
  80.     if (sizeof(NODE) & 3) {
  81.         printf("sizeof NODE not mult of 4\n");
  82.         exit(1);
  83.     }
  84.  
  85.     /*
  86.      * Parse the INCLUDE environment variable, if present.
  87.      */
  88.     if ((p = getenv("INCLUDE")) != NULL)
  89.         doincl(p);
  90.  
  91.     shownames = 0;
  92. #ifndef FOR_AMIGA
  93.     if (isatty(0)) {
  94. #ifndef MINIX
  95.         write(1, "\33v", 2);
  96. #endif
  97.         setbuf(stdout, NULL);
  98.     }
  99. #endif
  100. /* put author here */
  101.     while (argc-- > 1) {
  102.         argv++;
  103.         if (argv[0][0] == '-')
  104.             doopt(&argv[0][1]);
  105. #if CC68
  106.         else if (argv[0][0] == '+') {
  107.             upstr(&argv[0][1]);
  108.             doopt(&argv[0][1]);
  109.         }
  110. #endif
  111.         else {
  112.             if (argc > 1 || shownames) {
  113.                 shownames++;
  114.                 printf("%s:\n", argv[0]);
  115.             }
  116.             if (input != NULL)
  117.                 fclose(input);
  118.             input = fopen(argv[0], ROPEN);
  119.             if (input == NULL) {
  120.                 printf("Cant open %s\n", argv[0]);
  121.                 exit(1);
  122.             }
  123. #if NEEDBUF
  124.             setbuf(input, my_ibuf);
  125. #endif
  126.             inname = argv[0];
  127.             dofile();
  128.         }
  129.     }
  130.     if (input == NULL) {
  131.         input = stdin;
  132.         output = stdout;
  133.         inname = "<STDIN>";
  134.         dofile();
  135.     }
  136.     exit(0);
  137. }
  138.  
  139. adddef(s)
  140. char *s;
  141. {
  142.     char *as, *strchr();
  143.  
  144.     if (npred >= MAXPREDEF) {
  145.         warn("too many -D 's");
  146.         return;
  147.     }
  148.     if ((as = strchr(s,'=')) != NULL)
  149.         *as++ = 0;
  150.     else
  151.         as = NULL;
  152.     defines[npred].dname = s;
  153.     defines[npred].dval = as;
  154.     npred++;
  155. }
  156.  
  157. subdef(s)
  158. char *s;
  159. {
  160.     int i;
  161.  
  162.     for (i=0; i<npred; i++)
  163.         if (strcmp(s, defines[i].dname) == 0)
  164.             goto found;
  165.     return;
  166. found:
  167.     while (i < npred) {
  168.         defines[i] = defines[i+1];
  169.         i++;
  170.     }
  171.     npred--;
  172. }
  173.  
  174. dodefs()
  175. {
  176.     int i;
  177.     struct def *p;
  178.  
  179.     /*
  180.      * Define the "built-in" macros
  181.      */
  182.     p = defines;
  183.     for (i=0; i < npred; i++,p++)
  184.         optdef(p->dname, p->dval ? p->dval : "1");
  185. }
  186.  
  187. doincl(s)
  188. char    *s;
  189. {
  190.     char    *malloc(), *strcpy();
  191.     char    buf[256];
  192.     char    dir[128];
  193.     register char    *p;
  194.     char c;
  195.  
  196.     strcpy(buf, s);
  197.  
  198.     /*
  199.      * Convert ',' and ';' to nulls
  200.      */
  201.     for (p=buf; *p != '\0' ;p++)
  202.         if (*p == ',' || *p == ';')
  203.             *p = '\0';
  204.     p[1] = '\0';            /* double null terminated */
  205.  
  206.     /*
  207.      * Grab each directory, make sure it ends with a slash
  208.      * and add it to the directory list.
  209.      */
  210.     for (p=buf; *p != '\0' ;p++) {
  211.         strcpy(dir, p);
  212.         c = dir[strlen(dir)-1];
  213. #ifndef FOR_AMIGA
  214. #ifdef MINIX
  215.         if (c != '/')
  216.             strcat(dir, "/");
  217. #else
  218.         if (c != '\\')
  219.             strcat(dir, "\\");
  220. #endif
  221. #else
  222.         if (c != '/' && c != ':')
  223.             strcat(dir, "/");
  224. #endif
  225.  
  226.         optincl( strcpy(malloc((unsigned) (strlen(dir) + 1)), dir) );
  227.  
  228.         while (*p != '\0')
  229.             p++;
  230.     }
  231. }
  232.  
  233. dofile()
  234. {
  235.     extern int nodesmade, nodesavail;
  236.     char *scopy();
  237.     extern NODEP deflist[], symtab[], tagtab;
  238.     extern NODEP strsave;
  239.     extern int level;
  240.     int i;
  241.  
  242.     out_start(inname);
  243.     inname = scopy(inname);
  244.     lineno = 1;
  245.     nmerrors = 0;
  246.     dodefs();
  247.     advnode();
  248.  
  249.     level = 0;
  250.     program();
  251.     dumpstrs(strsave);
  252. #ifdef OUT_AZ
  253.     xrefs();
  254. #endif
  255.  
  256.     out_end();
  257.     if (cur && cur->e_token == EOFTOK)
  258.         freenode(cur);
  259.     sfree(inname);
  260.     for (i=0; i<NHASH; i++) {
  261.         if (debug>1 && deflist[i]) {
  262.             printf("defines[%d]", i);
  263.             printlist(deflist[i]);
  264.         }
  265.         freenode(deflist[i]);
  266.         deflist[i] = NULL;
  267.         if (debug && symtab[i]) {
  268.             printf("gsyms[%d]", i);
  269.             printlist(symtab[i]);
  270.         }
  271.         freenode(symtab[i]);
  272.         symtab[i] = NULL;
  273.     }
  274.     if (debug) {
  275.         printf("structs");
  276.         printlist(tagtab);
  277.     }
  278.     freenode(tagtab);
  279.     tagtab = NULL;
  280.     freenode(strsave);
  281.     strsave = NULL;
  282.     if (nmerrors) {
  283.         printf("%d errors\n", nmerrors);
  284.         exit(1);
  285.     }
  286.     if (nodesmade != nodesavail) {
  287.         printf("lost %d nodes!!!\n", nodesmade-nodesavail);
  288.         exit(1);
  289.     }
  290. /*
  291.     printf("Space = %ldK\n", ((long)nodesavail*sizeof(NODE))/1024);
  292. */
  293. }
  294.  
  295. static    char    Version[] =
  296. "hcc: version 1.20  Copyright (c) 1988,1989 by Sozobon, Limited.";
  297.  
  298. doopt(s)
  299. char *s;
  300. {
  301.     register char c;
  302.  
  303.     while ((c = *s++)) {
  304. #ifdef    DEBUG
  305.         if (c >= 'a' && c <='z') {
  306.             oflags[c-'a']++;
  307.             anydebug++;
  308.         } else
  309. #endif
  310.         if (c >= 'A' && c <= 'Z') {
  311.             switch (c) {
  312.             case 'D':
  313.                 adddef(s);
  314.                 return;
  315.             case 'U':
  316.                 subdef(s);
  317.                 return;
  318.             case 'I':
  319.                 doincl(s);
  320.                 return;
  321.             case 'P':
  322.                 pflag = 1;
  323.                 continue;
  324.             case 'V':
  325.                 printf("%s\n", Version);
  326.                 continue;
  327. #ifdef MINIX
  328.             case 'T':
  329.                 strcpy(tmpdir, s);
  330.                 if (tmpdir[strlen(tmpdir)-1] == '/')
  331.                     tmpdir[strlen(tmpdir)-1] = '\0';
  332.                 return;
  333. #endif
  334.             }
  335. #ifdef    DEBUG
  336.             xflags[c-'A']++;
  337.             anydebug++;
  338. #endif
  339.         }
  340.     }
  341. }
  342.  
  343. errors(s,t)
  344. char *s, *t;
  345. {
  346.     optnl();
  347.     printf("error in %s on line %d: %s %s\n", inname, lineno, s,t);
  348.     nmerrors++;
  349. }
  350.  
  351. errorn(s,np)
  352. char *s;
  353. NODE *np;
  354. {
  355.     optnl();
  356.     printf("error in %s on line %d: %s ", inname, lineno, s);
  357.     put_nnm(np);
  358.     putchar('\n');
  359.     nmerrors++;
  360. }
  361.  
  362. error(s)
  363. char *s;
  364. {
  365.     optnl();
  366.     printf("error in %s on line %d: %s\n", inname, lineno, s);
  367.     nmerrors++;
  368. }
  369.  
  370. warns(s,t)
  371. char *s, *t;
  372. {
  373.     optnl();
  374.     printf("warning in %s on line %d: %s %s\n", inname, lineno, s,t);
  375. }
  376.  
  377. warnn(s,np)
  378. char *s;
  379. NODE *np;
  380. {
  381.     optnl();
  382.     printf("warning in %s on line %d: %s ", inname, lineno, s);
  383.     put_nnm(np);
  384.     putchar('\n');
  385. }
  386.  
  387. warn(s)
  388. char *s;
  389. {
  390.     optnl();
  391.     printf("warning in %s on line %d: %s\n", inname, lineno, s);
  392. }
  393.  
  394. fatals(s,t)
  395. char *s, *t;
  396. {
  397.     optnl();
  398.     printf("fatal error in %s on line %d: %s %s\n", inname, lineno, s,t);
  399.     exit(1);
  400. }
  401.  
  402. fataln(s,np)
  403. char *s;
  404. NODE *np;
  405. {
  406.     optnl();
  407.     printf("fatal error in %s on line %d: %s ", inname, lineno, s);
  408.     put_nnm(np);
  409.     putchar('\n');
  410.     exit(1);
  411. }
  412.  
  413. fatal(s)
  414. char *s;
  415. {
  416.     optnl();
  417.     printf("fatal error in %s on line %d: %s\n", inname, lineno, s);
  418.     exit(1);
  419. }
  420.  
  421. static
  422. optnl()
  423. {
  424.     if (anydebug)
  425.         putchar('\n');
  426. }
  427.  
  428. struct kwtbl {
  429.     char *name;
  430.     int    kwval;
  431.     int    kflags;
  432. } kwtab[] = {
  433.     /* must be sorted */
  434.     {"asm", K_ASM},
  435.     {"auto", K_AUTO},
  436.     {"break", K_BREAK},
  437.     {"case", K_CASE},
  438.     {"char", K_CHAR},
  439.     {"continue", K_CONTINUE},
  440.     {"default", K_DEFAULT},
  441.     {"do", K_DO},
  442.     {"double", K_DOUBLE},
  443.     {"else", K_ELSE},
  444.     {"enum", K_ENUM},
  445.     {"extern", K_EXTERN},
  446.     {"float", K_FLOAT},
  447.     {"for", K_FOR},
  448.     {"goto", K_GOTO},
  449.     {"if", K_IF},
  450.     {"int", K_INT},
  451.     {"long", K_LONG},
  452.     {"register", K_REGISTER},
  453.     {"return", K_RETURN},
  454.     {"short", K_SHORT},
  455.     {"sizeof", K_SIZEOF},
  456.     {"static", K_STATIC},
  457.     {"struct", K_STRUCT},
  458.     {"switch", K_SWITCH},
  459.     {"typedef", K_TYPEDEF},
  460.     {"union", K_UNION},
  461.     {"unsigned", K_UNSIGNED},
  462.     {"void", K_VOID},
  463.     {"while", K_WHILE},
  464.  
  465.     {0,0}
  466. };
  467.  
  468. #define FIRST_C    'a'
  469. #define LAST_C    'z'
  470. struct kwtbl *kwstart[LAST_C-FIRST_C+1];
  471.  
  472. kw_init()
  473. {
  474.     register struct kwtbl *p;
  475.     register c;
  476.  
  477.     for (p=kwtab; p->name; p++) {
  478.         c = p->name[0];
  479.         if (kwstart[c-FIRST_C] == 0)
  480.             kwstart[c-FIRST_C] = p;
  481.     }
  482. }
  483.  
  484. kw_tok(tp)
  485. NODE *tp;
  486. {
  487.     register struct kwtbl *kp;
  488.     register char *nm;
  489.     register i;
  490.     static first = 0;
  491.  
  492.     nm = tp->n_name;
  493.     if (first == 0) {
  494.         kw_init();
  495.         first = 1;
  496.     }
  497.     i = nm[0];
  498.     if (i < FIRST_C || i > LAST_C)
  499.         return;
  500.     kp = kwstart[i-FIRST_C];
  501.     if (kp)
  502.     for (; kp->name; kp++) {
  503.         i = strcmp(nm, kp->name);
  504.         if (i == 0) {
  505.             tp->e_token = kp->kwval;
  506.             tp->e_flags = kp->kflags;
  507.             return;
  508.         } else if (i < 0)
  509.             return;
  510.     }
  511. }
  512.  
  513. #if CC68
  514. /* fix args since stupid lib makes all lower case */
  515. upstr(s)
  516. char *s;
  517. {
  518.     while (*s) {
  519.         if (*s >= 'a' && *s <= 'z')
  520.             *s += 'A'-'a';
  521.         s++;
  522.     }
  523. }
  524. downstr(s)
  525. char *s;
  526. {
  527.     while (*s) {
  528.         if (*s >= 'A' && *s <= 'Z')
  529.             *s -= 'A'-'a';
  530.         s++;
  531.     }
  532. }
  533. #endif
  534.