home *** CD-ROM | disk | FTP | other *** search
- #
- /* C compiler
- *
- *
- *
- * Called from cc:
- * c0 source temp1 temp2 [ profileflag ]
- * temp1 contains some ascii text and the binary expression
- * trees. Each tree is introduced by the # character.
- * Strings are put on temp2, which cc tacks onto
- * temp1 for assembly.
- */
-
- #include "c0h.c"
-
- int isn 1;
- int stflg 1;
- int peeksym -1;
- int line 1;
- int debug 0;
- int dimp 0;
- struct tname funcblk { NAME, 0, 0, REG, 0, 0 };
- int *treespace { osspace };
-
- struct kwtab {
- char *kwname;
- int kwval;
- } kwtab[]
- {
- "int", INT,
- "char", CHAR,
- "float", FLOAT,
- "double", DOUBLE,
- "struct", STRUCT,
- "long", LONG,
- "auto", AUTO,
- "extern", EXTERN,
- "static", STATIC,
- "register", REG,
- "goto", GOTO,
- "return", RETURN,
- "if", IF,
- "while", WHILE,
- "else", ELSE,
- "switch", SWITCH,
- "case", CASE,
- "break", BREAK,
- "continue", CONTIN,
- "do", DO,
- "default", DEFAULT,
- "for", FOR,
- "sizeof", SIZEOF,
- 0, 0,
- };
-
- main(argc, argv)
- char *argv[];
- {
- extern fin;
- register char *sp;
- register i;
- register struct kwtab *ip;
-
- if(argc<3) {
- error("Arg count");
- exit(1);
- }
- if((fin=open(argv[1],0))<0) {
- error("Can't find %s", argv[1]);
- exit(1);
- }
- if (fcreat(argv[2], obuf)<0 || fcreat(argv[3], sbuf)<0) {
- error("Can't create temp");
- exit(1);
- }
- if (argc>4)
- proflg++;
- /*
- * The hash table locations of the keywords
- * are marked; if an identifier hashes to one of
- * these locations, it is looked up in in the keyword
- * table first.
- */
- for (ip=kwtab; (sp = ip->kwname); ip++) {
- i = 0;
- while (*sp)
- i =+ *sp++;
- hshtab[i%hshsiz].hflag = FKEYW;
- }
- while(!eof) {
- extdef();
- blkend();
- }
- outcode("B", EOF);
- strflg++;
- outcode("B", EOF);
- fflush(obuf);
- fflush(sbuf);
- exit(nerror!=0);
- }
-
- /*
- * Look up the identifier in symbuf in the symbol table.
- * If it hashes to the same spot as a keyword, try the keyword table
- * first. An initial "." is ignored in the hash.
- * Return is a ptr to the symbol table entry.
- */
- lookup()
- {
- int ihash;
- register struct hshtab *rp;
- register char *sp, *np;
-
- ihash = 0;
- sp = symbuf;
- if (*sp=='.')
- sp++;
- while (sp<symbuf+ncps)
- ihash =+ *sp++;
- rp = &hshtab[ihash%hshsiz];
- if (rp->hflag&FKEYW)
- if (findkw())
- return(KEYW);
- while (*(np = rp->name)) {
- for (sp=symbuf; sp<symbuf+ncps;)
- if (*np++ != *sp++)
- goto no;
- csym = rp;
- return(NAME);
- no:
- if (++rp >= &hshtab[hshsiz])
- rp = hshtab;
- }
- if(++hshused >= hshsiz) {
- error("Symbol table overflow");
- exit(1);
- }
- rp->hclass = 0;
- rp->htype = 0;
- rp->hoffset = 0;
- rp->dimp = 0;
- rp->hflag =| xdflg;
- sp = symbuf;
- for (np=rp->name; sp<symbuf+ncps;)
- *np++ = *sp++;
- csym = rp;
- return(NAME);
- }
-
- /*
- * Search the keyword table.
- * Ignore initial "." to avoid member-of-structure
- * problems.
- */
- findkw()
- {
- register struct kwtab *kp;
- register char *p1, *p2;
- char *wp;
-
- wp = symbuf;
- if (*wp=='.')
- wp++;
- for (kp=kwtab; (p2 = kp->kwname); kp++) {
- p1 = wp;
- while (*p1 == *p2++)
- if (*p1++ == '\0') {
- cval = kp->kwval;
- return(1);
- }
- }
- return(0);
- }
-
-
- /*
- * Return the next symbol from the input.
- * peeksym is a pushed-back symbol, peekc is a pushed-back
- * character (after peeksym).
- * mosflg means that the next symbol, if an identifier,
- * is a member of structure or a structure tag, and it
- * gets a "." prepended to it to distinguish
- * it from other identifiers.
- */
- symbol() {
- register c;
- register char *sp;
-
- if (peeksym>=0) {
- c = peeksym;
- peeksym = -1;
- if (c==NAME)
- mosflg = 0;
- return(c);
- }
- if (peekc) {
- c = peekc;
- peekc = 0;
- } else
- if (eof)
- return(EOF);
- else
- c = getchar();
- loop:
- switch(ctab[c]) {
-
- case INSERT: /* ignore newlines */
- inhdr = 1;
- c = getchar();
- goto loop;
-
- case NEWLN:
- if (!inhdr)
- line++;
- inhdr = 0;
-
- case SPACE:
- c = getchar();
- goto loop;
-
- case EOF:
- eof++;
- return(0);
-
- case PLUS:
- return(subseq(c,PLUS,INCBEF));
-
- case MINUS:
- return(subseq(c,subseq('>',MINUS,ARROW),DECBEF));
-
- case ASSIGN:
- if (subseq(' ',0,1)) return(ASSIGN);
- c = symbol();
- if (c>=PLUS && c<=EXOR) {
- if (spnextchar() != ' '
- && (c==MINUS || c==AND || c==TIMES)) {
- error("Warning: assignment operator assumed");
- nerror--;
- }
- return(c+ASPLUS-PLUS);
- }
- if (c==ASSIGN)
- return(EQUAL);
- peeksym = c;
- return(ASSIGN);
-
- case LESS:
- if (subseq(c,0,1)) return(LSHIFT);
- return(subseq('=',LESS,LESSEQ));
-
- case GREAT:
- if (subseq(c,0,1)) return(RSHIFT);
- return(subseq('=',GREAT,GREATEQ));
-
- case EXCLA:
- return(subseq('=',EXCLA,NEQUAL));
-
- case DIVIDE:
- if (subseq('*',1,0))
- return(DIVIDE);
- while ((c = spnextchar()) != EOF) {
- peekc = 0;
- if (c=='*') {
- if (spnextchar() == '/') {
- peekc = 0;
- c = getchar();
- goto loop;
- }
- }
- }
- eof++;
- error("Nonterminated comment");
- return(0);
-
- case PERIOD:
- case DIGIT:
- peekc = c;
- if ((c=getnum(c=='0'?8:10)) == FCON)
- cval = isn++;
- return(c);
-
- case DQUOTE:
- return(getstr());
-
- case SQUOTE:
- return(getcc());
-
- case LETTER:
- sp = symbuf;
- if (mosflg) {
- *sp++ = '.';
- mosflg = 0;
- }
- while(ctab[c]==LETTER || ctab[c]==DIGIT) {
- if (sp<symbuf+ncps) *sp++ = c;
- c = getchar();
- }
- while(sp<symbuf+ncps)
- *sp++ = '\0';
- peekc = c;
- if ((c=lookup())==KEYW && cval==SIZEOF)
- c = SIZEOF;
- return(c);
-
- case AND:
- return(subseq('&', AND, LOGAND));
-
- case OR:
- return(subseq('|', OR, LOGOR));
-
- case UNKN:
- error("Unknown character");
- c = getchar();
- goto loop;
-
- }
- return(ctab[c]);
- }
-
- /*
- * If the next input character is c, return a and advance.
- * Otherwise push back the character and return a.
- */
- subseq(c,a,b)
- {
- if (spnextchar() != c)
- return(a);
- peekc = 0;
- return(b);
- }
-
- /*
- * Read a double-quoted string, placing it on the
- * string buffer.
- */
- getstr()
- {
- register int c;
- register char *sp;
-
- nchstr = 1;
- sp = savstr;
- while((c=mapch('"')) >= 0) {
- nchstr++;
- if (sp >= &savstr[STRSIZ]) {
- sp = savstr;
- error("String too long");
- }
- *sp++ = c;
- }
- strptr = sp;
- cval = isn++;
- return(STRING);
- }
-
- /*
- * Write out a string, either in-line
- * or in the string temp file labelled by
- * lab.
- */
- putstr(lab)
- {
- register char *sp;
-
- if (lab) {
- strflg++;
- outcode("BNB", LABEL, lab, BDATA);
- } else
- outcode("B", BDATA);
- for (sp = savstr; sp<strptr; )
- outcode("1N", *sp++ & 0377);
- outcode("100");
- strflg = 0;
- }
-
- /*
- * read a single-quoted character constant.
- * The routine is sensitive to the layout of
- * characters in a word.
- */
- getcc()
- {
- register int c, cc;
- register char *ccp;
-
- cval = 0;
- ccp = &cval;
- cc = 0;
- while((c=mapch('\'')) >= 0)
- if(cc++ < NCPW)
- *ccp++ = c;
- if(cc>NCPW)
- error("Long character constant");
- return(CON);
- }
-
- /*
- * Read a character in a string or character constant,
- * detecting the end of the string.
- * It implements the escape sequences.
- */
- mapch(ac)
- {
- register int a, c, n;
- static mpeek;
-
- c = ac;
- if (a = mpeek)
- mpeek = 0;
- else
- a = getchar();
- loop:
- if (a==c)
- return(-1);
- switch(a) {
-
- case '\n':
- case '\0':
- error("Nonterminated string");
- peekc = a;
- return(-1);
-
- case '\\':
- switch (a=getchar()) {
-
- case 't':
- return('\t');
-
- case 'n':
- return('\n');
-
- case 'b':
- return('\b');
-
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- n = 0;
- c = 0;
- while (++c<=3 && '0'<=a && a<='7') {
- n =<< 3;
- n =+ a-'0';
- a = getchar();
- }
- mpeek = a;
- return(n);
-
- case 'r':
- return('\r');
-
- case '\n':
- if (!inhdr)
- line++;
- inhdr = 0;
- a = getchar();
- goto loop;
- }
- }
- return(a);
- }
-
- /*
- * Read an expression and return a pointer to its tree.
- * It's the classical bottom-up, priority-driven scheme.
- * The initflg prevents the parse from going past
- * "," or ":" because those delimitesrs are special
- * in initializer (and some other) expressions.
- */
- tree()
- {
- #define SEOF 200
- #define SSIZE 20
- int *op, opst[SSIZE], *pp, prst[SSIZE];
- register int andflg, o;
- register struct hshtab *cs;
- int p, ps, os;
-
- space = treespace;
- op = opst;
- pp = prst;
- cp = cmst;
- *op = SEOF;
- *pp = 06;
- andflg = 0;
-
- advanc:
- switch (o=symbol()) {
-
- case NAME:
- cs = csym;
- if (cs->hclass==0 && cs->htype==0)
- if(nextchar()=='(') {
- /* set function */
- cs->hclass = EXTERN;
- cs->htype = FUNC;
- } else if (initflg)
- cs->hclass = EXTERN;
- else {
- /* set label */
- cs->htype = ARRAY;
- if (cs->hoffset==0)
- cs->hoffset = isn++;
- }
- *cp++ = copname(cs);
- goto tand;
-
- case FCON:
- if (!initflg)
- outcode("BBNB1N1N1N1N0B", DATA,LABEL,
- cval, WDATA, fcval, PROG);
-
- case CON:
- case SFCON:
- *cp++ = block(1,o,(o==CON?INT:DOUBLE),0,cval);
- goto tand;
-
- /* fake a static char array */
- case STRING:
- putstr(cval);
- *cp++ = block(3, NAME, ARRAY+CHAR,0,STATIC,0,cval);
-
- tand:
- if(cp>=cmst+cmsiz) {
- error("Expression overflow");
- exit(1);
- }
- if (andflg)
- goto syntax;
- andflg = 1;
- goto advanc;
-
- case INCBEF:
- case DECBEF:
- if (andflg)
- o =+ 2;
- goto oponst;
-
- case COMPL:
- case EXCLA:
- case SIZEOF:
- if (andflg)
- goto syntax;
- goto oponst;
-
- case MINUS:
- if (!andflg) {
- if ((peeksym=symbol())==FCON) {
- fcval = - fcval;
- goto advanc;
- }
- if (peeksym==SFCON) {
- fcval = - fcval;
- cval =^ 0100000;
- goto advanc;
- }
- o = NEG;
- }
- andflg = 0;
- goto oponst;
-
- case AND:
- case TIMES:
- if (andflg)
- andflg = 0; else
- if(o==AND)
- o = AMPER;
- else
- o = STAR;
- goto oponst;
-
- case LPARN:
- if (andflg) {
- o = symbol();
- if (o==RPARN)
- o = MCALL;
- else {
- peeksym = o;
- o = CALL;
- andflg = 0;
- }
- }
- goto oponst;
-
- case RBRACK:
- case RPARN:
- if (!andflg)
- goto syntax;
- goto oponst;
-
- case DOT:
- case ARROW:
- mosflg++;
- break;
-
- }
- /* binaries */
- if (!andflg)
- goto syntax;
- andflg = 0;
-
- oponst:
- p = (opdope[o]>>9) & 077;
- if ((o==COMMA || o==COLON) && initflg)
- p = 05;
- opon1:
- ps = *pp;
- if (p>ps || p==ps && (opdope[o]&RASSOC)!=0) {
- switch (o) {
-
- case INCAFT:
- case DECAFT:
- p = 37;
- break;
- case LPARN:
- case LBRACK:
- case CALL:
- p = 04;
- }
- if (op >= &opst[SSIZE-1]) {
- error("expression overflow");
- exit(1);
- }
- *++op = o;
- *++pp = p;
- goto advanc;
- }
- --pp;
- switch (os = *op--) {
-
- case SEOF:
- peeksym = o;
- build(0); /* flush conversions */
- return(*--cp);
-
- case CALL:
- if (o!=RPARN)
- goto syntax;
- build(os);
- goto advanc;
-
- case MCALL:
- *cp++ = block(0,0,0,0); /* 0 arg call */
- os = CALL;
- break;
-
- case INCBEF:
- case INCAFT:
- case DECBEF:
- case DECAFT:
- *cp++ = block(1, CON, INT, 0, 1);
- break;
-
- case LPARN:
- if (o!=RPARN)
- goto syntax;
- goto advanc;
-
- case LBRACK:
- if (o!=RBRACK)
- goto syntax;
- build(LBRACK);
- goto advanc;
- }
- build(os);
- goto opon1;
-
- syntax:
- error("Expression syntax");
- errflush(o);
- return(0);
- }
-
- /*
- * Generate a tree node for a name.
- * All the relevant info from the symbol table is
- * copied out, including the name if it's an external.
- * This is because the symbol table is gone in the next
- * pass, so a ptr isn't sufficient.
- */
- copname(acs)
- struct hshtab *acs;
- {
- register struct hshtab *cs;
- register struct tname *tp;
- register char *cp1;
- int i;
- char *cp2;
-
- cs = acs;
- tp = gblock(sizeof(*tp)/NCPW);
- tp->op = NAME;
- tp->type = cs->htype;
- tp->dimp = cs->hdimp;
- if ((tp->class = cs->hclass)==0)
- tp->class = STATIC;
- tp->offset = 0;
- tp->nloc = cs->hoffset;
- if (cs->hclass==EXTERN) {
- gblock((ncps-NCPW)/NCPW);
- cp1 = tp->nname;
- cp2 = cs->name;
- i = ncps;
- do {
- *cp1++ = *cp2++;
- } while (--i);
- }
- if (cs->hflag&FFIELD)
- tp->class = FMOS;
- return(tp);
- }
-