home *** CD-ROM | disk | FTP | other *** search
- /*
- * 68K/386 32-bit C compiler.
- *
- * copyright (c) 1996, David Lindauer
- *
- * This compiler is intended for educational use. It may not be used
- * for profit without the express written consent of the author.
- *
- * It may be freely redistributed, as long as this notice remains intact
- * and sources are distributed along with any executables derived from them.
- *
- * The author is not responsible for damages, either direct or consequential,
- * that may arise from use of this software.
- *
- * v1.5 August 1996
- * David Lindauer, gclind01@starbase.spd.louisville.edu
- *
- * Credits to Mathew Brandt for original K&R C compiler
- *
- */
- #include <stdio.h>
- #include "utype.h"
- #include "cmdline.h"
- #include "expr.h"
- #include "c.h"
- #include "gen.h"
- #include "cglbdec.h"
- #include "time.h"
-
- extern HASHREC **defhash;
- extern char *infile;
- extern int incconst;
- extern char *prm_searchpath;
- extern short *lptr;
- extern int cantnewline;
- extern char *infile;
- extern int backupchar;
- extern int floatregs,dataregs,addrregs,basefr,basedr,basear;
- extern int prm_cmangle;
-
- IFSTRUCT *ifshold[10];
- char *inclfname[10];
- FILE *inclfile[10];
- int incldepth = 0;
- int inclline[10];
- short *lptr;
-
- IFSTRUCT *ifs = 0;
- int ifskip = 0;
- int elsetaken = 0;
-
- void filemac(short *string);
- void datemac(short *string);
- void linemac(short *string);
-
- static char *unmangid; /* In this module we have to ignore leading underscores */
- /* List of standard macros */
- #define INGROWNMACROS 3
-
- struct inmac {
- char *s;
- void (*func)();
- } ingrownmacros[INGROWNMACROS] = {
- { "__FILE__",filemac }, { "__DATE__",datemac, },
- { "__LINE__",linemac } };
-
- void pushif(void);
-
- /* Moudle init */
- void preprocini(void)
- {
- floatregs = basefr;
- dataregs = basedr;
- addrregs = basear;
- incldepth = 0;
- ifs = 0;
- ifskip = elsetaken = 0;
- unmangid = lastid;
- if (prm_cmangle)
- unmangid++;
- }
- /* Preprocessor dispatch */
- int preprocess(void )
- {
- ++lptr;
- lastch = ' ';
- getsym(); /* get first word on line */
-
- if( lastst != id && lastst != kw_else && lastst!= kw_if) {
- generror(ERR_IDEXPECT,0,0);
- return incldepth == 0;
- }
- if( strcmp(unmangid,"include") == 0 )
- return doinclude();
- else if( strcmp(unmangid,"define") == 0 )
- return dodefine();
- else if (strcmp(unmangid,"endif") == 0)
- return doendif();
- else if (lastst == kw_else)
- return doelse();
- else if (strcmp(unmangid,"ifdef") == 0)
- return doifdef(TRUE);
- else if (strcmp(unmangid,"ifndef") == 0)
- return doifdef(FALSE);
- else if (lastst == kw_if)
- return doif(0);
- else if( strcmp(unmangid,"elif") == 0 )
- return doelif();
- else if (strcmp(unmangid,"undef") == 0)
- return(doundef());
- else if (strcmp(unmangid,"error") == 0)
- return(doerror());
- else if (strcmp(unmangid,"pragma") == 0)
- return(dopragma());
- else if (strcmp(unmangid,"line") == 0)
- return(incldepth == 0);
- else {
- gensymerror(ERR_PREPROCID,unmangid);
- return incldepth == 0;
- }
- }
-
- int doerror(void)
- {
- char *temp;
- int i=0;
- global_flag++;
- temp = xalloc(pstrlen(lptr)*3+2);
- pstrcpy(temp,lptr);
- while (*lptr)
- i+=installphichar(*lptr++,temp,i);
- temp[i-1] = 0;
- global_flag--;
- basicerror(ERR_ERROR,temp);
- return incldepth == 0;
- }
- int dopragma(void)
- {
- char buf[40],*p=buf;
- int val = 0;
- getsym();
- if (lastst != id)
- return incldepth == 0;
- if (!strcmp(unmangid,"startup"))
- startupseg();
- else if (!strcmp(unmangid,"rundown"))
- rundownseg();
- else if (!strncmp(unmangid,"regopt",6)) {
- short *s = lptr;
- dataregs = floatregs = addrregs = 0;
- while (*s != '\n') {
- switch (*s) {
- case 'a':
- case 'A':
- addrregs = 1;
- break;
- case 'f':
- case 'F':
- floatregs = 1;
- break;
- case 'd':
- case 'D':
- dataregs = 1;
- break;
- }
- s++;
- }
- return incldepth == 0;
- }
- else return incldepth == 0;
-
- /* Startup and rundown code */
- *p++ = '_';
- while (isalnum(*lptr))
- *p++=*lptr++;
- *p=0;
- while (*lptr == ' ' || *lptr == '\t')
- lptr++;
- while (isdigit(*lptr)) {
- val *= 10;
- val += (*lptr++)-'0';
- }
- gensrref(buf,val);
- return incldepth == 0;
- }
- int doinclude(void)
- /*
- * HAndle include files
- */
- { int rv;
- FILE *oldfile = inputFile;
- incconst = TRUE;
- getsym(); /* get file to include */
- incconst = FALSE;
- if (ifskip)
- return incldepth == 0;
- if( lastst != sconst ) {
- gensymerror(ERR_INCLFILE,"include");
- return incldepth == 0;
- }
- if (incldepth > 9) {
- generror(ERR_PREPROCID, 0,0);
- return incldepth == 0;
- }
- inputFile = SearchPath(laststr,prm_searchpath,"r");
- if( inputFile == 0 ) {
- gensymerror(ERR_CANTOPEN,laststr);
- inputFile = oldfile;
- rv = incldepth == 0;
- }
- else {
- pushif();
- ifshold[incldepth] = ifs;
- elsetaken = 0;
- ifskip = 0;
- ifs = 0;
- inclline[incldepth] = lineno;
- inclfile[incldepth] = oldfile; /* push current input file */
- inclfname[incldepth++] = infile;
- global_flag++;
- infile = litlate(laststr);
- global_flag--;
- rv = incldepth == 1;
- lineno = 0;
- }
- return rv;
- }
-
- short *plitlate(short *string)
- {
- short *temp = xalloc(pstrlen(string)*sizeof(short)+sizeof(short));
- pstrcpy(temp,string);
- return temp;
- }
- void glbdefine(char *string)
- {
- { SYM *sp;
- DEFSTRUCT *def;
- if (( sp = search(string,&defsyms) )!= 0)
- return;
- ++global_flag; /* always do #define as globals */
- sp = xalloc(sizeof(SYM));
- sp->name = litlate(string);
- def = xalloc(sizeof(DEFSTRUCT));
- def->args = 0;
- def->argcount = 0;
- def->string = xalloc(1);
- *(def->string) = 0;
- sp->value.s = (char *) def;
- insert(sp,&defsyms);
- --global_flag;
- return;
- }
- }
- /* Handle #defines
- * Doesn't check for redefine with different value
- * Does handle ANSI macros
- */
- int dodefine(void)
- { SYM *sp;
- DEFSTRUCT *def;
- short *args[40],count=0;
- short *olptr;
- int p;
- getsym(); /* get past #define */
- if (ifskip)
- return incldepth == 0;
- olptr = lptr;
- if( lastst != id ) {
- generror(ERR_IDEXPECT,0,0);
- return incldepth == 0;
- }
- if (( sp = search(unmangid,&defsyms) )!= 0)
- undef2();
- ++global_flag; /* always do #define as globals */
- sp = xalloc(sizeof(SYM));
- sp->name = litlate(unmangid);
- def = xalloc(sizeof(DEFSTRUCT));
- def->args = 0;
- def->argcount = 0;
- if (lastch == '(') {
- getdefsym();
- getdefsym();
- while (lastst == id) {
- args[count++] = plitlate(unmangid);
- getdefsym();
- if (lastst != comma)
- break;
- getdefsym();
- }
- if (lastst != closepa)
- generror(ERR_PUNCT,closepa,0);
- olptr = lptr;
- def->args = xalloc(count*sizeof(short *));
- memcpy(def->args,args,count*sizeof(short *));
- def->argcount = count;
- }
- p = pstrlen(olptr);
- if (olptr[p-1] == 0x0a)
- olptr[p-1] = 0;
- def->string = plitlate(olptr);
- sp->value.s = (char *) def;
- insert(sp,&defsyms);
- --global_flag;
- return incldepth == 0;
- }
- /*
- * Undefine
- */
- int doundef(void)
- {
- getsym();
- if (!ifskip)
- undef2();
- return(incldepth == 0);
- }
- int undef2(void)
- {
- if (lastst != id)
- generror(ERR_IDEXPECT,0,0);
- else {
- SYM **p = (SYM **)LookupHash(unmangid,defhash,HASHTABLESIZE);
- if (p) {
- *p = (*p)->next;
- }
- }
- }
- void getdefsym(void)
- {
- if (backupchar != -1) {
- lastst = backupchar;
- backupchar = -1;
- return;
- }
- restart: /* we come back here after comments */
- while(iswhitespacechar(lastch))
- getch();
- if( lastch == -1)
- lastst = eof;
- else if(isdigit(lastch))
- getnum();
- else if(isstartchar(lastch)) {
- lptr--;
- defid(unmangid,&lptr,0);
- lastch = *lptr++;
- lastst = id;
- }
- else if (getsym2())
- goto restart;
- }
- int defid(short *name, short **p, char *q)
- /*
- * Get an identifier during macro replacement
- */
- {
- int count = 0,i=0;
- while (issymchar(**p)) {
- if (count < 19) {
- name[count++] = *(*p);
- if (q)
- i+=installphichar(*(*p),q,i);
- }
- (*p)++;
- }
- if ((q[i-1] & 0xf0) == 0x90)
- q[i-1] = 0x90;
- q[i] = '\0';
- name[count] = 0;
- return(count);
- }
- /*
- * Insert a replacement string
- */
- int definsert(short *end, short *begin, short * text, int len, int replen)
- {
- short *q;
- int i,p, r;
- int val;
- if (*(begin-1) == '#') {
- if (*(begin-2) != '#') {
- begin--;
- replen++;
- r = pstrlen(text);
-
- text[r++] = '\"';
- text[r] = 0;
- for (i=r; i > 0; i--)
- text[i+1] = text[i];
- *text = '\"';
- }
- }
- p = pstrlen(text);
- val = p - replen;
- r = pstrlen(begin);
- if (val + strlen(begin) >= len-1) {
- generror(ERR_MACROSUBS,0,0);
- return(-8000);
- }
- if (val > 0)
- for (q = begin + r+1; q >= end; q--)
- *(q+val) = *q;
- else
- if (val < 0) {
- r = pstrlen(end)+1;
- for (q = end; q < end+r; q++ )
- *(q+val) = *q;
- }
- for (i=0; i < p; i++)
- begin[i] = text[i];
- return(val);
- }
- /* replace macro args */
- int defreplace(short *macro, int count, short **oldargs, short **newargs)
- {
- int i,rv;
- int narg[1024];
- int name[20];
- short *p=macro,*q;
- while (*p) {
- if (isstartchar(*p)) {
- q = p;
- defid(name,&p,0);
- for (i=0; i < count; i++)
- if (!pstrcmp(name,oldargs[i])) {
- pstrcpy(narg,newargs[i]);
- if ((rv = definsert(p,q,narg,1024-(q-macro),p-q)) == -8000)
- return(FALSE);
- else {
- p += rv;
- break;
- }
- }
- }
- p++;
- }
- return(TRUE);
- }
- /* Handlers for default macros */
- void cnvt(short *out,char *in)
- {
- while (*in)
- *out++=*in++;
- *out = 0;
- }
- void filemac(short *string)
- {
- char str1[40];
- sprintf(str1,"\"%s\"",infile);
- cnvt(string,str1);
- }
- void datemac(short *string)
- {
- char str1[40];
- struct tm *t1;
- time_t t2;
- time(&t2);
- t1 = localtime(&t2);
- str1[0] = '"';
- strcpy(&str1[1],asctime(t1));
- str1[25] = '"';
- str1[26] = 0;
- cnvt(string,str1);
- }
- void linemac(short *string)
- {
- char str1[40];
- sprintf(str1,"%d",lineno);
- cnvt(string,str1);
- }
- /* Scan for default macros and replace them */
- void defmacroreplace(short *macro, short *name)
- {
- int i;
- macro[0] = 0;
- for (i=0; i < INGROWNMACROS; i++)
- if (!strcmp(name,ingrownmacros[i].s)) {
- (ingrownmacros[i].func)(macro);
- break;
- }
- }
- /* Scan line for macros and do replacements */
- void defcheck(short *line)
- {
- short macro[1024];
- short name[20];
- short *args[40];
- char ascii[60];
- int count=0,tryagain = TRUE, changed = FALSE, waiting = FALSE,rv;
- short *p = line,*q;
- SYM *sp;
- while (tryagain) {
- p = line;
- tryagain = FALSE;
- while(*p) {
- q = p;
- if (*p == '"' || *p == '\'') {
- waiting = !waiting;
- p++;
- }
- else if (waiting)
- p++;
- else if (isstartchar(*p)) {
- defid(name,&p,ascii);
- if ((sp = search(ascii,&defsyms)) != 0) {
- DEFSTRUCT *def = sp->value.s;
- pstrcpy(macro,def->string);
- if (def->argcount) {
- if (*p++ != '(') {
- generror(ERR_MACROSUBS,0,0);
- return;
- }
- do {
- short *nm = name;
- while (*p != ',' && *p != ')' && *p != '\n')
- *nm++ = *p++;
- *nm = 0;
- args[count++] = plitlate(name);
- } while (*p++ == ',');
- if (*(p-1) != ')' || count != def->argcount) {
- generror(ERR_MACROSUBS,0,0);
- return;
- }
- if (!defreplace(macro,count,def->args,args))
- return;
- }
- if ((rv=definsert(p,q,macro,4096-(q-line),p-q))==-8000)
- return;
- p+=rv;
- changed = tryagain = TRUE;
- }
- else {
- defmacroreplace(macro,ascii);
- if (macro[0]) {
- if ((rv=definsert(p,q,macro,4096-(q-line),p-q))==-8000)
- return;
- p += rv;
- changed = TRUE;
- }
- }
- }
- else p++;
- }
- }
- if (changed) {
- p = q = line;
- while (*p) {
- if (*p == '#' && *(p+1) == '#')
- p+=2;
- else
- *q++ = *p++;
- }
- }
-
- }
- void pushif(void)
- /* Push an if context */
- {
- IFSTRUCT *p;
- global_flag++;
- p = xalloc(sizeof(IFSTRUCT));
- global_flag--;
- p->link = ifs;
- p->iflevel = ifskip;
- p->elsetaken = elsetaken;
- elsetaken = FALSE;
- ifs = p;
- }
- void popif(void)
- /* Pop an if context */
- {
- if (ifs) {
- ifskip = ifs->iflevel;
- elsetaken = ifs->elsetaken;
- ifs = ifs->link;
- }
- else {
- ifskip = 0;
- elsetaken = 0;
- }
- }
- int doifdef (int flag)
- /* Handle IFDEF */
- {
- SYM *sp;
- getch();
- while(isspace(lastch))
- getch();
- if (!isstartchar(lastch)) {
- generror(ERR_IDEXPECT,0,0);
- return incldepth == 0;
- }
- else
- getid();
- sp = search(unmangid,&defsyms);
- pushif();
- if (sp && !flag || !sp && flag)
- ifskip = TRUE;
- return(incldepth == 0);
- }
- int doif(int flag)
- /* Handle #if */
- {
- getsym();
- pushif();
- cantnewline = TRUE;
- if (!intexpr(0))
- ifskip = TRUE;
- cantnewline = FALSE;
- return(incldepth == 0);
- }
- int doelif(void)
- /* Handle #elif */
- {
- int is;
- getsym();
- cantnewline = TRUE;
- is = !intexpr(0);
- cantnewline = FALSE;
- if (ifs) {
- if (!ifs->iflevel)
- ifskip = !ifskip || is || elsetaken;
- if (!ifskip)
- elsetaken = TRUE;
- }
- else
- generror(ERR_PREPROCMATCH,0,0);
- return(incldepth == 0);
- }
- /* handle else */
- int doelse(void)
- {
- if (ifs) {
- if (!ifs->iflevel)
- ifskip = !ifskip || elsetaken;
- }
- else
- generror(ERR_PREPROCMATCH,0,0);
- return(incldepth == 0);
- }
- /* HAndle endif */
- int doendif(void)
- {
- if (!ifs)
- generror(ERR_PREPROCMATCH,0,0);
- popif();
- return(incldepth == 0);
- }