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
- *
- */
- /* Trigraphs implemented, won't work for token pasting though */
- #include <stdio.h>
- #include "expr.h"
- #include "c.h"
- #include "gen.h"
- #include "cglbdec.h"
- #include "utype.h"
- #include "interp.h"
-
- extern int prm_cplusplus,prm_cmangle;
- extern int ifskip,elsetaken;
- extern IFSTRUCT *ifs;
- extern int phiused;
-
- int inline[4096];
- extern char *infile;
- extern short *lptr; /* shared with preproc */
- extern FILE *inclfile[10]; /* shared with preproc */
- extern char *inclfname[10]; /* shared with preproc */
- extern IFSTRUCT *ifshold[10];
- extern int inclline[10]; /* shared with preproc */
- extern int incldepth; /* shared with preproc */
- extern int prm_listfile;
- char *linstack[20]; /* stack for substitutions */
- char chstack[20]; /* place to save lastch */
- int lstackptr = 0; /* substitution stack pointer */
- int cantnewline = FALSE;
- int incconst = FALSE;
-
- int backupchar = -1;
-
- static int phiputcpp,phiputlist;
- int isalnum(char c)
- { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9');
- }
-
- int isdigit(char c)
- { return (c >= '0' && c <= '9');
- }
- int isxdigit(char c)
- { return(isdigit(c) || (c >='A' && c <='Z') || (c >='a' && c <= 'z'));
- }
- void initsym(void)
- { lptr = inline;
- inline[0] = 0;
- lineno = 0;
- cantnewline=FALSE;
- incconst = FALSE;
- backupchar = -1;
- phiputcpp=phiputlist = FALSE;
- }
-
- int getline(int listflag)
- { int rv,rvc,i,prepping,temp;
-
- char ibuf[4096];
- int *ptr = ibuf;
- if (cantnewline) {
- lptr = inline+1;
- return(0);
- }
- do {
- rv = FALSE;
- prepping = FALSE;
- rvc = 0;
- if( lineno > 0 && listflag && prm_listfile) {
- if (phiused && !phiputlist) {
- phiputlist = TRUE;
- fputc('\x1f',listFile);
- }
- lferror();
- }
- while(rvc +131 < 4096 && !rv) {
- ++lineno;
- rv = (philine(ibuf+rvc,200,inputFile) == NULL);
- if (rv)
- break;
- rvc = strlen(ibuf);
- if (ibuf[rvc-1] != '\n') {
- ibuf[rvc++] = '\n';
- ibuf[rvc] = 0;
- }
- rvc-=2;
- while (ibuf[rvc]==' ')
- rvc--;
- if (ibuf[rvc] != '\\')
- break;
- }
- if (rvc)
- rv = FALSE;
- if (prm_listfile) {
- if (phiused && !phiputlist) {
- phiputlist = TRUE;
- fputc('\x1f',listFile);
- }
- fprintf(listFile,"%3d: %s",lineno, ibuf);
- }
- if( rv && incldepth > 0 ) {
- fclose(inputFile);
- inputFile = inclfile[--incldepth];
- lineno = inclline[incldepth];
- infile = inclfname[incldepth];
- if (ifs)
- generror(ERR_PREPROCMATCH,0,0);
- ifs = ifshold[incldepth];
- popif();
- return getline(0);
- }
- if( rv )
- return 1;
- lptr = inline;
- ptr = ibuf;
- while((temp = parsechar(&ptr)) != 0)
- *lptr++ = temp;
- *lptr = 0;
- lptr = inline;
- if(inline[0] == '#' || (inline[0] == '?' && inline[1] == '?' && inline[2] == '=')) {
- rv = pstrlen(inline);
- for (i=0; i < rv; i++)
- if (inline[i] == '/' && inline[i+1] == '/') {
- inline[i] = '\n';
- inline[i+1] = 0;
- break;
- }
- listflag = preprocess();
- prepping = TRUE;
- }
- } while (ifskip || prepping);
- defcheck(inline);
- rv = pstrlen(inline);
- for (i=0; i < rv; i++)
- if (inline[i] == '/' && inline[i+1] == '/') {
- inline[i] = '\n';
- inline[i+1] = 0;
- break;
- }
- if (cppFile) {
- char buf[20],*q=buf;
- short *p = inline;
- *q = 0;
- if (phiused && !phiputcpp) {
- phiputcpp = TRUE;
- fputc('\x1f',cppFile);
- }
- while (*p) {
- if (*q) {
- buf[0] = *q;
- i = 1;
- }
- else
- i = 0;
- i+=installphichar(*p++,buf,i);
- buf[i] = 0;
- q = buf;
- while (*q && (*(q+1) || ((*q &0xf0) != 0x90)))
- fputc(*q++,cppFile);
- }
- }
- return 0;
- }
-
- /*
- * getch - basic get character routine.
- */
- int getch(void)
- { while( (lastch = *lptr++) == '\0') {
- if( lstackptr > 0 ) {
- lptr = linstack[--lstackptr];
- lastch = chstack[lstackptr];
- return lastch;
- }
- if(getline(incldepth == 0))
- return lastch = -1;
- }
- return lastch;
- }
-
- /*
-
- /*
- * getid - get an identifier.
- *
- * identifiers are any isidch conglomerate
- * that doesn't start with a numeric character.
- * this set INCLUDES keywords.
- */
- void getid()
- { register int i;
- i = 0;
- if (prm_cmangle)
- lastid[i++] = '_'; /* Mangling */
- while(issymchar(lastch)) {
- if (i < 19)
- i+=installphichar(lastch,lastid,i);
- getch();
- }
- if ((lastid[i-1] & 0xf0) == 0x90)
- lastid[i-1] = 0x90;
- lastid[i] = '\0';
- lastst = id;
- }
-
- /*
- * getsch - get a character in a quoted string.
- *
- * this routine handles all of the escape mechanisms
- * for characters in strings and character constants.
- */
- int getsch(void) /* return an in-quote character */
- { register int i, j;
- if(lastch == '\n')
- return -1;
- if(lastch != '\\') {
- i = lastch;
- getch();
- return i;
- }
- getch(); /* get an escaped character */
- if(isdigit(lastch)) {
- for(i = 0,j=0;j < 3;++j) {
- if(lastch <= '7' && lastch >= '0')
- i = (i << 3) + lastch - '0';
- else
- break;
- getch();
- }
- return i;
- }
- i = lastch;
- getch();
- switch(i) {
- case '\n':
- getch();
- return getsch();
- case 'b':
- return '\b';
- case 'f':
- return '\f';
- case 'n':
- return '\n';
- case 'r':
- return '\r';
- case 't':
- return '\t';
- default:
- return i;
- }
- }
-
- int radix36(char c)
- { if(isdigit(c))
- return c - '0';
- if(c >= 'a' && c <= 'z')
- return c - 'a' + 10;
- if(c >= 'A' && c <= 'Z')
- return c - 'A' + 10;
- return -1;
- }
-
- /*
- * getbase - get an integer in any base.
- */
- void getbase(int b,char **ptr)
- { register long i, j;
- i = 0;
- while(isalnum(**ptr)) {
- if((j = radix36(*(*ptr)++)) < b) {
- i = i * b + j;
- }
- else break;
- }
- ival = i;
- lastst = iconst;
- }
-
- /*
- * getfrac - get fraction part of a floating number.
- */
- void getfrac(char **ptr)
- { double frmul;
- frmul = 0.1;
- while(isdigit(**ptr)) {
- rval += frmul * (*(*ptr)++ - '0');
- frmul *= 0.1;
- }
- }
-
- /*
- * getexp - get exponent part of floating number.
- *
- * this algorithm is primative but usefull. Floating
- * exponents are limited to +/-255 but most hardware
- * won't support more anyway.
- */
- void getexp(char **ptr)
- { double expo, exmul;
- expo = 1.0;
- if(lastst != rconst)
- rval = ival;
- if(**ptr = '-') {
- exmul = 0.1;
- (*ptr)++;
- }
- else {
- exmul = 10.0;
- if (**ptr == '+')
- (*ptr)++;
- }
- getbase(10,ptr);
- if(ival > 255)
- generror(ERR_FPCON,0,0);
- else
- while(ival--)
- expo *= exmul;
- rval *= expo;
- lastst = rconst;
- }
-
- /*
- * getnum - get a number from input.
- *
- * getnum handles all of the numeric input. it accepts
- * decimal, octal, hexidecimal, and floating point numbers.
- */
- void getnum(void)
- {
- int isfloat=FALSE;
- char buf[50],*ptr = buf;
- while (isxdigit(lastch) || lastch == 'x' || lastch == 'X') {
- *ptr++ = lastch;
- getch();
- }
- if (lastch == '.') {
- isfloat = TRUE;
- *ptr++=lastch;
- getch();
- while (isdigit(lastch)) {
- *ptr++ = lastch;
- getch();
- }
- }
- if (lastch == 'e' || lastch == 'E') {
- isfloat = TRUE;
- *ptr++ = lastch;
- getch();
- if (lastch == '+' || lastch == '-') {
- *ptr++=lastch;
- getch();
- }
- while (isdigit(lastch)) {
- *ptr++ = lastch;
- getch();
- }
- }
- if (lastch == 'F') {
- *ptr++ = 'F';
- getch();
- isfloat = TRUE;
- }
- *ptr = 0;
- ptr = buf;
- if (!isfloat) {
- if (*ptr == '0') {
- ptr++;
- if(*ptr == 'x' || *ptr == 'X') {
- ptr++;
- getbase(16,&ptr);
- }
- else getbase(8,&ptr);
- }
- else
- getbase(10,&ptr);
- if (lastch == 'L')
- getch();
- }
- else {
- getbase(10,&ptr);
- if(*ptr == '.') {
- ptr++;
- rval = ival; /* float the integer part */
- getfrac(&ptr); /* add the fractional part */
- lastst = rconst;
- }
- if(*ptr == 'e' || *ptr == 'E') {
- ptr++;
- getexp(&ptr); /* get the exponent */
- }
- if (*ptr == 'F') {
- ptr++;
- if (lastst != rconst) {
- rval = ival;
- lastst = rconst;
- }
- }
- }
- }
-
- int getsym2(void)
- { register int i, j;
- int size;
- swlp:
- switch(lastch) {
- case '+':
- getch();
- if(lastch == '+') {
- getch();
- lastst = autoinc;
- }
- else if(lastch == '=') {
- getch();
- lastst = asplus;
- }
- else lastst = plus;
- break;
- case '-':
- getch();
- if(lastch == '-') {
- getch();
- lastst = autodec;
- }
- else if(lastch == '=') {
- getch();
- lastst = asminus;
- }
- else if(lastch == '>') {
- getch();
- if (prm_cplusplus && lastch == '*') {
- getch();
- lastst = pointstar;
- }
- else
- lastst = pointsto;
- }
- else lastst = minus;
- break;
- case '*':
- getch();
- if(lastch == '=') {
- getch();
- lastst = astimes;
- }
- else lastst = star;
- break;
- case '/':
- getch();
- if(lastch == '=') {
- getch();
- lastst = asdivide;
- }
- else if(lastch == '*') {
- getch();
- for(;;) {
- if(lastch == '*') {
- getch();
- if(lastch == '/') {
- getch();
- return 1;
- }
- }
- else
- getch();
- }
- }
- else lastst = divide;
- break;
- case '^':
- getch();
- lastst = uparrow;
- break;
- case ';':
- getch();
- lastst = semicolon;
- break;
- case ':':
- getch();
- if (prm_cplusplus && lastch == ':') {
- lastst = classsel;
- getch();
- }
- else
- lastst = colon;
- break;
- case '=':
- getch();
- if(lastch == '=') {
- getch();
- lastst = eq;
- }
- else lastst = assign;
- break;
- case '>':
- getch();
- if(lastch == '=') {
- getch();
- lastst = geq;
- }
- else if(lastch == '>') {
- getch();
- if(lastch == '=') {
- getch();
- lastst = asrshift;
- }
- else lastst = rshift;
- }
- else lastst = gt;
- break;
- case '<':
- getch();
- if (incconst) {
- for(i = 0;i < MAX_STRLEN;++i) {
- if(lastch == '>')
- break;
- if((j = getsch()) == -1)
- break;
- else
- laststr[i] = j;
- }
- laststr[i] = 0;
- lastst = sconst;
- if(lastch != '>')
- generror(ERR_NEEDCHAR,'>',0);
- else
- getch();
- } else
- if(lastch == '=') {
- getch();
- lastst = leq;
- }
- else if(lastch == '<') {
- getch();
- if(lastch == '=') {
- getch();
- lastst = aslshift;
- }
- else lastst = lshift;
- }
- else lastst = lt;
- break;
- case '\'':
- getch();
- ival = getsch(); /* get a string char */
- if(lastch != '\'')
- generror(ERR_NEEDCHAR,'\'',0);
- else
- getch();
- lastst = iconst;
- break;
- case 0x2d4:
- getch();
- i=0;
- while (lastch != '\"' && lastch)
- i=installphichar(lastch,laststr,i);
- if ((lastch & 0x7f) != '\"')
- generror(ERR_NEEDCHAR,'\"',0);
- else
- getch();
- size = strlen(laststr);
- lastst = sconst;
- break;
- case '\"':
- size = 0;
- while (lastch == '\"') {
- getch();
- for(i = size;i < MAX_STRLEN;++i) {
- if(lastch == '\"')
- break;
- if((j = getsch()) == -1)
- break;
- else
- laststr[i] = j;
- }
- laststr[i] = 0;
- size = i;
- lastst = sconst;
- if(lastch != '\"')
- generror(ERR_NEEDCHAR,'\"',0);
- else
- getch();
- }
- break;
- case '!':
- getch();
- if(lastch == '=') {
- getch();
- lastst = neq;
- }
- else lastst = not;
- break;
- case '%':
- getch();
- if(lastch == '=') {
- getch();
- lastst = asmodop;
- }
- else lastst = modop;
- break;
- case '~':
- getch();
- lastst = compl;
- break;
- case '.':
- if (isdigit(*lptr))
- getnum();
- else {
- getch();
- if (prm_cplusplus && lastch == '*') {
- getch();
- lastst = dotstar;
- }
- else if (lastch == '.') {
- getch();
- if (lastch == '.') {
- getch();
- lastst = ellipse;
- break;
- }
- else {
- generror(ERR_ILLCHAR,lastch,0);
- }
- }
- lastst = dot;
- }
- break;
- case ',':
- getch();
- lastst = comma;
- break;
- case '&':
- getch();
- if( lastch == '&') {
- lastst = land;
- getch();
- }
- else if( lastch == '=') {
- lastst = asand;
- getch();
- }
- else
- lastst = and;
- break;
- case '|':
- getch();
- if(lastch == '|') {
- lastst = lor;
- getch();
- }
- else if( lastch == '=') {
- lastst = asor;
- getch();
- }
- else
- lastst = or;
- break;
- case '(':
- getch();
- lastst = openpa;
- break;
- case ')':
- getch();
- lastst = closepa;
- break;
- case '[':
- getch();
- lastst = openbr;
- break;
- case ']':
- getch();
- lastst = closebr;
- break;
- case '{':
- getch();
- lastst = begin;
- break;
- case '}':
- getch();
- lastst = end;
- break;
- case '?':
- getch();
- if (lastch != '?')
- lastst = hook;
- else {
- getch();
- switch(lastch) {
- case '(': lastch = '['; break;
- case '/': lastch = '\\'; break;
- case ')': lastch = ']'; break;
- case '\'': lastch = '^'; break;
- case '<': lastch = '{'; break;
- case '!': lastch = '|'; break;
- case '>': lastch = '}'; break;
- case '-': lastch = '~'; break;
- }
- goto swlp;
- }
- break;
- default:
- if (iscommentchar(lastch)) {
- do {
- getch();
- } while (!iscommentchar(lastch) && lastch != '\n');
- }
- else
- generror(ERR_ILLCHAR,lastch,0);
- getch();
- return 1;
- }
- return 0;
- }
- /*
- * getsym - get next symbol from input stream.
- *
- * getsym is the basic lexical analyzer. It builds
- * basic tokens out of the characters on the input
- * stream and sets the following global variables:
- *
- * lastch: A look behind buffer.
- * lastst: type of last symbol read.
- * laststr: last string constant read.
- * lastid: last identifier read.
- * ival: last integer constant read.
- * rval: last real constant read.
- *
- * getsym should be called for all your input needs...
- */
- void getsym(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)) {
- getid();
- searchkw();
- }
- else if (getsym2())
- goto restart;
- }
-
- int needpunc(enum e_sym p, int *skimlist)
- { if( lastst == p) {
- getsym();
- return(TRUE);
- }
- else
- expecttoken(p,skimlist);
- return(FALSE);
- }
- int needpuncexp(enum e_sym p, int *skimlist)
- { if( lastst == p) {
- getsym();
- return(TRUE);
- }
- else
- expecttokenexp(p,skimlist);
- return(FALSE);
- }
- void backup(int st)
- {
- backupchar = lastst;
- lastst = st;
- }