home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1996 December / CD_shareware_12-96.iso / DOS / Programa / CCDL122.ZIP / SOURCE / PREPROC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-08  |  14.2 KB  |  647 lines

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1996, 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 sources are distributed along with any executables derived from them.
  11.  *
  12.  * The author is not responsible for damages, either direct or consequential,
  13.  * that may arise from use of this software.
  14.  *
  15.  * v1.5 August 1996
  16.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  17.  *
  18.  * Credits to Mathew Brandt for original K&R C compiler
  19.  *
  20.  */
  21. #include        <stdio.h>
  22. #include                "utype.h"
  23. #include                "cmdline.h"
  24. #include        "expr.h"
  25. #include        "c.h"
  26. #include        "gen.h"
  27. #include        "cglbdec.h"
  28. #include                "time.h"
  29.  
  30. extern HASHREC **defhash;
  31. extern char *infile;
  32. extern int incconst;
  33. extern char *prm_searchpath;
  34. extern short *lptr;
  35. extern int cantnewline;
  36. extern char *infile;
  37. extern int backupchar;
  38. extern int floatregs,dataregs,addrregs,basefr,basedr,basear;
  39. extern int prm_cmangle;
  40.  
  41. IFSTRUCT              *ifshold[10];
  42. char                         *inclfname[10];
  43. FILE            *inclfile[10];
  44. int             incldepth = 0;
  45. int             inclline[10];
  46. short            *lptr;
  47.  
  48. IFSTRUCT *ifs = 0;
  49. int ifskip = 0;
  50. int elsetaken = 0;
  51.  
  52. void filemac(short *string);
  53. void datemac(short *string);
  54. void linemac(short *string);
  55.  
  56. static char *unmangid;        /* In this module we have to ignore leading underscores */
  57. /* List of standard macros */
  58. #define INGROWNMACROS 3
  59.  
  60. struct inmac {
  61.         char *s;
  62.         void (*func)();
  63. } ingrownmacros[INGROWNMACROS] = { 
  64.             { "__FILE__",filemac }, { "__DATE__",datemac, },
  65.             { "__LINE__",linemac } };
  66.  
  67. void pushif(void);
  68.  
  69. /* Moudle init */
  70. void preprocini(void)
  71. {
  72.     floatregs = basefr;
  73.     dataregs = basedr;
  74.     addrregs = basear;
  75.     incldepth = 0;
  76.     ifs = 0;
  77.     ifskip = elsetaken = 0;
  78.     unmangid = lastid;
  79.     if (prm_cmangle)
  80.         unmangid++;
  81. }
  82. /* Preprocessor dispatch */
  83. int preprocess(void )
  84. {
  85.         ++lptr;
  86.         lastch = ' ';
  87.         getsym();               /* get first word on line */
  88.  
  89.         if( lastst != id  && lastst != kw_else && lastst!= kw_if) {
  90.                 generror(ERR_IDEXPECT,0,0);
  91.                 return incldepth == 0;
  92.                 }
  93.         if( strcmp(unmangid,"include") == 0 )
  94.                 return doinclude();
  95.         else if( strcmp(unmangid,"define") == 0 )
  96.                 return dodefine();
  97.                 else if (strcmp(unmangid,"endif") == 0)
  98.                                 return doendif();
  99.                 else if (lastst == kw_else)
  100.                                 return doelse();
  101.                 else if (strcmp(unmangid,"ifdef") == 0)
  102.                                 return doifdef(TRUE);
  103.                 else if (strcmp(unmangid,"ifndef") == 0)
  104.                                 return doifdef(FALSE);
  105.                 else if (lastst == kw_if)
  106.                                 return doif(0);
  107.         else if( strcmp(unmangid,"elif") == 0 )
  108.                 return doelif();
  109.                 else if (strcmp(unmangid,"undef") == 0)
  110.                                 return(doundef());
  111.                 else if (strcmp(unmangid,"error") == 0)
  112.                                 return(doerror());
  113.                 else if (strcmp(unmangid,"pragma") == 0)
  114.                                 return(dopragma());
  115.                 else if (strcmp(unmangid,"line") == 0)
  116.                                 return(incldepth == 0);
  117.         else    {
  118.                 gensymerror(ERR_PREPROCID,unmangid);
  119.                 return incldepth == 0;
  120.                 }
  121. }
  122.  
  123. int doerror(void)
  124. {
  125.     char *temp;
  126.     int i=0;
  127.     global_flag++;
  128.     temp = xalloc(pstrlen(lptr)*3+2);
  129.     pstrcpy(temp,lptr);
  130.     while (*lptr)
  131.         i+=installphichar(*lptr++,temp,i);
  132.     temp[i-1] = 0;
  133.     global_flag--;
  134.     basicerror(ERR_ERROR,temp);
  135.     return incldepth == 0;
  136. }
  137. int dopragma(void)
  138. {
  139.     char buf[40],*p=buf;
  140.     int val = 0;
  141.     getsym();
  142.     if (lastst != id)
  143.         return incldepth == 0;
  144.     if (!strcmp(unmangid,"startup"))
  145.         startupseg();
  146.     else if (!strcmp(unmangid,"rundown"))
  147.         rundownseg();
  148.     else if (!strncmp(unmangid,"regopt",6)) {
  149.         short *s = lptr;
  150.         dataregs = floatregs = addrregs = 0;
  151.         while (*s != '\n') {
  152.             switch (*s) {
  153.                 case 'a':
  154.                 case 'A':
  155.                     addrregs = 1;
  156.                     break;
  157.                 case 'f':
  158.                 case 'F':
  159.                     floatregs = 1;
  160.                     break;
  161.                 case 'd':
  162.                 case 'D':
  163.                     dataregs = 1;
  164.                     break;
  165.             }
  166.             s++;
  167.         }
  168.         return incldepth == 0;
  169.     }
  170.     else return incldepth == 0;
  171.     
  172.     /* Startup and rundown code */
  173.     *p++ = '_';
  174.     while (isalnum(*lptr))
  175.         *p++=*lptr++;
  176.     *p=0;
  177.     while (*lptr == ' ' || *lptr == '\t')
  178.         lptr++;
  179.     while (isdigit(*lptr)) {
  180.         val *= 10;
  181.         val += (*lptr++)-'0';
  182.     }
  183.     gensrref(buf,val);
  184.     return incldepth == 0;
  185. }
  186. int doinclude(void)
  187. /*
  188.  * HAndle include files
  189.  */
  190. {       int     rv;
  191.                 FILE *oldfile = inputFile;
  192.                 incconst = TRUE;
  193.         getsym();               /* get file to include */
  194.                 incconst = FALSE;
  195.                 if (ifskip)
  196.                     return incldepth == 0;
  197.         if( lastst != sconst ) {
  198.                 gensymerror(ERR_INCLFILE,"include");
  199.                 return incldepth == 0;
  200.                 }
  201.                 if (incldepth > 9) {
  202.                     generror(ERR_PREPROCID, 0,0);
  203.                     return incldepth == 0;
  204.                 }
  205.         inputFile = SearchPath(laststr,prm_searchpath,"r");
  206.         if( inputFile == 0 ) {
  207.                 gensymerror(ERR_CANTOPEN,laststr);
  208.                 inputFile = oldfile;
  209.                 rv = incldepth == 0;
  210.                 }
  211.         else    {
  212.                                 pushif();
  213.                                 ifshold[incldepth] = ifs;
  214.                                 elsetaken = 0;
  215.                                 ifskip = 0;
  216.                                 ifs = 0;
  217.                         inclline[incldepth] = lineno;
  218.                         inclfile[incldepth] = oldfile;  /* push current input file */
  219.                                 inclfname[incldepth++] = infile;
  220.                                 global_flag++;
  221.                                 infile = litlate(laststr);
  222.                                 global_flag--;
  223.                 rv = incldepth == 1;
  224.                 lineno = 0;
  225.                 }
  226.         return rv;
  227. }
  228.  
  229. short *plitlate(short *string)
  230. {
  231.     short *temp = xalloc(pstrlen(string)*sizeof(short)+sizeof(short));
  232.     pstrcpy(temp,string);
  233.     return temp;
  234. }
  235. void glbdefine(char *string)
  236. {
  237. {       SYM     *sp;
  238.                 DEFSTRUCT *def;
  239.                 if (( sp = search(string,&defsyms) )!= 0)
  240.                     return;
  241.         ++global_flag;          /* always do #define as globals */
  242.         sp = xalloc(sizeof(SYM));
  243.         sp->name = litlate(string);
  244.                 def = xalloc(sizeof(DEFSTRUCT));
  245.                 def->args = 0;
  246.                 def->argcount = 0;
  247.                 def->string = xalloc(1);
  248.                 *(def->string) = 0;
  249.         sp->value.s = (char *) def;
  250.         insert(sp,&defsyms);
  251.         --global_flag;
  252.         return;
  253. }
  254. }
  255. /* Handle #defines
  256.  * Doesn't check for redefine with different value
  257.  * Does handle ANSI macros
  258.  */
  259. int dodefine(void)
  260. {       SYM     *sp;
  261.                 DEFSTRUCT *def;
  262.                 short *args[40],count=0;
  263.                 short *olptr;
  264.                 int p;
  265.         getsym();               /* get past #define */
  266.                 if (ifskip)
  267.                     return incldepth == 0;
  268.                 olptr = lptr;
  269.         if( lastst != id ) {
  270.                 generror(ERR_IDEXPECT,0,0);
  271.                 return incldepth == 0;
  272.                 }
  273.                 if (( sp = search(unmangid,&defsyms) )!= 0)
  274.                     undef2();
  275.         ++global_flag;          /* always do #define as globals */
  276.         sp = xalloc(sizeof(SYM));
  277.         sp->name = litlate(unmangid);
  278.                 def = xalloc(sizeof(DEFSTRUCT));
  279.                 def->args = 0;
  280.                 def->argcount = 0;
  281.                 if (lastch == '(') {
  282.                     getdefsym();
  283.                     getdefsym();
  284.                     while (lastst == id) {
  285.                         args[count++] = plitlate(unmangid);
  286.                         getdefsym();
  287.                         if (lastst != comma)
  288.                             break;
  289.                         getdefsym();
  290.                     }
  291.                     if (lastst != closepa)
  292.                       generror(ERR_PUNCT,closepa,0);
  293.                     olptr = lptr;
  294.                     def->args = xalloc(count*sizeof(short *));
  295.                     memcpy(def->args,args,count*sizeof(short *));
  296.                     def->argcount = count;
  297.                 }
  298.                 p = pstrlen(olptr);
  299.                 if (olptr[p-1] == 0x0a)
  300.                     olptr[p-1] = 0;
  301.                 def->string = plitlate(olptr);
  302.         sp->value.s = (char *) def;
  303.         insert(sp,&defsyms);
  304.         --global_flag;
  305.         return incldepth == 0;
  306. }
  307. /*
  308.  * Undefine
  309.  */
  310. int doundef(void)
  311. {
  312.     getsym();
  313.     if (!ifskip)
  314.         undef2();
  315.     return(incldepth == 0);
  316. }
  317. int undef2(void)
  318. {
  319.     if (lastst != id) 
  320.     generror(ERR_IDEXPECT,0,0);
  321.     else {
  322.         SYM **p = (SYM **)LookupHash(unmangid,defhash,HASHTABLESIZE);
  323.         if (p) {
  324.             *p = (*p)->next;
  325.         }
  326.     }
  327. }
  328. void getdefsym(void)
  329. {
  330.                 if (backupchar != -1) {
  331.                     lastst = backupchar;
  332.                     backupchar = -1;
  333.                     return;
  334.                 }
  335. restart:        /* we come back here after comments */
  336.         while(iswhitespacechar(lastch))
  337.                 getch();
  338.         if( lastch == -1)
  339.                 lastst = eof;
  340.         else if(isdigit(lastch))
  341.                 getnum();
  342.         else if(isstartchar(lastch)) {
  343.                                 lptr--;
  344.                 defid(unmangid,&lptr,0);    
  345.                                 lastch = *lptr++;
  346.                                 lastst = id;
  347.                 }
  348.         else if (getsym2())
  349.                     goto restart;
  350. }
  351. int defid(short *name, short **p, char *q)
  352. /*
  353.  * Get an identifier during macro replacement
  354.  */
  355. {
  356.     int count = 0,i=0;
  357.             while (issymchar(**p)) {
  358.                 if (count < 19) {
  359.                     name[count++] = *(*p);
  360.                     if (q)
  361.                         i+=installphichar(*(*p),q,i);
  362.                 }
  363.                 (*p)++;
  364.             }
  365.             if ((q[i-1] & 0xf0) == 0x90)
  366.                 q[i-1] = 0x90;
  367.       q[i] = '\0';
  368.     name[count] = 0;
  369.     return(count);
  370. }
  371. /* 
  372.  * Insert a replacement string
  373.  */
  374. int definsert(short *end, short *begin, short * text, int len, int replen)
  375. {
  376.     short *q;
  377.     int i,p, r;
  378.     int val;
  379.     if (*(begin-1) == '#') {
  380.         if (*(begin-2) != '#') {
  381.             begin--;
  382.             replen++;
  383.             r = pstrlen(text);
  384.             
  385.             text[r++] = '\"';
  386.             text[r] = 0;
  387.             for (i=r; i > 0; i--)
  388.                 text[i+1] = text[i];
  389.             *text = '\"';
  390.         }
  391.     }
  392.     p = pstrlen(text);
  393.     val = p - replen;
  394.     r = pstrlen(begin);
  395.     if (val + strlen(begin) >= len-1) {
  396.         generror(ERR_MACROSUBS,0,0);
  397.         return(-8000);
  398.     }
  399.     if (val > 0)
  400.         for (q = begin + r+1; q >= end; q--)
  401.             *(q+val) = *q;
  402.     else
  403.         if (val < 0) {
  404.             r = pstrlen(end)+1;
  405.             for (q = end; q < end+r; q++ )
  406.                 *(q+val) = *q;
  407.         }
  408.     for (i=0; i < p; i++)
  409.         begin[i] = text[i]; 
  410.     return(val);
  411. }
  412. /* replace macro args */    
  413. int defreplace(short *macro, int count, short **oldargs, short **newargs)
  414. {
  415.     int i,rv;
  416.     int narg[1024];
  417.     int name[20];
  418.     short *p=macro,*q;
  419.     while (*p) {
  420.         if (isstartchar(*p)) {
  421.             q = p;
  422.             defid(name,&p,0);
  423.             for (i=0; i < count; i++)
  424.                 if (!pstrcmp(name,oldargs[i])) {
  425.                     pstrcpy(narg,newargs[i]);
  426.                     if ((rv = definsert(p,q,narg,1024-(q-macro),p-q)) == -8000)
  427.                         return(FALSE);
  428.                     else {
  429.                         p += rv;
  430.                         break;
  431.                     }
  432.                 }
  433.         }
  434.         p++;
  435.     }
  436.     return(TRUE);
  437. }
  438. /* Handlers for default macros */
  439. void cnvt(short *out,char *in)
  440. {
  441.     while (*in) 
  442.         *out++=*in++;
  443.     *out = 0;
  444. }
  445. void filemac(short *string)
  446. {
  447.     char str1[40];
  448.     sprintf(str1,"\"%s\"",infile);
  449.     cnvt(string,str1);
  450. }
  451. void datemac(short *string)
  452. {
  453.     char str1[40];
  454.     struct tm *t1;
  455.     time_t t2;
  456.     time(&t2);
  457.     t1 = localtime(&t2);
  458.     str1[0] = '"';
  459.   strcpy(&str1[1],asctime(t1));
  460.     str1[25] = '"';
  461.     str1[26] = 0;
  462.     cnvt(string,str1);
  463. }
  464. void linemac(short *string)
  465. {
  466.     char str1[40];
  467.     sprintf(str1,"%d",lineno);
  468.     cnvt(string,str1);
  469. }
  470. /* Scan for default macros and replace them */
  471. void defmacroreplace(short *macro, short *name)
  472. {
  473.     int i;
  474.     macro[0] = 0;
  475.     for (i=0; i < INGROWNMACROS; i++)
  476.         if (!strcmp(name,ingrownmacros[i].s)) {
  477.             (ingrownmacros[i].func)(macro);
  478.             break;
  479.         }
  480. }
  481. /* Scan line for macros and do replacements */
  482. void defcheck(short *line)
  483. {
  484.     short macro[1024];
  485.     short name[20];
  486.     short *args[40];
  487.     char ascii[60];
  488.     int count=0,tryagain = TRUE, changed = FALSE, waiting = FALSE,rv;
  489.     short *p = line,*q;
  490.     SYM *sp;
  491.     while (tryagain) {
  492.         p = line;
  493.         tryagain = FALSE;
  494.         while(*p) {
  495.             q = p;
  496.             if (*p == '"' || *p == '\'') {
  497.                 waiting = !waiting;
  498.                 p++;
  499.             }
  500.             else if (waiting)
  501.                 p++;
  502.             else if (isstartchar(*p)) {
  503.                 defid(name,&p,ascii);
  504.                 if ((sp = search(ascii,&defsyms)) != 0) {
  505.                     DEFSTRUCT *def = sp->value.s;
  506.                     pstrcpy(macro,def->string);
  507.                     if (def->argcount) {
  508.                         if (*p++ != '(') {
  509.                             generror(ERR_MACROSUBS,0,0);
  510.                             return;
  511.                         }
  512.                         do {
  513.                             short *nm = name;
  514.                             while (*p != ',' && *p != ')' && *p != '\n')
  515.                                     *nm++ = *p++;
  516.                             *nm = 0;
  517.                             args[count++] = plitlate(name);
  518.                         } while (*p++ == ',');
  519.                         if (*(p-1) != ')' || count != def->argcount) {
  520.                             generror(ERR_MACROSUBS,0,0);
  521.                             return;
  522.                         }
  523.                         if (!defreplace(macro,count,def->args,args))
  524.                             return;
  525.                     }
  526.                     if ((rv=definsert(p,q,macro,4096-(q-line),p-q))==-8000)
  527.                         return;
  528.                     p+=rv;
  529.                     changed = tryagain = TRUE;
  530.                 }
  531.                 else {
  532.                     defmacroreplace(macro,ascii);
  533.                     if (macro[0]) {
  534.                         if ((rv=definsert(p,q,macro,4096-(q-line),p-q))==-8000)
  535.                             return;
  536.                         p += rv;
  537.                         changed = TRUE;
  538.                     }
  539.                 }
  540.             }
  541.             else p++;
  542.         }
  543.     }
  544.     if (changed) {
  545.         p = q = line;
  546.         while (*p) {
  547.             if (*p == '#' && *(p+1) == '#')
  548.                 p+=2;
  549.             else
  550.                 *q++ = *p++;
  551.         }
  552.     }
  553.             
  554. }
  555. void pushif(void)
  556. /* Push an if context */
  557. {
  558.     IFSTRUCT *p;
  559.     global_flag++;
  560.     p = xalloc(sizeof(IFSTRUCT));
  561.     global_flag--;
  562.     p->link = ifs;
  563.     p->iflevel = ifskip;
  564.     p->elsetaken = elsetaken;
  565.     elsetaken = FALSE;
  566.     ifs = p;
  567. }
  568. void popif(void)
  569. /* Pop an if context */
  570. {
  571.     if (ifs) {
  572.         ifskip = ifs->iflevel;
  573.         elsetaken = ifs->elsetaken;
  574.         ifs = ifs->link;
  575.     }
  576.     else {
  577.         ifskip = 0;
  578.         elsetaken = 0;
  579.     }
  580. }    
  581. int doifdef (int flag)
  582. /* Handle IFDEF */
  583. {
  584.     SYM *sp;
  585.     getch();
  586.     while(isspace(lastch))
  587.         getch();
  588.     if (!isstartchar(lastch)) {
  589.     generror(ERR_IDEXPECT,0,0);
  590.     return incldepth == 0;
  591.     }
  592.     else
  593.         getid();
  594.      sp = search(unmangid,&defsyms);
  595.   pushif();
  596.     if (sp && !flag || !sp && flag)
  597.         ifskip = TRUE;
  598.     return(incldepth == 0);
  599. }
  600. int doif(int flag)
  601. /* Handle #if */
  602. {
  603.     getsym();
  604.   pushif();
  605.     cantnewline = TRUE;
  606.     if (!intexpr(0))
  607.         ifskip = TRUE;
  608.     cantnewline = FALSE;
  609.     return(incldepth == 0);
  610. }
  611. int doelif(void)
  612. /* Handle #elif */
  613. {
  614.     int is;
  615.     getsym();
  616.     cantnewline = TRUE;
  617.     is = !intexpr(0);
  618.     cantnewline = FALSE;
  619.     if (ifs) {
  620.         if (!ifs->iflevel)
  621.             ifskip = !ifskip || is || elsetaken;
  622.             if (!ifskip)
  623.                 elsetaken = TRUE;
  624.     }
  625.     else
  626.         generror(ERR_PREPROCMATCH,0,0);
  627.     return(incldepth == 0);
  628. }
  629. /* handle else */
  630. int doelse(void)
  631. {
  632.     if (ifs) {
  633.         if (!ifs->iflevel)
  634.             ifskip = !ifskip || elsetaken;
  635.     }
  636.     else
  637.         generror(ERR_PREPROCMATCH,0,0);
  638.     return(incldepth == 0);
  639. }
  640. /* HAndle endif */
  641. int doendif(void)
  642. {
  643.     if (!ifs)
  644.         generror(ERR_PREPROCMATCH,0,0);
  645.     popif();
  646.     return(incldepth == 0);
  647. }