Research V6 development
authorDennis Ritchie <dmr@research.uucp>
Fri, 18 Jul 1975 10:22:07 +0000 (05:22 -0500)
committerDennis Ritchie <dmr@research.uucp>
Fri, 18 Jul 1975 10:22:07 +0000 (05:22 -0500)
Work on file usr/source/c/cvopt.c
Work on file usr/source/c/table.s
Work on file usr/source/c/c13.c
Work on file usr/source/c/c1t.s
Work on file usr/source/c/c10.c
Work on file usr/source/c/c1h.c
Work on file usr/source/c/c0h.c
Work on file usr/source/c/c03.c
Work on file usr/source/c/c00.c
Work on file usr/source/c/c11.c
Work on file usr/source/c/c20.c
Work on file usr/source/c/c12.c
Work on file usr/source/c/c02.c
Work on file usr/source/c/c04.c
Work on file usr/source/c/c05.c
Work on file usr/source/c/c2h.c
Work on file usr/source/c/c21.c
Work on file usr/source/c/c01.c

Synthesized-from: v6

18 files changed:
usr/source/c/c00.c [new file with mode: 0644]
usr/source/c/c01.c [new file with mode: 0644]
usr/source/c/c02.c [new file with mode: 0644]
usr/source/c/c03.c [new file with mode: 0644]
usr/source/c/c04.c [new file with mode: 0644]
usr/source/c/c05.c [new file with mode: 0644]
usr/source/c/c0h.c [new file with mode: 0644]
usr/source/c/c10.c [new file with mode: 0644]
usr/source/c/c11.c [new file with mode: 0644]
usr/source/c/c12.c [new file with mode: 0644]
usr/source/c/c13.c [new file with mode: 0644]
usr/source/c/c1h.c [new file with mode: 0644]
usr/source/c/c1t.s [new file with mode: 0644]
usr/source/c/c20.c [new file with mode: 0644]
usr/source/c/c21.c [new file with mode: 0644]
usr/source/c/c2h.c [new file with mode: 0644]
usr/source/c/cvopt.c [new file with mode: 0644]
usr/source/c/table.s [new file with mode: 0644]

diff --git a/usr/source/c/c00.c b/usr/source/c/c00.c
new file mode 100644 (file)
index 0000000..51720ec
--- /dev/null
@@ -0,0 +1,709 @@
+#
+/* 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);
+}
diff --git a/usr/source/c/c01.c b/usr/source/c/c01.c
new file mode 100644 (file)
index 0000000..2b33ad3
--- /dev/null
@@ -0,0 +1,521 @@
+#
+/*
+ * C compiler
+ *
+ *
+ */
+
+#include "c0h.c"
+
+/*
+ * Called from tree, this routine takes the top 1, 2, or 3
+ * operands on the expression stack, makes a new node with
+ * the operator op, and puts it on the stack.
+ * Essentially all the work is in inserting
+ * appropriate conversions.
+ */
+build(op) {
+       register int t1;
+       int t2, t3, t;
+       struct tnode *p3, *disarray();
+       register struct tnode *p1, *p2;
+       int d, dope, leftc, cvn, pcvn;
+
+       /*
+        * a[i] => *(a+i)
+        */
+       if (op==LBRACK) {
+               build(PLUS);
+               op = STAR;
+       }
+       dope = opdope[op];
+       if ((dope&BINARY)!=0) {
+               p2 = chkfun(disarray(*--cp));
+               t2 = p2->type;
+       }
+       p1 = *--cp;
+       /*
+        * sizeof gets turned into a number here.
+        * Bug: sizeof(structure-member-array) is 2 because
+        * the array has been turned into a ptr already.
+        */
+       if (op==SIZEOF) {
+               t1 = length(p1);
+               p1->op = CON;
+               p1->type = INT;
+               p1->dimp = 0;
+               p1->value = t1;
+               *cp++ = p1;
+               return;
+       }
+       if (op!=AMPER) {
+               p1 = disarray(p1);
+               if (op!=CALL)
+                       p1 = chkfun(p1);
+       }
+       t1 = p1->type;
+       pcvn = 0;
+       t = INT;
+       switch (op) {
+
+       /* end of expression */
+       case 0:
+               *cp++ = p1;
+               return;
+
+       /* no-conversion operators */
+       case QUEST:
+               if (p2->op!=COLON)
+                       error("Illegal conditional");
+               t = t2;
+
+       case COMMA:
+       case LOGAND:
+       case LOGOR:
+               *cp++ = block(2, op, t, 0, p1, p2);
+               return;
+
+       case CALL:
+               if ((t1&XTYPE) != FUNC)
+                       error("Call of non-function");
+               *cp++ = block(2,CALL,decref(t1),p1->dimp,p1,p2);
+               return;
+
+       case STAR:
+               if (p1->op==AMPER ) {
+                       *cp++ = p1->tr1;
+                       return;
+               }
+               if ((t1&XTYPE) == FUNC)
+                       error("Illegal indirection");
+               *cp++ = block(1,STAR,decref(t1),p1->dimp,p1);
+               return;
+
+       case AMPER:
+               if (p1->op==STAR) {
+                       p1->tr1->dimp = p1->dimp;
+                       p1->tr1->type = incref(t1);
+                       *cp++ = p1->tr1;
+                       return;
+               }
+               if (p1->op==NAME) {
+                       *cp++ = block(1,op,incref(t1),p1->dimp,p1);
+                       return;
+               }
+               error("Illegal lvalue");
+               break;
+
+       /*
+        * a->b goes to (*a).b
+        */
+       case ARROW:
+               *cp++ = p1;
+               chkw(p1, -1);
+               p1->type = PTR+STRUCT;
+               build(STAR);
+               p1 = *--cp;
+
+       /*
+        * In a.b, a fairly complicated process has to
+        * be used to make the left operand look
+        * as if it had the type of the second.
+        * Also, the offset in the structure has to be
+        * given a special type to prevent conversion.
+        */
+       case DOT:
+               if (p2->op!=NAME || (p2->class!=MOS && p2->class!=FMOS))
+                       error("Illegal structure ref");
+               *cp++ = p1;
+               t = t2;
+               if ((t&XTYPE) == ARRAY) {
+                       t = decref(t);
+                       p2->ssp++;
+               }
+               setype(p1, t, p2->dimp);
+               build(AMPER);
+               *cp++ = block(1,CON,NOTYPE,0,p2->nloc);
+               build(PLUS);
+               if ((t2&XTYPE) != ARRAY)
+                       build(STAR);
+               if (p2->class == FMOS)
+                       *cp++ = block(2, FSEL, t, 0, *--cp, p2->dimp);
+               return;
+       }
+       if ((dope&LVALUE)!=0)
+               chklval(p1);
+       if ((dope&LWORD)!=0)
+               chkw(p1, LONG);
+       if ((dope&RWORD)!=0)
+               chkw(p2, LONG);
+       if ((dope&BINARY)==0) {
+               if (op==ITOF)
+                       t1 = DOUBLE;
+               else if (op==FTOI)
+                       t1 = INT;
+               if (!fold(op, p1, 0))
+                       *cp++ = block(1,op,t1,p1->dimp,p1);
+               return;
+       }
+       cvn = 0;
+       if (t1==STRUCT || t2==STRUCT) {
+               error("Unimplemented structure operation");
+               t1 = t2 = INT;
+       }
+       if (t2==NOTYPE) {
+               t = t1;
+               p2->type = INT; /* no int cv for struct */
+               t2 = INT;
+       } else
+               cvn = cvtab[lintyp(t1)][lintyp(t2)];
+       leftc = (cvn>>4)&017;
+       cvn =& 017;
+       t = leftc? t2:t1;
+       if (dope&ASSGOP) {
+               t = t1;
+               if (op==ASSIGN && (cvn==ITP||cvn==PTI))
+                       cvn = leftc = 0;
+               if (leftc)
+                       cvn = leftc;
+               leftc = 0;
+       } else if (op==COLON && t1>=PTR && t1==t2)
+               cvn = 0;
+       else if (dope&RELAT) {
+               if (op>=LESSEQ && (t1>=PTR || t2>=PTR))
+                       op =+ LESSEQP-LESSEQ;
+               if (cvn==PTI)
+                       cvn = 0;
+       }
+       if (cvn==PTI) {
+               cvn = 0;
+               if (op==MINUS) {
+                       t = INT;
+                       pcvn++;
+               } else {
+                       if (t1!=t2 || t1!=(PTR+CHAR))
+                               cvn = XX;
+               }
+       }
+       if (cvn) {
+               t1 = plength(p1);
+               t2 = plength(p2);
+               if (cvn==XX || (cvn==PTI&&t1!=t2))
+                       error("Illegal conversion");
+               else if (leftc)
+                       p1 = convert(p1, t, cvn, t2);
+               else
+                       p2 = convert(p2, t, cvn, t1);
+       }
+       if (dope&RELAT)
+               t = INT;
+       if (fold(op, p1, p2)==0)
+               *cp++ = block(2,op,t,(p1->dimp==0? p2:p1)->dimp,p1,p2);
+       if (pcvn && t1!=(PTR+CHAR)) {
+               p1 = *--cp;
+               *cp++ = convert(p1, 0, PTI, plength(p1->tr1));
+       }
+}
+
+/*
+ * Generate the appropirate conversion operator.
+ * For pointer <=> integer this is a multiplication
+ * or division, otherwise a special operator.
+ */
+convert(p, t, cvn, len)
+struct tnode *p;
+{
+       register int n;
+
+       switch(cvn) {
+
+       case PTI:
+       case ITP:
+               if (len==1)
+                       return(p);
+               return(block(2, (cvn==PTI?DIVIDE:TIMES), t, 0, p,
+                       block(1, CON, 0, 0, len)));
+
+       case ITF:
+               n = ITOF;
+               break;
+       case FTI:
+               n = FTOI;
+               break;
+       case ITL:
+               n = ITOL;
+               break;
+       case LTI:
+               n = LTOI;
+               break;
+       case FTL:
+               n = FTOL;
+               break;
+       case LTF:
+               n = LTOF;
+               break;
+       }
+       return(block(1, n, t, 0, p));
+}
+
+/*
+ * Traverse an expression tree, adjust things
+ * so the types of things in it are consistent
+ * with the view that its top node has
+ * type at.
+ * Used with structure references.
+ */
+setype(ap, at, adimptr)
+struct tnode *ap;
+{
+       register struct tnode *p;
+       register t, dimptr;
+
+       p = ap;
+       t = at;
+       dimptr = adimptr;
+       p->type = t;
+       if (dimptr != -1)
+               p->dimp = dimptr;
+       switch(p->op) {
+
+       case AMPER:
+               setype(p->tr1, decref(t), dimptr);
+               return;
+
+       case STAR:
+               setype(p->tr1, incref(t), dimptr);
+               return;
+
+       case PLUS:
+       case MINUS:
+               setype(p->tr1, t, dimptr);
+       }
+}
+
+/*
+ * A mention of a function name is turned into
+ * a pointer to that function.
+ */
+chkfun(ap)
+struct tnode *ap;
+{
+       register struct tnode *p;
+       register int t;
+
+       p = ap;
+       if (((t = p->type)&XTYPE)==FUNC)
+               return(block(1,AMPER,incref(t),p->dimp,p));
+       return(p);
+}
+
+/*
+ * A mention of an array is turned into
+ * a pointer to the base of the array.
+ */
+struct tnode *disarray(ap)
+struct tnode *ap;
+{
+       register int t;
+       register struct tnode *p;
+
+       p = ap;
+       /* check array & not MOS */
+       if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->class==MOS)
+               return(p);
+       p->ssp++;
+       *cp++ = p;
+       setype(p, decref(t), -1);
+       build(AMPER);
+       return(*--cp);
+}
+
+/*
+ * make sure that p is a ptr to a node
+ * with type int or char or 'okt.'
+ * okt might be nonexistent or 'long'
+ * (e.g. for <<).
+ */
+chkw(p, okt)
+struct tnode *p;
+{
+       register int t;
+
+       if ((t=p->type)>CHAR && t<PTR && t!=okt)
+               error("Integer operand required");
+       return;
+}
+
+/*
+ *'linearize' a type for looking up in the
+ * conversion table
+ */
+lintyp(t)
+{
+       switch(t) {
+
+       case INT:
+       case CHAR:
+               return(0);
+
+       case FLOAT:
+       case DOUBLE:
+               return(1);
+
+       case LONG:
+               return(2);
+
+       default:
+               return(3);
+       }
+}
+
+/*
+ * Report an error.
+ */
+error(s, p1, p2, p3, p4, p5, p6)
+{
+       nerror++;
+       printf("%d: ", line);
+       printf(s, p1, p2, p3, p4, p5, p6);
+       printf("\n");
+}
+
+/*
+ * Generate a node in an expression tree,
+ * setting the operator, type, degree (unused in this pass)
+ * and the operands.
+ */
+block(an, op, t, d, p1,p2,p3)
+int *p1, *p2, *p3;
+{
+       register int *ap, *p, n;
+       int *oldp;
+
+       n = an+3;
+       p = gblock(n);
+       oldp = p;
+       ap = &op;
+       do {
+               *p++ = *ap++;
+       } while (--n);
+       return(oldp);
+}
+
+/*
+ * Assign an unitialized block for use in the
+ * expression tree.
+ */
+gblock(n)
+{
+       register int *p;
+
+       p = space;
+       if ((space =+ n) >= &osspace[OSSIZ]) {
+               error("Expression overflow");
+               exit(1);
+       }
+       return(p);
+}
+
+/*
+ * Check that a tree can be used as an lvalue.
+ */
+chklval(ap)
+struct tnode *ap;
+{
+       register struct tnode *p;
+
+       p = ap;
+       if (p->op!=NAME && p->op!=STAR)
+               error("Lvalue required");
+}
+
+/*
+ * reduce some forms of `constant op constant'
+ * to a constant.  More of this is done in the next pass
+ * but this is used to allow constant expressions
+ * to be used in switches and array bounds.
+ */
+fold(op, ap1, ap2)
+struct tnode *ap1, *ap2;
+{
+       register struct tnode *p1;
+       register int v1, v2;
+
+       p1 = ap1;
+       if (p1->op!=CON || (ap2!=0 && ap2->op!=CON))
+               return(0);
+       v1 = p1->value;
+       v2 = ap2->value;
+       switch (op) {
+
+       case PLUS:
+               v1 =+ v2;
+               break;
+
+       case MINUS:
+               v1 =- v2;
+               break;
+
+       case TIMES:
+               v1 =* v2;
+               break;
+
+       case DIVIDE:
+               v1 =/ v2;
+               break;
+
+       case MOD:
+               v1 =% v2;
+               break;
+
+       case AND:
+               v1 =& v2;
+               break;
+
+       case OR:
+               v1 =| v2;
+               break;
+
+       case EXOR:
+               v1 =^ v2;
+               break;
+
+       case NEG:
+               v1 = - v1;
+               break;
+
+       case COMPL:
+               v1 = ~ v1;
+               break;
+
+       case LSHIFT:
+               v1 =<< v2;
+               break;
+
+       case RSHIFT:
+               v1 =>> v2;
+               break;
+
+       default:
+               return(0);
+       }
+       p1->value = v1;
+       *cp++ = p1;
+       return(1);
+}
+
+/*
+ * Compile an expression expected to have constant value,
+ * for example an array bound or a case value.
+ */
+conexp()
+{
+       register struct tnode *t;
+
+       initflg++;
+       if (t = tree())
+               if (t->op != CON)
+                       error("Constant required");
+       initflg--;
+       return(t->value);
+}
diff --git a/usr/source/c/c02.c b/usr/source/c/c02.c
new file mode 100644 (file)
index 0000000..1a37702
--- /dev/null
@@ -0,0 +1,673 @@
+#
+/* C compiler
+ *
+ *
+ */
+
+#include "c0h.c"
+
+/*
+ * Process a single external definition
+ */
+extdef()
+{
+       register o, elsize;
+       int type, sclass;
+       register struct hshtab *ds;
+
+       if(((o=symbol())==EOF) || o==SEMI)
+               return;
+       peeksym = o;
+       type = INT;
+       sclass = EXTERN;
+       xdflg = FNDEL;
+       if ((elsize = getkeywords(&sclass, &type)) == -1 && peeksym!=NAME)
+               goto syntax;
+       if (type==STRUCT)
+               blkhed();
+       do {
+               defsym = 0;
+               decl1(EXTERN, type, 0, elsize);
+               if ((ds=defsym)==0)
+                       return;
+               funcsym = ds;
+               ds->hflag =| FNDEL;
+               outcode("BS", SYMDEF, ds->name);
+               xdflg = 0;
+               if ((ds->type&XTYPE)==FUNC) {
+                       if ((peeksym=symbol())==LBRACE || peeksym==KEYW) {
+                               funcblk.type = decref(ds->type);
+                               cfunc(ds->name);
+                               return;
+                       }
+               } else 
+                       cinit(ds);
+       } while ((o=symbol())==COMMA);
+       if (o==SEMI)
+               return;
+syntax:
+       if (o==RBRACE) {
+               error("Too many }'s");
+               peeksym = 0;
+               return;
+       }
+       error("External definition syntax");
+       errflush(o);
+       statement(0);
+}
+
+/*
+ * Process a function definition.
+ */
+cfunc(cs)
+char *cs;
+{
+       register savdimp;
+
+       savdimp = dimp;
+       outcode("BBS", PROG, RLABEL, cs);
+       declist(ARG);
+       regvar = 5;
+       retlab = isn++;
+       if ((peeksym = symbol()) != LBRACE)
+               error("Compound statement required");
+       statement(1);
+       outcode("BNB", LABEL, retlab, RETRN);
+       dimp = savdimp;
+}
+
+/*
+ * Process the initializers for an external definition.
+ */
+cinit(ds)
+struct hshtab *ds;
+{
+       register basetype, nel, ninit;
+       int o, width, realwidth;
+
+       nel = 1;
+       basetype = ds->type;
+       /*
+        * If it's an array, find the number of elements.
+        * "basetype" is the type of thing it's an array of.
+        */
+       while ((basetype&XTYPE)==ARRAY) {
+               if ((nel = dimtab[ds->ssp&0377])==0)
+                       nel = 1;
+               basetype = decref(basetype);
+       }
+       realwidth = width = length(ds) / nel;
+       /*
+        * Pretend a structure is kind of an array of integers.
+        * This is a kludge.
+        */
+       if (basetype==STRUCT) {
+               nel =* realwidth/2;
+               width = 2;
+       }
+       if ((peeksym=symbol())==COMMA || peeksym==SEMI) {
+               outcode("BSN",CSPACE,ds->name,(nel*width+ALIGN)&~ALIGN);
+               return;
+       }
+       ninit = 0;
+       outcode("BBS", DATA, NLABEL, ds->name);
+       if ((o=symbol())==LBRACE) {
+               do
+                       ninit = cinit1(ds, basetype, width, ninit, nel);
+               while ((o=symbol())==COMMA);
+               if (o!=RBRACE)
+                       peeksym = o;
+       } else {
+               peeksym = o;
+               ninit = cinit1(ds, basetype, width, 0, nel);
+       }
+       /*
+        * Above we pretended that a structure was a bunch of integers.
+        * Readjust in accordance with reality.
+        * First round up partial initializations.
+        */
+       if (basetype==STRUCT) {
+               if (o = 2*ninit % realwidth)
+                       outcode("BN", SSPACE, realwidth-o);
+               ninit = (2*ninit+realwidth-2) / realwidth;
+               nel =/ realwidth/2;
+       }
+       /*
+        * If there are too few initializers, allocate
+        * more storage.
+        * If there are too many initializers, extend
+        * the declared size for benefit of "sizeof"
+        */
+       if (ninit<nel)
+               outcode("BN", SSPACE, (nel-ninit)*realwidth);
+       else if (ninit>nel) {
+               if ((ds->type&XTYPE)==ARRAY)
+                       dimtab[ds->ssp&0377] = ninit;
+               nel = ninit;
+       }
+       /*
+        * If it's not an array, only one initializer is allowed.
+        */
+       if (ninit>1 && (ds->type&XTYPE)!=ARRAY)
+               error("Too many initializers");
+       if (((nel&width)&ALIGN))
+               outcode("B", EVEN);
+}
+
+/*
+ * Process a single expression in a sequence of initializers
+ * for an external. Mainly, it's for checking
+ * type compatibility.
+ */
+cinit1(ds, type, awidth, aninit, nel)
+struct hshtab *ds;
+{
+       float sf;
+       register struct tnode *s;
+       register width, ninit;
+
+       width = awidth;
+       ninit = aninit;
+       if ((peeksym=symbol())==STRING && type==CHAR) {
+               peeksym = -1;
+               if (ninit)
+                       bxdec();
+               putstr(0);
+               if (nel>nchstr) {
+                       strflg++;
+                       outcode("BN", SSPACE, nel-nchstr);
+                       strflg = 0;
+                       nchstr = nel;
+               }
+               return(nchstr);
+       }
+       if (peeksym==RBRACE)
+               return(ninit);
+       initflg++;
+       s = tree();
+       initflg = 0;
+       switch(width) {
+
+       case 1:
+               if (s->op != CON)
+                       goto bad;
+               outcode("B1N0", BDATA, s->value);
+               break;
+
+       case 2:
+               if (s->op==CON) {
+                       outcode("B1N0", WDATA, s->value);
+                       break;
+               }
+               if (s->op==FCON || s->op==SFCON) {
+                       if (type==STRUCT) {
+                               ninit =+ 3;
+                               goto prflt;
+                       }
+                       goto bad;
+               }
+               rcexpr(block(1,INIT,0,0,s));
+               break;
+
+       case 4:
+               sf = fcval;
+               outcode("B1N1N0", WDATA, sf);
+               goto flt;
+
+       case 8:
+       prflt:
+               outcode("B1N1N1N1N0", WDATA, fcval);
+       flt:
+               if (s->op==FCON || s->op==SFCON)
+                       break;
+
+       default:
+       bad:
+               bxdec();
+
+       }
+       return(++ninit);
+}
+
+bxdec()
+{
+       error("Inconsistent external initialization");
+}
+
+/*
+ * Process one statement in a function.
+ */
+statement(d)
+{
+       register o, o1, o2;
+       int o3, o4;
+       struct tnode *np;
+
+stmt:
+       switch(o=symbol()) {
+
+       case EOF:
+               error("Unexpected EOF");
+       case SEMI:
+               return;
+
+       case LBRACE:
+               if (d) {
+                       if (proflg)
+                               outcode("BN", PROFIL, isn++);
+                       outcode("BN", SAVE, blkhed());
+               }
+               while (!eof) {
+                       if ((o=symbol())==RBRACE)
+                               return;
+                       peeksym = o;
+                       statement(0);
+               }
+               error("Missing '}'");
+               return;
+
+       case KEYW:
+               switch(cval) {
+
+               case GOTO:
+                       if (o1 = simplegoto())
+                               branch(o1);
+                       else 
+                               dogoto();
+                       goto semi;
+
+               case RETURN:
+                       doret();
+                       goto semi;
+
+               case IF:
+                       np = pexpr();
+                       o2 = 0;
+                       if ((o1=symbol())==KEYW) switch (cval) {
+                       case GOTO:
+                               if (o2=simplegoto())
+                                       goto simpif;
+                               cbranch(np, o2=isn++, 0);
+                               dogoto();
+                               label(o2);
+                               goto hardif;
+
+                       case RETURN:
+                               if (nextchar()==';') {
+                                       o2 = retlab;
+                                       goto simpif;
+                               }
+                               cbranch(np, o1=isn++, 0);
+                               doret();
+                               label(o1);
+                               o2++;
+                               goto hardif;
+
+                       case BREAK:
+                               o2 = brklab;
+                               goto simpif;
+
+                       case CONTIN:
+                               o2 = contlab;
+                       simpif:
+                               chconbrk(o2);
+                               cbranch(np, o2, 1);
+                       hardif:
+                               if ((o=symbol())!=SEMI)
+                                       goto syntax;
+                               if ((o1=symbol())==KEYW && cval==ELSE) 
+                                       goto stmt;
+                               peeksym = o1;
+                               return;
+                       }
+                       peeksym = o1;
+                       cbranch(np, o1=isn++, 0);
+                       statement(0);
+                       if ((o=symbol())==KEYW && cval==ELSE) {
+                               o2 = isn++;
+                               branch(o2);
+                               label(o1);
+                               statement(0);
+                               label(o2);
+                               return;
+                       }
+                       peeksym = o;
+                       label(o1);
+                       return;
+
+               case WHILE:
+                       o1 = contlab;
+                       o2 = brklab;
+                       label(contlab = isn++);
+                       cbranch(pexpr(), brklab=isn++, 0);
+                       statement(0);
+                       branch(contlab);
+                       label(brklab);
+                       contlab = o1;
+                       brklab = o2;
+                       return;
+
+               case BREAK:
+                       chconbrk(brklab);
+                       branch(brklab);
+                       goto semi;
+
+               case CONTIN:
+                       chconbrk(contlab);
+                       branch(contlab);
+                       goto semi;
+
+               case DO:
+                       o1 = contlab;
+                       o2 = brklab;
+                       contlab = isn++;
+                       brklab = isn++;
+                       label(o3 = isn++);
+                       statement(0);
+                       label(contlab);
+                       contlab = o1;
+                       if ((o=symbol())==KEYW && cval==WHILE) {
+                               cbranch(tree(), o3, 1);
+                               label(brklab);
+                               brklab = o2;
+                               goto semi;
+                       }
+                       goto syntax;
+
+               case CASE:
+                       o1 = conexp();
+                       if ((o=symbol())!=COLON)
+                               goto syntax;
+                       if (swp==0) {
+                               error("Case not in switch");
+                               goto stmt;
+                       }
+                       if(swp>=swtab+swsiz) {
+                               error("Switch table overflow");
+                       } else {
+                               swp->swlab = isn;
+                               (swp++)->swval = o1;
+                               label(isn++);
+                       }
+                       goto stmt;
+
+               case SWITCH:
+                       o1 = brklab;
+                       brklab = isn++;
+                       np = pexpr();
+                       chkw(np, -1);
+                       rcexpr(block(1,RFORCE,0,0,np));
+                       pswitch();
+                       brklab = o1;
+                       return;
+
+               case DEFAULT:
+                       if (swp==0)
+                               error("Default not in switch");
+                       if ((o=symbol())!=COLON)
+                               goto syntax;
+                       label(deflab = isn++);
+                       goto stmt;
+
+               case FOR:
+                       o1 = contlab;
+                       o2 = brklab;
+                       contlab = isn++;
+                       brklab = isn++;
+                       if (o=forstmt())
+                               goto syntax;
+                       label(brklab);
+                       contlab = o1;
+                       brklab = o2;
+                       return;
+               }
+
+               error("Unknown keyword");
+               goto syntax;
+
+       case NAME:
+               if (nextchar()==':') {
+                       peekc = 0;
+                       o1 = csym;
+                       if (o1->hclass>0) {
+                               error("Redefinition");
+                               goto stmt;
+                       }
+                       o1->hclass = STATIC;
+                       o1->htype = ARRAY;
+                       if (o1->hoffset==0)
+                               o1->hoffset = isn++;
+                       label(o1->hoffset);
+                       goto stmt;
+               }
+       }
+       peeksym = o;
+       rcexpr(tree());
+
+semi:
+       if ((o=symbol())==SEMI)
+               return;
+syntax:
+       error("Statement syntax");
+       errflush(o);
+}
+
+/*
+ * Process a for statement.
+ */
+forstmt()
+{
+       register int l, o, sline;
+       int sline1, *ss;
+       struct tnode *st;
+
+       if ((o=symbol()) != LPARN)
+               return(o);
+       if ((o=symbol()) != SEMI) {             /* init part */
+               peeksym = o;
+               rcexpr(tree());
+               if ((o=symbol()) != SEMI)
+                       return(o);
+       }
+       label(contlab);
+       if ((o=symbol()) != SEMI) {             /* test part */
+               peeksym = o;
+               rcexpr(block(1,CBRANCH,tree(),brklab,0));
+               if ((o=symbol()) != SEMI)
+                       return(o);
+       }
+       if ((peeksym=symbol()) == RPARN) {      /* incr part */
+               peeksym = -1;
+               statement(0);
+               branch(contlab);
+               return(0);
+       }
+       l = contlab;
+       contlab = isn++;
+       st = tree();
+       sline = line;
+       if ((o=symbol()) != RPARN)
+               return(o);
+       ss = treespace;
+       treespace = space;
+       statement(0);
+       sline1 = line;
+       line = sline;
+       label(contlab);
+       rcexpr(st);
+       line = sline1;
+       treespace = ss;
+       branch(l);
+       return(0);
+}
+
+/*
+ * A parenthesized expression,
+ * as after "if".
+ */
+pexpr()
+{
+       register o, t;
+
+       if ((o=symbol())!=LPARN)
+               goto syntax;
+       t = tree();
+       if ((o=symbol())!=RPARN)
+               goto syntax;
+       return(t);
+syntax:
+       error("Statement syntax");
+       errflush(o);
+       return(0);
+}
+
+/*
+ * The switch stateent, which involves collecting the
+ * constants and labels for the cases.
+ */
+pswitch()
+{
+       register struct swtab *cswp, *sswp;
+       int dl, swlab;
+
+       cswp = sswp = swp;
+       if (swp==0)
+               cswp = swp = swtab;
+       branch(swlab=isn++);
+       dl = deflab;
+       deflab = 0;
+       statement(0);
+       branch(brklab);
+       label(swlab);
+       if (deflab==0)
+               deflab = brklab;
+       outcode("BNN", SWIT, deflab, line);
+       for (; cswp < swp; cswp++)
+               outcode("NN", cswp->swlab, cswp->swval);
+       outcode("0");
+       label(brklab);
+       deflab = dl;
+       swp = sswp;
+}
+
+/*
+ * blkhed is called at the start of each function.
+ * It reads the declarations at the start;
+ * then assigns storage locations for the
+ * parameters (which have been linked into a list,
+ * in order of appearance).
+ * This list is necessary because in
+ * f(a, b) float b; int a; ...
+ * the names are seen before the types.
+ * Also, the routine adjusts structures involved
+ * in some kind of forward-referencing.
+ */
+blkhed()
+{
+       register pl;
+       register struct hshtab *cs;
+
+       autolen = 6;
+       declist(0);
+       pl = 4;
+       while(paraml) {
+               parame->hoffset = 0;
+               cs = paraml;
+               paraml = paraml->hoffset;
+               if (cs->htype==FLOAT)
+                       cs->htype = DOUBLE;
+               cs->hoffset = pl;
+               cs->hclass = AUTO;
+               if ((cs->htype&XTYPE) == ARRAY) {
+                       cs->htype =- (ARRAY-PTR);       /* set ptr */
+                       cs->ssp++;              /* pop dims */
+               }
+               pl =+ rlength(cs);
+       }
+       for (cs=hshtab; cs<hshtab+hshsiz; cs++) {
+               if (cs->name[0] == '\0')
+                       continue;
+               /* check tagged structure */
+               if (cs->hclass>KEYWC && (cs->htype&TYPE)==RSTRUCT) {
+                       cs->lenp = dimtab[cs->lenp&0377]->lenp;
+                       cs->htype = cs->htype&~TYPE | STRUCT;
+               }
+               if (cs->hclass == STRTAG && dimtab[cs->lenp&0377]==0)
+                       error("Undefined structure: %.8s", cs->name);
+               if (cs->hclass == ARG)
+                       error("Not an argument: %.8s", cs->name);
+               if (stflg)
+                       prste(cs);
+       }
+       space = treespace;
+       outcode("BN", SETREG, regvar);
+       return(autolen);
+}
+
+/*
+ * After a function definition, delete local
+ * symbols.
+ * Also complain about undefineds.
+ */
+blkend() {
+       register struct hshtab *cs;
+
+       for (cs=hshtab; cs<hshtab+hshsiz; cs++) {
+               if (cs->name[0]) {
+                       if (cs->hclass==0 && (cs->hflag&FNUND)==0) {
+                               error("%.8s undefined", cs->name);
+                               cs->hflag =| FNUND;
+                       }
+                       if((cs->hflag&FNDEL)==0) {
+                               cs->name[0] = '\0';
+                               hshused--;
+                               cs->hflag =& ~(FNUND|FFIELD);
+                       }
+               }
+       }
+}
+
+/*
+ * write out special definitions of local symbols for
+ * benefit of the debugger.  None of these are used
+ * by the assembler except to save them.
+ */
+prste(acs)
+{
+       register struct hshtab *cs;
+       register nkind;
+
+       cs = acs;
+       switch (cs->hclass) {
+       case REG:
+               nkind = RNAME;
+               break;
+
+       case AUTO:
+               nkind = ANAME;
+               break;
+
+       case STATIC:
+               nkind = SNAME;
+               break;
+
+       default:
+               return;
+
+       }
+       outcode("BSN", nkind, cs->name, cs->hoffset);
+}
+
+/*
+ * In case of error, skip to the next
+ * statement delimiter.
+ */
+errflush(ao)
+{
+       register o;
+
+       o = ao;
+       while(o>RBRACE) /* ; { } */
+               o = symbol();
+       peeksym  = o;
+}
diff --git a/usr/source/c/c03.c b/usr/source/c/c03.c
new file mode 100644 (file)
index 0000000..3c72ae0
--- /dev/null
@@ -0,0 +1,412 @@
+#
+/*
+ * C compiler, phase 1
+ *
+ *
+ * Handles processing of declarations,
+ * except for top-level processing of
+ * externals.
+ */
+
+#include "c0h.c"
+
+/*
+ * Process a sequence of declaration statements
+ */
+declist(sclass)
+{
+       register sc, elsize, offset;
+       int type;
+
+       offset = 0;
+       sc = sclass;
+       while ((elsize = getkeywords(&sclass, &type)) != -1) {
+               offset = declare(sclass, type, offset, elsize);
+               sclass = sc;
+       }
+       return(offset+align(INT, offset, 0));
+}
+
+/*
+ * Read the keywords introducing a declaration statement
+ */
+getkeywords(scptr, tptr)
+int *scptr, *tptr;
+{
+       register skw, tkw, longf;
+       int o, elsize, isadecl, ismos;
+
+       isadecl = 0;
+       longf = 0;
+       tkw = -1;
+       skw = *scptr;
+       elsize = 0;
+       ismos = skw==MOS;
+       for (;;) {
+               mosflg = ismos;
+               switch ((o=symbol())==KEYW? cval: -1) {
+
+               case AUTO:
+               case STATIC:
+               case EXTERN:
+               case REG:
+                       if (skw && skw!=cval)
+                               error("Conflict in storage class");
+                       skw = cval;
+                       break;
+       
+               case LONG:
+                       longf++;
+                       break;
+
+               case STRUCT:
+                       o = STRUCT;
+                       elsize = strdec(&o, ismos);
+                       cval = o;
+               case INT:
+               case CHAR:
+               case FLOAT:
+               case DOUBLE:
+                       if (tkw>=0)
+                               error("Type clash");
+                       tkw = cval;
+                       break;
+       
+               default:
+                       peeksym = o;
+                       if (isadecl==0)
+                               return(-1);
+                       if (tkw<0)
+                               tkw = INT;
+                       if (skw==0)
+                               skw = AUTO;
+                       if (longf) {
+                               if (tkw==FLOAT)
+                                       tkw = DOUBLE;
+                               else if (tkw==INT)
+                                       tkw = LONG;
+                               else
+                                       error("Misplaced 'long'");
+                       }
+                       *scptr = skw;
+                       *tptr = tkw;
+                       return(elsize);
+               }
+               isadecl++;
+       }
+}
+
+/*
+ * Process a structure declaration; a subroutine
+ * of getkeywords.
+ */
+strdec(tkwp, mosf)
+int *tkwp;
+{
+       register elsize, o;
+       register struct hshtab *ssym;
+       int savebits;
+       struct hshtab *ds;
+
+       mosflg = 1;
+       ssym = 0;
+       if ((o=symbol())==NAME) {
+               ssym = csym;
+               if (ssym->hclass==0) {
+                       ssym->hclass = STRTAG;
+                       ssym->lenp = dimp;
+                       chkdim();
+                       dimtab[dimp++] = 0;
+               }
+               if (ssym->hclass != STRTAG)
+                       redec();
+               mosflg = mosf;
+               o = symbol();
+       }
+       mosflg = 0;
+       if (o != LBRACE) {
+               if (ssym==0) {
+               syntax:
+                       decsyn(o);
+                       return(0);
+               }
+               if (ssym->hclass!=STRTAG)
+                       error("Bad structure name");
+               if ((elsize = dimtab[ssym->lenp&0377])==0) {
+                       *tkwp = RSTRUCT;
+                       elsize = ssym;
+               }
+               peeksym = o;
+       } else {
+               ds = defsym;
+               mosflg = 0;
+               savebits = bitoffs;
+               bitoffs = 0;
+               elsize = declist(MOS);
+               bitoffs = savebits;
+               defsym = ds;
+               if ((o = symbol()) != RBRACE)
+                       goto syntax;
+               if (ssym) {
+                       if (dimtab[ssym->lenp&0377])
+                               error("%.8s redeclared", ssym->name);
+                       dimtab[ssym->lenp&0377] = elsize;
+               }
+       }
+       return(elsize);
+}
+
+/*
+ * Check that the dimension table has not overflowed
+ */
+chkdim()
+{
+       if (dimp >= dimsiz) {
+               error("Dimension/struct table overflow");
+               exit(1);
+       }
+}
+
+/*
+ * Process a comma-separated list of declarators
+ */
+declare(askw, tkw, offset, elsize)
+{
+       register int o;
+       register int skw;
+
+       skw = askw;
+       do {
+               offset =+ decl1(skw, tkw, offset, elsize);
+       } while ((o=symbol()) == COMMA);
+       if (o==SEMI || o==RPARN && skw==ARG1)
+               return(offset);
+       decsyn(o);
+}
+
+/*
+ * Process a single declarator
+ */
+decl1(askw, tkw, offset, elsize)
+{
+       int t1, chkoff, a;
+       register int type, skw;
+       register struct hshtab *dsym;
+
+       skw = askw;
+       chkoff = 0;
+       mosflg = skw==MOS;
+       if ((peeksym=symbol())==SEMI || peeksym==RPARN)
+               return(0);
+       /*
+        * Filler field
+        */
+       if (peeksym==COLON && skw==MOS) {
+               peeksym = -1;
+               t1 = conexp();
+               elsize = align(tkw, offset, t1);
+               bitoffs =+ t1;
+               return(elsize);
+       }
+       if ((t1=getype()) < 0)
+               goto syntax;
+       type = 0;
+       do
+               type = type<<TYLEN | (t1 & XTYPE);
+       while (((t1=>>TYLEN) & XTYPE)!=0);
+       type =| tkw;
+       dsym = defsym;
+       if (!(dsym->hclass==0
+          || (skw==ARG && dsym->hclass==ARG1)
+          || (skw==EXTERN && dsym->hclass==EXTERN && dsym->htype==type)))
+               if (skw==MOS && dsym->hclass==MOS && dsym->htype==type)
+                       chkoff = 1;
+               else {
+                       redec();
+                       goto syntax;
+               }
+       dsym->htype = type;
+       if (skw)
+               dsym->hclass = skw;
+       if (skw==ARG1) {
+               if (paraml==0)
+                       paraml = dsym;
+               else
+                       parame->hoffset = dsym;
+               parame = dsym;
+       }
+       if (elsize && ((type&TYPE)==RSTRUCT || (type&TYPE)==STRUCT)) {
+               dsym->lenp = dimp;
+               chkdim();
+               dimtab[dimp++] = elsize;
+       }
+       elsize = 0;
+       if (skw==MOS) {
+               elsize = length(dsym);
+               t1 = 0;
+               if ((peeksym = symbol())==COLON) {
+                       elsize = 0;
+                       peeksym = -1;
+                       t1 = conexp();
+                       dsym->hflag =| FFIELD;
+               }
+               a = align(type, offset, t1);
+               elsize =+ a;
+               offset =+ a;
+               if (t1) {
+                       if (chkoff && (dsym->bitoffs!=bitoffs
+                        || dsym->flen!=t1))
+                               redec();
+                       dsym->bitoffs = bitoffs;
+                       dsym->flen = t1;
+                       bitoffs =+ t1;
+               }
+               if (chkoff && dsym->hoffset != offset)
+                       redec();
+               dsym->hoffset = offset;
+       }
+       if ((dsym->htype&XTYPE)==FUNC) {
+               if (dsym->hclass!=EXTERN && dsym->hclass!=AUTO)
+                       error("Bad function");
+               dsym->hclass = EXTERN;
+       }
+       if (dsym->hclass==AUTO) {
+               autolen =+ rlength(dsym);
+               dsym->hoffset = -autolen;
+       } else if (dsym->hclass==STATIC) {
+               dsym->hoffset = isn;
+               outcode("BBNBNB", BSS, LABEL, isn++,
+                   SSPACE, rlength(dsym), PROG);
+       } else if (dsym->hclass==REG) {
+               if ((type&TYPE)>CHAR && (type&XTYPE)==0
+                || (type&XTYPE)>PTR || regvar<3)
+                       error("Bad register %o", type);
+               dsym->hoffset = --regvar;
+       }
+syntax:
+       return(elsize);
+}
+
+/*
+ * Read a declarator and get the implied type
+ */
+getype()
+{
+       register int o, type;
+       register struct hshtab *ds;
+
+       switch(o=symbol()) {
+
+       case TIMES:
+               return(getype()<<TYLEN | PTR);
+
+       case LPARN:
+               type = getype();
+               if ((o=symbol()) != RPARN)
+                       goto syntax;
+               goto getf;
+
+       case NAME:
+               defsym = ds = csym;
+               type = 0;
+               ds->ssp = dimp;
+       getf:
+               switch(o=symbol()) {
+
+               case LPARN:
+                       if (xdflg) {
+                               xdflg = 0;
+                               ds = defsym;
+                               declare(ARG1, 0, 0, 0);
+                               defsym = ds;
+                               xdflg++;
+                       } else
+                               if ((o=symbol()) != RPARN)
+                                       goto syntax;
+                       type = type<<TYLEN | FUNC;
+                       goto getf;
+
+               case LBRACK:
+                       chkdim();
+                       if ((o=symbol()) != RBRACK) {
+                               peeksym = o;
+                               cval = conexp();
+                               for (o=ds->ssp&0377; o<dimp; o++)
+                                       dimtab[o] =* cval;
+                               dimtab[dimp++] = cval;
+                               if ((o=symbol())!=RBRACK)
+                                       goto syntax;
+                       } else
+                               dimtab[dimp++] = 1;
+                       type = type<<TYLEN | ARRAY;
+                       goto getf;
+               }
+               peeksym = o;
+               return(type);
+       }
+syntax:
+       decsyn(o);
+       return(-1);
+}
+
+/*
+ * Enforce alignment restrictions in structures,
+ * including bit-field considerations.
+ */
+align(type, offset, aflen)
+{
+       register a, t, flen;
+       char *ftl;
+
+       flen = aflen;
+       a = offset;
+       t = type;
+       ftl = "Field too long";
+       if (flen==0 && bitoffs) {
+               a =+ (bitoffs-1) / NBPC;
+               bitoffs = 0;
+       }
+       while ((t&XTYPE)==ARRAY)
+               t = decref(t);
+       if (t!=CHAR) {
+               a = (a+ALIGN) & ~ALIGN;
+               if (a>offset)
+                       bitoffs = 0;
+       }
+       if (flen) {
+               if (type==INT) {
+                       if (flen > NBPW)
+                               error(ftl);
+                       if (flen+bitoffs > NBPW) {
+                               bitoffs = 0;
+                               a =+ NCPW;
+                       }
+               } else if (type==CHAR) {
+                       if (flen > NBPC)
+                               error(ftl);
+                       if (flen+bitoffs > NCPW) {
+                               bitoffs = 0;
+                               a =+ 1;
+                       }
+               } else
+                       error("Bad type for field");
+       }
+       return(a-offset);
+}
+
+/*
+ * Complain about syntax error in declaration
+ */
+decsyn(o)
+{
+       error("Declaration syntax");
+       errflush(o);
+}
+
+/*
+ * Complain about a redeclaration
+ */
+redec()
+{
+       error("%.8s redeclared", defsym->name);
+}
diff --git a/usr/source/c/c04.c b/usr/source/c/c04.c
new file mode 100644 (file)
index 0000000..064aed4
--- /dev/null
@@ -0,0 +1,343 @@
+#
+/*
+ * C compiler
+ *
+ *
+ */
+
+#include "c0h.c"
+
+/*
+ * Reduce the degree-of-reference by one.
+ * e.g. turn "ptr-to-int" into "int".
+ */
+decref(at)
+{
+       register t;
+
+       t = at;
+       if ((t & ~TYPE) == 0) {
+               error("Illegal indirection");
+               return(t);
+       }
+       return((t>>TYLEN) & ~TYPE | t&TYPE);
+}
+
+/*
+ * Increase the degree of reference by
+ * one; e.g. turn "int" to "ptr-to-int".
+ */
+incref(t)
+{
+       return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR);
+}
+
+/*
+ * Make a tree that causes a branch to lbl
+ * if the tree's value is non-zero together with the cond.
+ */
+cbranch(tree, lbl, cond)
+struct tnode *tree;
+{
+       rcexpr(block(1,CBRANCH,tree,lbl,cond));
+}
+
+/*
+ * Write out a tree.
+ */
+rcexpr(tree)
+struct tnode *tree;
+{
+
+       treeout(tree);
+       outcode("BN", EXPR, line);
+}
+
+treeout(atree)
+struct tnode *atree;
+{
+       register struct tnode *tree;
+
+       if ((tree = atree) == 0)
+               return;
+       switch(tree->op) {
+
+       case 0:
+               outcode("B", NULL);
+               return;
+
+       case NAME:
+               outcode("BNN", NAME, tree->class, tree->type);
+               if (tree->class==EXTERN)
+                       outcode("S", tree->nname);
+               else
+                       outcode("N", tree->nloc);
+               return;
+
+       case CON:
+       case FCON:
+       case SFCON:
+               outcode("BNN", tree->op, tree->type, tree->value);
+               return;
+
+       case FSEL:
+               treeout(tree->tr1);
+               outcode("BNN", tree->op, tree->type, tree->tr2);
+               return;
+
+       case CBRANCH:
+               treeout(tree->btree);
+               outcode("BNN", tree->op, tree->lbl, tree->cond);
+               return;
+
+       default:
+               treeout(tree->tr1);
+               if (opdope[tree->op]&BINARY)
+                       treeout(tree->tr2);
+               outcode("BN", tree->op, tree->type);
+               return;
+       }
+}
+
+/*
+ * Generate a branch
+ */
+branch(lab) {
+       outcode("BN", BRANCH, lab);
+}
+
+/*
+ * Generate a label
+ */
+label(l) {
+       outcode("BN", LABEL, l);
+}
+
+/*
+ * ap is a tree node whose type
+ * is some kind of pointer; return the size of the object
+ * to which the pointer points.
+ */
+plength(ap)
+struct tname *ap;
+{
+       register t, l;
+       register struct tname *p;
+
+       p = ap;
+       if (p==0 || ((t=p->type)&~TYPE) == 0)           /* not a reference */
+               return(1);
+       p->type = decref(t);
+       l = length(p);
+       p->type = t;
+       return(l);
+}
+
+/*
+ * return the number of bytes in the object
+ * whose tree node is acs.
+ */
+length(acs)
+struct tnode *acs;
+{
+       register t, n;
+       register struct tnode *cs;
+
+       cs = acs;
+       t = cs->type;
+       n = 1;
+       while ((t&XTYPE) == ARRAY) {
+               t = decref(t);
+               n = dimtab[cs->ssp&0377];
+       }
+       if ((t&~TYPE)==FUNC)
+               return(0);
+       if (t>=PTR)
+               return(2*n);
+       switch(t&TYPE) {
+
+       case INT:
+               return(2*n);
+
+       case CHAR:
+               return(n);
+
+       case FLOAT:
+       case LONG:
+               return(4*n);
+
+       case DOUBLE:
+               return(8*n);
+
+       case STRUCT:
+               return(n * dimtab[cs->lenp&0377]);
+
+       case RSTRUCT:
+               error("Bad structure");
+               return(0);
+       }
+       error("Compiler error (length)");
+}
+
+/*
+ * The number of bytes in an object, rounded up to a word.
+ */
+rlength(cs)
+struct tnode *cs;
+{
+       return((length(cs)+ALIGN) & ~ALIGN);
+}
+
+/*
+ * After an "if (...) goto", look to see if the transfer
+ * is to a simple label.
+ */
+simplegoto()
+{
+       register struct hshtab *csp;
+
+       if ((peeksym=symbol())==NAME && nextchar()==';') {
+               csp = csym;
+               if (csp->hclass==0 && csp->htype==0) {
+                       csp->htype = ARRAY;
+                       if (csp->hoffset==0)
+                               csp->hoffset = isn++;
+               }
+               if ((csp->hclass==0||csp->hclass==STATIC)
+                &&  csp->htype==ARRAY) {
+                       peeksym = -1;
+                       return(csp->hoffset);
+               }
+       }
+       return(0);
+}
+
+/*
+ * Return the next non-white-space character
+ */
+nextchar()
+{
+       while (spnextchar()==' ')
+               peekc = 0;
+       return(peekc);
+}
+
+/*
+ * Return the next character, translating all white space
+ * to blank and handling line-ends.
+ */
+spnextchar()
+{
+       register c;
+
+       if ((c = peekc)==0)
+               c = getchar();
+       if (c=='\t')
+               c = ' ';
+       else if (c=='\n') {
+               c = ' ';
+               if (inhdr==0)
+                       line++;
+               inhdr = 0;
+       } else if (c=='\001') { /* SOH, insert marker */
+               inhdr++;
+               c = ' ';
+       }
+       peekc = c;
+       return(c);
+}
+
+/*
+ * is a break or continue legal?
+ */
+chconbrk(l)
+{
+       if (l==0)
+               error("Break/continue error");
+}
+
+/*
+ * The goto statement.
+ */
+dogoto()
+{
+       register struct tnode *np;
+
+       *cp++ = tree();
+       build(STAR);
+       chkw(np = *--cp, -1);
+       rcexpr(block(1,JUMP,0,0,np));
+}
+
+/*
+ * The return statement, which has to convert
+ * the returned object to the function's type.
+ */
+doret()
+{
+       register struct tnode *t;
+
+       if (nextchar() != ';') {
+               t = tree();
+               *cp++ = &funcblk;
+               *cp++ = t;
+               build(ASSIGN);
+               cp[-1] = cp[-1]->tr2;
+               build(RFORCE);
+               rcexpr(*--cp);
+       }
+       branch(retlab);
+}
+
+/*
+ * write out a character to the usual output
+ * or to the string file
+ */
+putchar(c)
+{
+       write(1, &c, 1);
+}
+
+outcode(s, a)
+char *s;
+{
+       register char *sp;
+       register *ap, *bufp;
+       int n;
+       char *np;
+
+       bufp = obuf;
+       if (strflg)
+               bufp = sbuf;
+       ap = &a;
+       for (;;) switch(*s++) {
+       case 'B':
+               putw(*ap++ | (0376<<8), bufp);
+               continue;
+
+       case 'N':
+               putw(*ap++, bufp);
+               continue;
+
+       case 'S':
+               np = *ap++;
+               n = ncps;
+               while (n-- && *np) {
+                       putc(*np++, bufp);
+               }
+               putc(0, bufp);
+               continue;
+
+       case '1':
+               putw(1, bufp);
+               continue;
+
+       case '0':
+               putw(0, bufp);
+               continue;
+
+       case '\0':
+               return;
+       }
+       error("Botch in outcode");
+}
diff --git a/usr/source/c/c05.c b/usr/source/c/c05.c
new file mode 100644 (file)
index 0000000..3dbad30
--- /dev/null
@@ -0,0 +1,176 @@
+#
+#include "c0h.c"
+/*
+ *  info on operators:
+ *   01-- is binary operator
+ *   02-- left (or only) operand must be lvalue
+ *   04-- is relational operator
+ *  010-- is assignment-type operator
+ *  020-- non-float req. on left
+ *  040-- non-float req. on right
+ * 0100-- is commutative
+ * 0200-- is right, not left-associative
+ * 0400-- is leaf of tree
+ * *0XX000-- XX is priority of operator
+ */
+int opdope[] {
+       000000, /* EOF */
+       000000, /* ; */
+       000000, /* { */
+       000000, /* } */
+       036000, /* [ */
+       002000, /* ] */
+       036000, /* ( */
+       002000, /* ) */
+       014201, /* : */
+       007001, /* , */
+       000000, /* field selection */
+       000000, /* 11 */
+       000000, /* 12 */
+       000000, /* 13 */
+       000000, /* 14 */
+       000000, /* 15 */
+       000000, /* 16 */
+       000000, /* 17 */
+       000000, /* 18 */
+       000000, /* 19 */
+       000400, /* name */
+       000400, /* short constant */
+       000400, /* string */
+       000400, /* float */
+       000400, /* double */
+       000000, /* 25 */
+       000000, /* 26 */
+       000000, /* 27 */
+       000000, /* 28 */
+       000000, /* 29 */
+       034203, /* ++pre */
+       034203, /* --pre */
+       034203, /* ++post */
+       034203, /* --post */
+       034220, /* !un */
+       034202, /* &un */
+       034220, /* *un */
+       034200, /* -un */
+       034220, /* ~un */
+       036001, /* . (structure reference) */
+       030101, /* + */
+       030001, /* - */
+       032101, /* * */
+       032001, /* / */
+       032001, /* % */
+       026061, /* >> */
+       026061, /* << */
+       020161, /* & */
+       017161, /* | */
+       017161, /* ^ */
+       036001, /* -> */
+       000000, /* int -> double */
+       000000, /* double -> int */
+       016001, /* && */
+       015001, /* || */
+       030001, /* &~ */
+       000000, /* 56 */
+       000000, /* 57 */
+       000000, /* 58 */
+       000000, /* 59 */
+       022005, /* == */
+       022005, /* != */
+       024005, /* <= */
+       024005, /* < */
+       024005, /* >= */
+       024005, /* > */
+       024005, /* <p */
+       024005, /* <=p */
+       024005, /* >p */
+       024005, /* >=p */
+       012213, /* =+ */
+       012213, /* =- */
+       012213, /* =* */
+       012213, /* =/ */
+       012213, /* =% */
+       012253, /* =>> */
+       012253, /* =<< */
+       012253, /* =& */
+       012253, /* =| */
+       012253, /* =^ */
+       012213, /* = */
+       000000, /* 81 */
+       000000, /* 82 */
+       000000, /* 83 */
+       000000, /* 84 */
+       000000, /* 85 */
+       000000, /* 86 */
+       000000, /* 87 */
+       000000, /* 88 */
+       000000, /* 89 */
+       014201, /* ? */
+       034200, /* sizeof */
+       000000, /* 92 */
+       000000, /* 93 */
+       000000, /* 94 */
+       000000, /* 95 */
+       000000, /* 96 */
+       000000, /* 97 */
+       000000, /* 98 */
+       000000, /* 99 */
+       036001, /* call */
+       036001, /* mcall */
+       000000, /* goto */
+       000000, /* jump cond */
+       000000, /* branch cond */
+       000000, /* 105 */
+       000000, /* 106 */
+       000000, /* 107 */
+       000000, /* 108 */
+       000000, /* 109 */
+       000000  /* force r0 */
+};
+
+/*
+ * conversion table:
+ * FTI: float (or double) to integer
+ * ITF: integer to float
+ * ITP: integer to pointer
+ * ITL: integer to long
+ * LTI: long to integer
+ * LTF: long to float
+ * FTL: float to long
+ * PTI: pointer to integer
+ * XX: usually illegal
+ * When FTI, LTI, FTL are added in they specify
+ * that it is the left operand that should be converted.
+ * For + this is done and the conversion is turned back into
+ * ITF, ITL, LTF.
+ * For = however the left operand can't be converted
+ * and the specified conversion is applied to the rhs.
+ */
+char cvtab[4][4] {
+/*             int     double          long            ptr */
+/* int */      0,      (FTI<<4)+ITF,   (LTI<<4)+ITL,   (ITP<<4)+ITP,   
+/* double */   ITF,    0,              LTF,            XX,
+/* long */     ITL,    (FTL<<4)+LTF,   0,              XX,
+/* ptr */      ITP,    XX,             XX,             PTI
+};
+
+/*
+ * character type table
+ */
+char ctab[] {
+       EOF,    INSERT, UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,
+       UNKN,   SPACE,  NEWLN,  UNKN,   UNKN,   UNKN,   UNKN,   UNKN,
+       UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,
+       UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,
+       SPACE,  EXCLA,  DQUOTE, UNKN,   UNKN,   MOD,     AND,   SQUOTE,
+       LPARN,  RPARN,  TIMES,  PLUS,   COMMA,  MINUS,  PERIOD, DIVIDE,
+       DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,
+       DIGIT,  DIGIT,  COLON,  SEMI,   LESS,   ASSIGN, GREAT,  QUEST,
+       UNKN,   LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+       LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+       LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+       LETTER, LETTER, LETTER, LBRACK, UNKN,   RBRACK, EXOR,   LETTER,
+       UNKN,   LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+       LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+       LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+       LETTER, LETTER, LETTER, LBRACE, OR,     RBRACE, COMPL,  UNKN
+};
diff --git a/usr/source/c/c0h.c b/usr/source/c/c0h.c
new file mode 100644 (file)
index 0000000..90b67db
--- /dev/null
@@ -0,0 +1,351 @@
+#
+/*
+
+       C compiler-- pass 1 header
+
+
+*/
+
+/*
+  parameters
+*/
+
+#define        ncps    8
+#define        hshsiz  200
+#define        cmsiz   40
+#define        swsiz   200
+#define        OSSIZ   500
+#define        dimsiz  100
+#define        NBPW    16
+#define        NBPC    8
+#define        NCPW    2
+#define        STRSIZ  256
+
+struct tnode {
+       int     op;
+       int     type;
+       int     dimp;
+       struct  tnode *tr1, *tr2;
+};
+
+struct {
+       int     op;
+       int     type;
+       char    ssp;            /* subscript list */
+       char    lenp;           /* structure length */
+};
+
+struct tname {
+       int     op;
+       int     type;
+       int     dimp;
+       int     class;
+       int     offset;
+       int     nloc;
+};
+
+struct txname {
+       int     op;
+       int     type;
+       int     dimp;
+       int     class;
+       int     offset;
+       char    nname[ncps];
+};
+
+struct tconst {
+       int     op;
+       int     type;
+       int     dimp;
+       int     value;
+};
+
+struct hshtab {
+       char    hclass;
+       char    hflag;
+       int     htype;
+       int     hdimp;
+       int     hoffset;
+       char    name[ncps];
+};
+
+struct {
+       char    hclass;
+       char    hflag;
+       int     htype;
+       char    flen;           /* Field length */
+       char    bitoffs;        /* Offset of field */
+};
+
+struct swtab {
+       int     swlab;
+       int     swval;
+};
+
+struct bnode {
+       int     bop;
+       struct  tnode *btree;
+       int     lbl;
+       int     cond;
+};
+
+char   cvtab[4][4];
+char   savstr[STRSIZ];
+char   *strptr;
+int    opdope[];
+char   ctab[];
+char   symbuf[ncps+2];
+int    hshused;
+struct hshtab  hshtab[hshsiz];
+int    *space;
+int    *cp;
+int    cmst[cmsiz];
+int    isn;
+struct swtab   swtab[swsiz];
+struct swtab   *swp;
+int    contlab;
+int    brklab;
+int    retlab;
+int    deflab;
+int    nauto;
+int    autolen;
+int    peeksym;
+int    peekc;
+int    eof;
+int    line;
+int    osspace[OSSIZ];
+int    *treespace;
+struct hshtab  *defsym;
+struct hshtab  *funcsym;
+int    xdflg;
+int    proflg;
+int    stflg;
+struct hshtab  *csym;
+int    cval;
+double fcval;
+int    nchstr;
+int    nerror;
+struct hshtab  *paraml;
+struct hshtab  *parame;
+int    strflg;
+int    mosflg;
+int    initflg;
+int    inhdr;
+int    dimtab[dimsiz];
+char   obuf[518];
+char   sbuf[518];
+int    dimp;
+int    regvar;
+int    bitoffs;
+struct tname   funcblk;
+
+/*
+  operators
+*/
+#define        EOF     0
+#define        SEMI    1
+#define        LBRACE  2
+#define        RBRACE  3
+#define        LBRACK  4
+#define        RBRACK  5
+#define        LPARN   6
+#define        RPARN   7
+#define        COLON   8
+#define        COMMA   9
+#define        FSEL    10
+
+#define        KEYW    19
+#define        NAME    20
+#define        CON     21
+#define        STRING  22
+#define        FCON    23
+#define        SFCON   24
+
+#define        SIZEOF  91
+#define        INCBEF  30
+#define        DECBEF  31
+#define        INCAFT  32
+#define        DECAFT  33
+#define        EXCLA   34
+#define        AMPER   35
+#define        STAR    36
+#define        NEG     37
+#define        COMPL   38
+
+#define        DOT     39
+#define        PLUS    40
+#define        MINUS   41
+#define        TIMES   42
+#define        DIVIDE  43
+#define        MOD     44
+#define        RSHIFT  45
+#define        LSHIFT  46
+#define        AND     47
+#define        OR      48
+#define        EXOR    49
+#define        ARROW   50
+#define        ITOF    51
+#define        FTOI    52
+#define        LOGAND  53
+#define        LOGOR   54
+#define        FTOL    56
+#define        LTOF    57
+#define        ITOL    58
+#define        LTOI    59
+
+#define        EQUAL   60
+#define        NEQUAL  61
+#define        LESSEQ  62
+#define        LESS    63
+#define        GREATEQ 64
+#define        GREAT   65
+#define        LESSEQP 66
+#define        LESSP   67
+#define        GREATQP 68
+#define        GREATP  69
+
+#define        ASPLUS  70
+#define        ASMINUS 71
+#define        ASTIMES 72
+#define        ASDIV   73
+#define        ASMOD   74
+#define        ASRSH   75
+#define        ASLSH   76
+#define        ASSAND  77
+#define        ASOR    78
+#define        ASXOR   79
+#define        ASSIGN  80
+
+#define        QUEST   90
+#define        CALL    100
+#define        MCALL   101
+#define        JUMP    102
+#define        CBRANCH 103
+#define        INIT    104
+#define        SETREG  105
+#define        RFORCE  110
+#define        BRANCH  111
+#define        LABEL   112
+#define        NLABEL  113
+#define        RLABEL  114
+
+/*
+  types
+*/
+#define        INT     0
+#define        CHAR    1
+#define        FLOAT   2
+#define        DOUBLE  3
+#define        STRUCT  4
+#define        RSTRUCT 5
+#define        LONG    6
+#define        NOTYPE  7       /* used internally */
+
+#define        ALIGN   01
+#define        TYPE    07
+#define        TYLEN   2
+#define        XTYPE   (03<<3)
+#define        PTR     010
+#define        FUNC    020
+#define        ARRAY   030
+
+/*
+  storage classes
+*/
+#define        KEYWC   1
+#define        MOS     10
+#define        AUTO    11
+#define        EXTERN  12
+#define        STATIC  13
+#define        REG     14
+#define        STRTAG  15
+#define ARG    16
+#define        ARG1    17
+#define        FMOS    18
+
+/*
+  keywords
+*/
+#define        GOTO    20
+#define        RETURN  21
+#define        IF      22
+#define        WHILE   23
+#define        ELSE    24
+#define        SWITCH  25
+#define        CASE    26
+#define        BREAK   27
+#define        CONTIN  28
+#define        DO      29
+#define        DEFAULT 30
+#define        FOR     31
+
+/*
+  characters
+*/
+#define        INSERT  119
+#define        PERIOD  120
+#define        SQUOTE  121
+#define        DQUOTE  122
+#define        LETTER  123
+#define        DIGIT   124
+#define        NEWLN   125
+#define        SPACE   126
+#define        UNKN    127
+
+/*
+ * Special operators in intermediate code
+ */
+#define        BDATA   200
+#define        WDATA   201
+#define        PROG    202
+#define        DATA    203
+#define        BSS     204
+#define        CSPACE  205
+#define        SSPACE  206
+#define        SYMDEF  207
+#define        SAVE    208
+#define        RETRN   209
+#define        EVEN    210
+#define        PROFIL  212
+#define        SWIT    213
+#define        EXPR    214
+#define        SNAME   215
+#define        RNAME   216
+#define        ANAME   217
+#define        NULL    218
+
+/*
+  Flag bits
+*/
+
+#define        BINARY  01
+#define        LVALUE  02
+#define        RELAT   04
+#define        ASSGOP  010
+#define        LWORD   020
+#define        RWORD   040
+#define        COMMUTE 0100
+#define        RASSOC  0200
+#define        LEAF    0400
+
+/*
+ * Conversion codes
+ */
+#define        ITF     1
+#define        ITL     2
+#define        LTF     3
+#define        ITP     4
+#define        PTI     5
+#define        FTI     6
+#define        LTI     7
+#define        FTL     8
+#define        XX      15
+
+/*
+ * symbol table flags
+ */
+
+#define        FNDEL   01
+#define        FNUND   02
+#define        FKEYW   04
+#define        FFIELD  020
diff --git a/usr/source/c/c10.c b/usr/source/c/c10.c
new file mode 100644 (file)
index 0000000..a3fc68b
--- /dev/null
@@ -0,0 +1,922 @@
+#
+/*
+
+               C compiler, part 2
+
+
+*/
+
+#include "c1h.c"
+
+char   maprel[] {      EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ,
+                       LESS, GREATQP, GREATP, LESSEQP, LESSP
+};
+
+char   notrel[] {      NEQUAL, EQUAL, GREAT, GREATEQ, LESS,
+                       LESSEQ, GREATP, GREATQP, LESSP, LESSEQP
+};
+
+struct tconst czero { CON, INT, 0, 0};
+struct tconst cone  { CON, INT, 0, 1};
+struct tconst fczero { SFCON, DOUBLE, 0, 0 };
+
+struct table   *cregtab;
+
+int    nreg    3;
+int    isn     10000;
+int    namsiz  8;
+
+main(argc, argv)
+char *argv[];
+{
+       extern fout;
+
+       if (argc<4) {
+               error("Arg count");
+               exit(1);
+       }
+       if(fopen(argv[1], ascbuf)<0) {
+               error("Missing temp file");
+               exit(1);
+       }
+       if ((fout = creat(argv[3], 0666)) < 0) {
+               error("Can't create %s", argv[3]);
+               exit(1);
+       }
+       spacep = treespace;
+       getree();
+       /*
+        * If any floating-point instructions
+        * were used, generate a reference which
+        * pulls in the floating-point part of printf.
+        */
+       if (nfloat)
+               printf(".globl  fltused\n");
+       /*
+        * tack on the string file.
+        */
+       close(ascbuf[0]);
+       if (fopen(argv[2], ascbuf)<0) {
+               error("Missing temp file");
+               exit(1);
+       }
+       printf(".globl\n.data\n");
+       getree();
+       flush();
+       exit(nerror!=0);
+}
+
+/*
+ * Given a tree, a code table, and a
+ * count of available registers, find the code table
+ * for the appropriate operator such that the operands
+ * are of the right type and the number of registers
+ * required is not too large.
+ * Return a ptr to the table entry or 0 if none found.
+ */
+char *match(atree, table, nrleft)
+struct tnode *atree;
+struct table *table;
+{
+       int op, d1, d2, t1, t2, dope;
+       struct tnode *p2;
+       register struct tnode *p1, *tree;
+       register struct optab *opt;
+
+       if ((tree=atree)==0)
+               return(0);
+       if (table==lsptab)
+               table = sptab;
+       if ((op = tree->op)==0)
+               return(0);
+       dope = opdope[op];
+       if ((dope&LEAF) == 0)
+               p1 = tree->tr1;
+       else
+               p1 = tree;
+       t1 = p1->type;
+       d1 = dcalc(p1, nrleft);
+       if ((dope&BINARY)!=0) {
+               p2 = tree->tr2;
+               /*
+                * If a subtree starts off with a conversion operator,
+                * try for a match with the conversion eliminated.
+                * E.g. int = double can be done without generating
+                * the converted int in a register by
+                * movf double,fr0; movfi fr0,int .
+                */
+               if(opdope[p1->op]&CNVRT && (opdope[p2->op]&CNVRT)==0) {
+                       tree->tr1 = p1->tr1;
+                       if (opt = match(tree, table, nrleft))
+                               return(opt);
+                       tree->tr1 = p1;
+               } else if (opdope[p2->op]&CNVRT && (opdope[p1->op]&CNVRT)==0) {
+                       tree->tr2 = p2->tr1;
+                       if (opt = match(tree, table, nrleft))
+                               return(opt);
+                       tree->tr2 = p2;
+               }
+               t2 = p2->type;
+               d2 = dcalc(p2, nrleft);
+       }
+       for (; table->op!=op; table++)
+               if (table->op==0)
+                       return(0);
+       for (opt = table->tabp; opt->tabdeg1!=0; opt++) {
+               if (d1 > (opt->tabdeg1&077)
+                || (opt->tabdeg1 >= 0100 && (p1->op != STAR)))
+                       continue;
+               if (notcompat(p1, opt->tabtyp1, op)) {
+                       continue;
+               }
+               if ((opdope[op]&BINARY)!=0 && p2!=0) {
+                       if (d2 > (opt->tabdeg2&077)
+                        || (opt->tabdeg2 >= 0100) && (p2->op != STAR) )
+                               continue;
+                       if (notcompat(p2,opt->tabtyp2, 0))
+                               continue;
+               }
+               return(opt);
+       }
+       return(0);
+}
+
+/*
+ * Given a tree, a code table, and a register,
+ * produce code to evaluate the tree with the appropriate table.
+ * Registers reg and upcan be used.
+ * If there is a value, it is desired that it appear in reg.
+ * The routine returns the register in which the value actually appears.
+ * This routine must work or there is an error.
+ * If the table called for is cctab, sptab, or efftab,
+ * and tree can't be done using the called-for table,
+ * another try is made.
+ * If the tree can't be compiled using cctab, regtab is
+ * used and a "tst" instruction is produced.
+ * If the tree can't be compiled using sptab,
+ * regtab is used and the register is pushed on the stack.
+ * If the tree can't be compiled using efftab,
+ * just use regtab.
+ * Regtab must succeed or an "op not found" error results.
+ *
+ * A number of special cases are recognized, and
+ * there is an interaction with the optimizer routines.
+ */
+rcexpr(atree, atable, reg)
+struct tnode *atree;
+struct table *atable;
+{
+       register r;
+       int modf, nargs, recurf;
+       register struct tnode *tree;
+       register struct table *table;
+
+       table = atable;
+       recurf = 0;
+       if (reg<0) {
+               recurf++;
+               reg = ~reg;
+               if (reg>=020) {
+                       reg =- 020;
+                       recurf++;
+               }
+       }
+       if((tree=atree)==0)
+               return(0);
+       switch (tree->op)  {
+
+       /*
+        * A conditional branch
+        */
+       case CBRANCH:
+               cbranch(optim(tree->btree), tree->lbl, tree->cond, 0);
+               return(0);
+
+       /*
+        * An initializing expression
+        */
+       case INIT:
+               if (tree->tr1->op == AMPER)
+                       tree->tr1 = tree->tr1->tr1;
+               if (tree->tr1->op==NAME)
+                       pname(tree->tr1);
+               else if (tree->tr1==CON)
+                       psoct(tree->tr1->value);
+               else
+                       error("Illegal initialization");
+               putchar('\n');
+               return(0);
+
+       /*
+        * Put the value of an expression in r0,
+        * for a switch or a return
+        */
+       case RFORCE:
+               if((r=rcexpr(tree->tr1, regtab, reg)) != 0)
+                       printf("mov%c   r%d,r0\n", isfloat(tree->tr1), r);
+               return(0);
+
+       /*
+        * sequential execution
+        */
+       case COMMA:
+               rcexpr(tree->tr1, efftab, reg);
+               atree = tree = tree->tr2;
+               break;
+
+       /*
+        * In the generated &~ operator,
+        * fiddle things so a PDP-11 "bit"
+        * instruction will be produced when cctab is used.
+        */
+       case NAND:
+               if (table==cctab) {
+                       tree->op = TAND;
+                       tree->tr2 = optim(block(1, COMPL, INT, 0, tree->tr2));
+               }
+               break;
+
+
+       /*
+        * Handle a subroutine call. It has to be done
+        * here because if cexpr got called twice, the
+        * arguments might be compiled twice.
+        * There is also some fiddling so the
+        * first argument, in favorable circumstances,
+        * goes to (sp) instead of -(sp), reducing
+        * the amount of stack-popping.
+        */
+       case CALL:
+               r = 0;
+               nargs = 0;
+               modf = 0;
+               if (tree->tr1->op!=NAME) {      /* get nargs right */
+                       nargs++;
+                       nstack++;
+               }
+               tree = tree->tr2;
+               if(tree->op) {
+                       while (tree->op==COMMA) {
+                               r =+ comarg(tree->tr2, &modf);
+                               tree = tree->tr1;
+                               nargs++;
+                       }
+                       r =+ comarg(tree, &modf);
+                       nargs++;
+               }
+               tree = atree;
+               tree->op = CALL2;
+               if (modf && tree->tr1->op==NAME && tree->tr1->class==EXTERN)
+                       tree->op = CALL1;
+               cexpr(tree, regtab, reg);
+               popstk(r);
+               nstack =- nargs;
+               if (table==efftab || table==regtab)
+                       return(0);
+               r = 0;
+               goto fixup;
+
+       /*
+        * Longs need special treatment.
+        */
+       case ASLSH:
+       case LSHIFT:
+               if (tree->type==LONG) {
+                       if (tree->tr2->op==ITOL)
+                               tree->tr2 = tree->tr2->tr1;
+                       if (tree->op==ASLSH)
+                               tree->op = ASLSHL;
+                       else
+                               tree->op = LLSHIFT;
+               }
+               break;
+
+       /*
+        * Try to change * and / to shifts.
+        */
+       case TIMES:
+       case DIVIDE:
+       case ASTIMES:
+       case ASDIV:
+               tree = pow2(tree);
+       }
+       /*
+        * Try to find postfix ++ and -- operators that can be
+        * pulled out and done after the rest of the expression
+        */
+       if (table!=cctab && table!=cregtab && recurf<2
+        && (opdope[tree->op]&LEAF)==0) {
+               if (r=delay(&atree, table, reg)) {
+                       tree = atree;
+                       table = efftab;
+                       reg = r-1;
+               }
+       }
+       /*
+        * Basically, try to reorder the computation
+        * so  reg = x+y  is done as  reg = x; reg =+ y
+        */
+       if (recurf==0 && reorder(&atree, table, reg)) {
+               if (table==cctab && atree->op==NAME)
+                       return(reg);
+       }
+       tree = atree;
+       if (table==efftab && tree->op==NAME)
+               return(reg);
+       if ((r=cexpr(tree, table, reg))>=0)
+               return(r);
+       if (table!=regtab)  {
+               if((r=cexpr(tree, regtab, reg))>=0) {
+       fixup:
+                       modf = isfloat(tree);
+                       if (table==sptab || table==lsptab) {
+                               if (tree->type==LONG) {
+                                       printf("mov\tr%d,-(sp)\n",r+1);
+                                       nstack++;
+                               }
+                               printf("mov%c   r%d,%c(sp)\n", modf, r,
+                                       table==sptab? '-':0);
+                               nstack++;
+                       }
+                       if (table==cctab)
+                               printf("tst%c   r%d\n", modf, r);
+                       return(r);
+               }
+       }
+       if (tree->op>0 && tree->op<RFORCE && opntab[tree->op])
+               error("No code table for op: %s", opntab[tree->op]);
+       else
+               error("No code table for op %d", tree->op);
+       return(reg);
+}
+
+/*
+ * Try to compile the tree with the code table using
+ * registers areg and up.  If successful,
+ * return the register where the value actually ended up.
+ * If unsuccessful, return -1.
+ *
+ * Most of the work is the macro-expansion of the
+ * code table.
+ */
+cexpr(atree, table, areg)
+struct tnode *atree;
+struct table *table;
+{
+       int c, r;
+       register struct tnode *p, *p1, *tree;
+       struct table *ctable;
+       struct tnode *p2;
+       char *string;
+       int reg, reg1, rreg, flag, opd;
+       char *opt;
+
+       tree = atree;
+       reg = areg;
+       p1 = tree->tr2;
+       c = tree->op;
+       opd = opdope[c];
+       /*
+        * When the value of a relational or a logical expression is
+        * desired, more work must be done.
+        */
+       if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) {
+               cbranch(tree, c=isn++, 1, reg);
+               rcexpr(&czero, table, reg);
+               branch(isn, 0);
+               label(c);
+               rcexpr(&cone, table, reg);
+               label(isn++);
+               return(reg);
+       }
+       if(c==QUEST) {
+               if (table==cctab)
+                       return(-1);
+               cbranch(tree->tr1, c=isn++, 0, reg);
+               flag = nstack;
+               rreg = rcexpr(p1->tr1, table, reg);
+               nstack = flag;
+               branch(r=isn++, 0);
+               label(c);
+               reg = rcexpr(p1->tr2, table, rreg);
+               if (rreg!=reg)
+                       printf("mov%c   r%d,r%d\n",
+                           isfloat(tree),reg,rreg);
+               label(r);
+               return(rreg);
+       }
+       reg = oddreg(tree, reg);
+       reg1 = reg+1;
+       /*
+        * long values take 2 registers.
+        */
+       if (tree->type==LONG && tree->op!=ITOL)
+               reg1++;
+       /*
+        * Leaves of the expression tree
+        */
+       if ((r = chkleaf(tree, table, reg)) >= 0)
+               return(r);
+       /*
+        * x + (-1) is better done as x-1.
+        */
+
+       if ((tree->op==PLUS||tree->op==ASPLUS) &&
+           (p1=tree->tr2)->op == CON && p1->value == -1) {
+               p1->value = 1;
+               tree->op =+ (MINUS-PLUS);
+       }
+       if (table==cregtab)
+               table = regtab;
+       /*
+        * The following peculiar code depends on the fact that
+        * if you just want the codition codes set, efftab
+        * will generate the right code unless the operator is
+        * postfix ++ or --. Unravelled, if the table is
+        * cctab and the operator is not special, try first
+        * for efftab;  if the table isn't, if the operator is,
+        * or the first match fails, try to match
+        * with the table actually asked for.
+        */
+       if (table!=cctab || c==INCAFT || c==DECAFT
+        || (opt = match(tree, efftab, nreg-reg)) == 0)
+               if ((opt=match(tree, table, nreg-reg))==0)
+                       return(-1);
+       string = opt->tabstring;
+       p1 = tree->tr1;
+       p2 = 0;
+       if (opdope[tree->op]&BINARY)
+               p2 = tree->tr2;
+loop:
+       /*
+        * The 0200 bit asks for a tab.
+        */
+       if ((c = *string++) & 0200) {
+               c =& 0177;
+               putchar('\t');
+       }
+       switch (c) {
+
+       case '\0':
+               if (!isfloat(tree))
+                       if (tree->op==DIVIDE || tree->op==ASDIV)
+                               reg--;
+               return(reg);
+
+       /* A1 */
+       case 'A':
+               p = p1;
+               goto adr;
+
+       /* A2 */
+       case 'B':
+               p = p2;
+               goto adr;
+
+       adr:
+               c = 0;
+               if (*string=='\'') {
+                       c = 1;
+                       string++;
+               } else if (*string=='+') {
+                       c = 2;
+                       string++;
+               }
+               pname(p, c);
+               goto loop;
+
+       /* I */
+       case 'M':
+               if ((c = *string)=='\'')
+                       string++;
+               else
+                       c = 0;
+               prins(tree->op, c, instab);
+               goto loop;
+
+       /* B1 */
+       case 'C':
+               if ((opd&LEAF) != 0)
+                       p = tree;
+               else
+                       p = p1;
+               goto pbyte;
+
+       /* BF */
+       case 'P':
+               p = tree;
+               goto pb1;
+
+       /* B2 */
+       case 'D':
+               p = p2;
+       pbyte:
+               if (p->type==CHAR)
+                       putchar('b');
+       pb1:
+               if (isfloat(p))
+                       putchar('f');
+               goto loop;
+
+       /* BE */
+       case 'L':
+               if (p1->type==CHAR || p2->type==CHAR)
+                       putchar('b');
+               p = tree;
+               goto pb1;
+
+       /* F */
+       case 'G':
+               p = p1;
+               flag = 01;
+               goto subtre;
+
+       /* S */
+       case 'K':
+               p = p2;
+               flag = 02;
+               goto subtre;
+
+       /* H */
+       case 'H':
+               p = tree;
+               flag = 04;
+
+       subtre:
+               ctable = regtab;
+               c = *string++ - 'A';
+               if (*string=='!') {
+                       string++;
+                       c =| 020;       /* force right register */
+               }
+               if ((c&02)!=0)
+                       ctable = sptab;
+               if ((c&04)!=0)
+                       ctable = cctab;
+               if ((flag&01) && ctable==regtab && (c&01)==0
+                 && (tree->op==DIVIDE||tree->op==MOD
+                  || tree->op==ASDIV||tree->op==ASMOD))
+                       ctable = cregtab;
+               if ((c&01)!=0) {
+                       p = p->tr1;
+                       if(collcon(p) && ctable!=sptab) {
+                               if (p->op==STAR)
+                                       p = p->tr1;
+                               p = p->tr1;
+                       }
+               }
+               if (table==lsptab && ctable==sptab)
+                       ctable = lsptab;
+               if (c&010)
+                       r = reg1;
+               else
+                       if (opdope[p->op]&LEAF || p->degree < 2)
+                               r = reg;
+                       else
+                               r = areg;
+               rreg = rcexpr(p, ctable, r);
+               if (ctable!=regtab && ctable!=cregtab)
+                       goto loop;
+               if (c&010) {
+                       if (c&020 && rreg!=reg1)
+                               printf("mov%c   r%d,r%d\n",
+                                   isfloat(tree),rreg,reg1);
+                       else
+                               reg1 = rreg;
+               } else if (rreg!=reg)
+                       if ((c&020)==0 && oddreg(tree, 0)==0 && (flag&04 ||
+                             flag&01
+                         && xdcalc(p2, nreg-rreg-1) <= (opt->tabdeg2&077)
+                        ||   flag&02
+                         && xdcalc(p1,nreg-rreg-1) <= (opt->tabdeg1&077))) {
+                               reg = rreg;
+                               reg1 = rreg+1;
+                       } else
+                               printf("mov%c\tr%d,r%d\n",
+                                   isfloat(tree), rreg, reg);
+               goto loop;
+
+       /* R */
+       case 'I':
+               r = reg;
+               if (*string=='-') {
+                       string++;
+                       r--;
+               }
+               goto preg;
+
+       /* R1 */
+       case 'J':
+               r = reg1;
+       preg:
+               if (*string=='+') {
+                       string++;
+                       r++;
+               }
+               if (r>nreg)
+                       error("Register overflow: simplify expression");
+               printf("r%d", r);
+               goto loop;
+
+       case '-':               /* check -(sp) */
+               if (*string=='(') {
+                       nstack++;
+                       if (table!=lsptab)
+                               putchar('-');
+                       goto loop;
+               }
+               break;
+
+       case ')':               /* check (sp)+ */
+               putchar(')');
+               if (*string=='+')
+                       nstack--;
+               goto loop;
+
+       /* #1 */
+       case '#':
+               p = p1->tr1;
+               goto nmbr;
+
+       /* #2 */
+       case '"':
+               p = p2->tr1;
+
+       nmbr:
+               if(collcon(p)) {
+                       if (p->op==STAR) {
+                               printf("*");
+                               p = p->tr1;
+                       }
+                       if ((p = p->tr2)->op == CON) {
+                               if (p->value)
+                                       psoct(p->value);
+                       } else if (p->op==AMPER)
+                               pname(p->tr1, 0);
+               }
+               goto loop;
+
+       case 'T':               /* "tst R" if 1st op not in cctab */
+               if (dcalc(p1, 5)>12 && !match(p1, cctab, 10))
+                       printf("tst     r%d\n", reg);
+               goto loop;
+       case 'V':       /* adc or sbc as required for longs */
+               switch(tree->op) {
+               case PLUS:
+               case ASPLUS:
+               case INCBEF:
+               case INCAFT:
+                       printf("adc");
+                       break;
+
+               case MINUS:
+               case ASMINUS:
+               case NEG:
+               case DECBEF:
+               case DECAFT:
+                       printf("sbc");
+                       break;
+
+               default:
+                       while ((c = *string++)!='\n' && c!='\0');
+                       break;
+               }
+               goto loop;
+       }
+       putchar(c);
+       goto loop;
+}
+
+/*
+ * This routine just calls sreorder (below)
+ * on the subtrees and then on the tree itself.
+ * It returns non-zero if anything changed.
+ */
+reorder(treep, table, reg)
+struct tnode **treep;
+struct table *table;
+{
+       register r, r1;
+       register struct tnode *p;
+
+       p = *treep;
+       if (opdope[p->op]&LEAF)
+               return(0);
+       r1 = 0;
+       while(sreorder(&p->tr1, table, reg))
+               r1++;
+       if (opdope[p->op]&BINARY) 
+               while(sreorder(&p->tr2, table, reg))
+                       r1++;
+       r = 0;
+       while (sreorder(treep, table, reg))
+               r++;
+       *treep = optim(*treep);
+       return(r);
+}
+
+/*
+ * Basically this routine carries out two kinds of optimization.
+ * First, it observes that "x + (reg = y)" where actually
+ * the = is any assignment op is better done as "reg=y; x+reg".
+ * In this case rcexpr is called to do the first part and the
+ * tree is modified so the name of the register
+ * replaces the assignment.
+ * Moreover, expressions like "reg = x+y" are best done as
+ * "reg = x; reg =+ y" (so long as "reg" and "y" are not the same!).
+ */
+sreorder(treep, table, reg)
+struct tnode **treep;
+struct table *table;
+{
+       register struct tnode *p, *p1;
+
+       p = *treep;
+       if (opdope[p->op]&LEAF)
+               return(0);
+       if (p->op==PLUS)
+               if (reorder(&p->tr2, table, reg))
+                       *treep = p = optim(p);
+       p1 = p->tr1;
+       if (p->op==STAR || p->op==PLUS) {
+               if (reorder(&p->tr1, table, reg))
+                       *treep = p = optim(p);
+               p1 = p->tr1;
+       }
+       if (p1->op==NAME) switch(p->op) {
+               case ASLSH:
+               case ASRSH:
+               case ASSIGN:
+                       if (p1->class != REG || isfloat(p->tr2))
+                               return(0);
+                       if (p->op==ASSIGN) switch (p->tr2->op) {
+                       case TIMES:
+                       case DIVIDE:
+                               if (!ispow2(p->tr2))
+                                       break;
+                               p->tr2 = pow2(p->tr2);
+                       case PLUS:
+                       case MINUS:
+                       case AND:
+                       case NAND:
+                       case OR:
+                       case EXOR:
+                       case LSHIFT:
+                       case RSHIFT:
+                               p1 = p->tr2->tr2;
+                               if (xdcalc(p1) > 12
+                                || p1->op==NAME
+                                &&(p1->nloc==p->tr1->nloc
+                                 || p1->regno==p->tr1->nloc))
+                                       return(0);
+                               p1 = p->tr2;
+                               p->tr2 = p1->tr1;
+                               if (p1->tr1->op!=NAME
+                                || p1->tr1->class!=REG
+                                || p1->tr1->nloc!=p->tr1->nloc)
+                                       rcexpr(p, efftab, reg);
+                               p->tr2 = p1->tr2;
+                               p->op = p1->op + ASPLUS - PLUS;
+                               *treep = p;
+                               return(1);
+                       }
+                       goto OK;
+
+               case ASTIMES:
+               case ASDIV:
+                       if (!ispow2(p))
+                               return(0);
+               case ASPLUS:
+               case ASMINUS:
+               case ASSAND:
+               case ASSNAND:
+               case ASOR:
+               case ASXOR:
+               case DECBEF:
+               case INCBEF:
+               OK:
+                       if (table==cctab||table==cregtab)
+                               reg =+ 020;
+                       rcexpr(optim(p), efftab, ~reg);
+                       *treep = p1;
+                       return(1);
+       }
+       return(0);
+}
+
+/*
+ * Delay handles postfix ++ and -- 
+ * It observes that "x + y++" is better
+ * treated as "x + y; y++".
+ * If the operator is ++ or -- itself,
+ * it calls rcexpr to load the operand, letting
+ * the calling instance of rcexpr to do the
+ * ++ using efftab.
+ * Otherwise it uses sdelay to search for inc/dec
+ * among the operands.
+ */
+delay(treep, table, reg)
+struct tnode **treep;
+{
+       register struct tnode *p, *p1;
+       register r;
+
+       p = *treep;
+       if (table!=efftab && (p->op==INCAFT||p->op==DECAFT)
+        && p->tr1->op==NAME) {
+               return(1+rcexpr(p->tr1, table, reg));
+       }
+       p1 = 0;
+       if (opdope[p->op]&BINARY)
+               p1 = sdelay(&p->tr2);
+       if (p1==0)
+               p1 = sdelay(&p->tr1);
+       if (p1) {
+               r = rcexpr(optim(p), table, reg);
+               *treep = p1;
+               return(r+1);
+       }
+       return(0);
+}
+
+sdelay(ap)
+struct tnode **ap;
+{
+       register struct tnode *p, *p1;
+
+       p = *ap;
+       if ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME) {
+               *ap = ncopy(p->tr1);
+               return(p);
+       }
+       if (p->op==STAR || p->op==PLUS)
+               if (p1=sdelay(&p->tr1))
+                       return(p1);
+       if (p->op==PLUS)
+               return(sdelay(&p->tr2));
+       return(0);
+}
+
+/*
+ * Copy a tree node for a register variable.
+ * Used by sdelay because if *reg-- is turned
+ * into *reg; reg-- the *reg will in turn
+ * be changed to some offset class, accidentally
+ * modifying the reg--.
+ */
+ncopy(ap)
+struct tname *ap;
+{
+       register struct tname *p;
+
+       p = ap;
+       if (p->class!=REG)
+               return(p);
+       return(block(3, NAME, p->type, p->elsize, p->tr1,
+           p->offset, p->nloc));
+}
+
+/*
+ * If the tree can be immediately loaded into a register,
+ * produce code to do so and return success.
+ */
+chkleaf(atree, table, reg)
+struct tnode *atree;
+{
+       struct tnode lbuf;
+       register struct tnode *tree;
+
+       tree = atree;
+       if (tree->op!=STAR && dcalc(tree, nreg-reg) > 12)
+               return(-1);
+       lbuf.op = LOAD;
+       lbuf.type = tree->type;
+       lbuf.degree = tree->degree;
+       lbuf.tr1 = tree;
+       return(rcexpr(&lbuf, table, reg));
+}
+
+/*
+ * Compile a function argument.
+ * If the stack is currently empty, put it in (sp)
+ * rather than -(sp); this will save a pop.
+ * Return the number of bytes pushed,
+ * for future popping.
+ */
+comarg(atree, flagp)
+int *flagp;
+{
+       register struct tnode *tree;
+       register retval;
+
+       tree = atree;
+       if (nstack || isfloat(tree) || tree->type==LONG) {
+               rcexpr(tree, sptab, 0);
+               retval = arlength(tree->type);
+       } else {
+               (*flagp)++;
+               rcexpr(tree, lsptab, 0);
+               retval = 0;
+       }
+       return(retval);
+}
diff --git a/usr/source/c/c11.c b/usr/source/c/c11.c
new file mode 100644 (file)
index 0000000..8c88291
--- /dev/null
@@ -0,0 +1,849 @@
+#
+/*
+ *  C compiler
+ */
+
+#include "c1h.c"
+
+max(a, b)
+{
+       if (a>b)
+               return(a);
+       return(b);
+}
+
+degree(at)
+struct tnode *at;
+{
+       register struct tnode *t, *t1;
+
+       if ((t=at)==0 || t->op==0)
+               return(0);
+       if (t->op == CON)
+               return(-3);
+       if (t->op == AMPER)
+               return(-2);
+       if (t->op==ITOL && (t1 = isconstant(t)) && t1->value>= 0)
+               return(-2);
+       if ((opdope[t->op] & LEAF) != 0) {
+               if (t->type==CHAR || t->type==FLOAT)
+                       return(1);
+               return(0);
+       }
+       return(t->degree);
+}
+
+pname(ap, flag)
+struct tnode *ap;
+{
+       register i;
+       register struct tnode *p;
+
+       p = ap;
+loop:
+       switch(p->op) {
+
+       case SFCON:
+       case CON:
+               printf("$");
+               psoct(p->value);
+               return;
+
+       case FCON:
+               printf("L%d", p->value);
+               return;
+
+       case NAME:
+               i = p->offset;
+               if (flag==2)
+                       i =+ 2;
+               if (i) {
+                       psoct(i);
+                       if (p->class!=OFFS)
+                               putchar('+');
+                       if (p->class==REG)
+                               regerr();
+               }
+               switch(p->class) {
+
+               case SOFFS:
+               case XOFFS:
+                       pbase(p);
+
+               case OFFS:
+                       printf("(r%d)", p->regno);
+                       return;
+
+               case EXTERN:
+               case STATIC:
+                       pbase(p);
+                       return;
+
+               case REG:
+                       printf("r%d", p->nloc);
+                       return;
+
+               }
+               error("Compiler error: pname");
+               return;
+
+       case AMPER:
+               putchar('$');
+               p = p->tr1;
+               if (p->op==NAME && p->class==REG)
+                       regerr();
+               goto loop;
+
+       case AUTOI:
+               printf("(r%d)%c", p->nloc, flag==1?0:'+');
+               return;
+
+       case AUTOD:
+               printf("%c(r%d)", flag==1?0:'-', p->nloc);
+               return;
+
+       case STAR:
+               p = p->tr1;
+               putchar('*');
+               goto loop;
+
+       }
+       error("pname called illegally");
+}
+
+regerr()
+{
+       error("Illegal use of register");
+}
+
+pbase(ap)
+struct tnode *ap;
+{
+       register struct tnode *p;
+
+       p = ap;
+       if (p->class==SOFFS || p->class==STATIC)
+               printf("L%d", p->nloc);
+       else
+               printf("_%.8s", &(p->nloc));
+}
+
+xdcalc(ap, nrleft)
+struct tnode *ap;
+{
+       register struct tnode *p;
+       register d;
+
+       p = ap;
+       d = dcalc(p, nrleft);
+       if (d<20 && p->type==CHAR) {
+               if (nrleft>=1)
+                       d = 20;
+               else
+                       d = 24;
+       }
+       return(d);
+}
+
+dcalc(ap, nrleft)
+struct tnode *ap;
+{
+       register struct tnode *p, *p1;
+
+       if ((p=ap)==0)
+               return(0);
+       switch (p->op) {
+
+       case NAME:
+               if (p->class==REG)
+                       return(9);
+
+       case AMPER:
+       case FCON:
+       case AUTOI:
+       case AUTOD:
+               return(12);
+
+       case CON:
+       case SFCON:
+               if (p->value==0)
+                       return(4);
+               if (p->value==1)
+                       return(5);
+               if (p->value > 0)
+                       return(8);
+               return(12);
+
+       case STAR:
+               p1 = p->tr1;
+               if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD)
+                       if (p->type!=LONG)
+                               return(12);
+       }
+       if (p->type==LONG)
+               nrleft--;
+       return(p->degree <= nrleft? 20: 24);
+}
+
+notcompat(ap, ast, op)
+struct tnode *ap;
+{
+       register at, st;
+       register struct tnode *p;
+
+       p = ap;
+       at = p->type;
+       st = ast;
+       if (st==0)              /* word, byte */
+               return(at>CHAR && at<PTR);
+       if (st==1)              /* word */
+               return(at>INT && at<PTR);
+       st =- 2;
+       if ((at&(~(TYPE+XTYPE))) != 0)
+               at = 020;
+       if ((at&(~TYPE)) != 0)
+               at = at&TYPE | 020;
+       if (st==FLOAT && at==DOUBLE)
+               at = FLOAT;
+       if (p->op==NAME && p->class==REG && op==ASSIGN && st==CHAR)
+               return(0);
+       return(st != at);
+}
+
+prins(op, c, itable)
+struct instab *itable;
+{
+       register struct instab *insp;
+       register char *ip;
+
+       for (insp=itable; insp->op != 0; insp++) {
+               if (insp->op == op) {
+                       ip = c? insp->str2: insp->str1;
+                       if (ip==0)
+                               break;
+                       printf("%s", ip);
+                       return;
+               }
+       }
+       error("No match' for op %d", op);
+}
+
+collcon(ap)
+struct tnode *ap;
+{
+       register op;
+       register struct tnode *p;
+
+       p = ap;
+       if (p->op==STAR)
+               p = p->tr1;
+       if (p->op==PLUS) {
+               op = p->tr2->op;
+               if (op==CON || op==AMPER)
+                       return(1);
+       }
+       return(0);
+}
+
+isfloat(at)
+struct tnode *at;
+{
+       register struct tnode *t;
+
+       t = at;
+       if ((opdope[t->op]&RELAT)!=0)
+               t = t->tr1;
+       if (t->type==FLOAT || t->type==DOUBLE) {
+               nfloat = 1;
+               return('f');
+       }
+       return(0);
+}
+
+oddreg(t, areg)
+struct tnode *t;
+{
+       register reg;
+
+       reg = areg;
+       if (!isfloat(t))
+               switch(t->op) {
+               case DIVIDE:
+               case MOD:
+               case ASDIV:
+               case ASMOD:
+                       reg++;
+
+               case TIMES:
+               case ASTIMES:
+                       return(reg|1);
+               }
+       return(reg);
+}
+
+arlength(t)
+{
+       if (t>=PTR)
+               return(2);
+       switch(t) {
+
+       case INT:
+       case CHAR:
+               return(2);
+
+       case LONG:
+               return(4);
+
+       case FLOAT:
+       case DOUBLE:
+               return(8);
+       }
+       return(1024);
+}
+
+/*
+ * Strings for switch code.
+ */
+
+char   dirsw[] {"\
+cmp    r0,$%o\n\
+jhi    L%d\n\
+asl    r0\n\
+jmp    *L%d(r0)\n\
+.data\n\
+L%d:\
+" };
+
+char   simpsw[] {"\
+mov    $L%d,r1\n\
+mov    r0,L%d\n\
+L%d:cmp        r0,(r1)+\n\
+jne    L%d\n\
+jmp    *L%d-L%d(r1)\n\
+.data\n\
+L%d:\
+"};
+
+char   hashsw[] {"\
+mov    r0,r1\n\
+clr    r0\n\
+div    $%o,r0\n\
+asl    r1\n\
+add    $L%d,r1\n\
+mov    r0,*(r1)+\n\
+mov    (r1)+,r1\n\
+L%d:cmp        r0,-(r1)\n\
+jne    L%d\n\
+jmp    *L%d-L%d(r1)\n\
+.data\n\
+L%d:\
+"};
+
+pswitch(afp, alp, deflab)
+struct swtab *afp, *alp;
+{
+       int tlab, ncase, i, j, tabs, worst, best, range;
+       register struct swtab *swp, *fp, *lp;
+       int poctab[swsiz];
+
+       fp = afp;
+       lp = alp;
+       if (fp==lp) {
+               printf("jbr     L%d\n", deflab);
+               return;
+       }
+       tlab = isn++;
+       if (sort(fp, lp))
+               return;
+       ncase = lp-fp;
+       lp--;
+       range = lp->swval - fp->swval;
+       /* direct switch */
+       if (range>0 && range <= 3*ncase) {
+               if (fp->swval)
+                       printf("sub     $%o,r0\n", fp->swval);
+               printf(dirsw, range, deflab, isn, isn);
+               isn++;
+               for (i=fp->swval; i<=lp->swval; i++) {
+                       if (i==fp->swval) {
+                               printf("L%d\n", fp->swlab);
+                               fp++;
+                       } else
+                               printf("L%d\n", deflab);
+               }
+               goto esw;
+       }
+       /* simple switch */
+       if (ncase<8) {
+               i = isn++;
+               j = isn++;
+               printf(simpsw, i, j, isn, isn, j, i, i);
+               isn++;
+               for (; fp<=lp; fp++)
+                       printf("%o\n", fp->swval);
+               printf("L%d:..\n", j);
+               for (fp = afp; fp<=lp; fp++)
+                       printf("L%d\n", fp->swlab);
+               printf("L%d\n", deflab);
+               goto esw;
+       }
+       /* hash switch */
+       best = 077777;
+       for (i=ncase/4; i<=ncase/2; i++) {
+               for (j=0; j<i; j++)
+                       poctab[j] = 0;
+               for (swp=fp; swp<=lp; swp++)
+                       poctab[lrem(0, swp->swval, i)]++;
+               worst = 0;
+               for (j=0; j<i; j++)
+                       if (poctab[j]>worst)
+                               worst = poctab[j];
+               if (i*worst < best) {
+                       tabs = i;
+                       best = i*worst;
+               }
+       }
+       i = isn++;
+       printf(hashsw, tabs, isn, i, i, isn+tabs+1, isn+1, isn);
+       isn++;
+       for (i=0; i<=tabs; i++)
+               printf("L%d\n", isn+i);
+       for (i=0; i<tabs; i++) {
+               printf("L%d:..\n", isn++);
+               for (swp=fp; swp<=lp; swp++)
+                       if (lrem(0, swp->swval, tabs) == i)
+                               printf("%o\n", ldiv(0, swp->swval, tabs));
+       }
+       printf("L%d:", isn++);
+       for (i=0; i<tabs; i++) {
+               printf("L%d\n", deflab);
+               for (swp=fp; swp<=lp; swp++)
+                       if (lrem(0, swp->swval, tabs) == i)
+                               printf("L%d\n", swp->swlab);
+       }
+esw:
+       printf(".text\n");
+}
+
+sort(afp, alp)
+struct swtab *afp, *alp;
+{
+       register struct swtab *cp, *fp, *lp;
+       int intch, t;
+
+       fp = afp;
+       lp = alp;
+       while (fp < --lp) {
+               intch = 0;
+               for (cp=fp; cp<lp; cp++) {
+                       if (cp->swval == cp[1].swval) {
+                               error("Duplicate case (%d)", cp->swval);
+                               return(1);
+                       }
+                       if (cp->swval > cp[1].swval) {
+                               intch++;
+                               t = cp->swval;
+                               cp->swval = cp[1].swval;
+                               cp[1].swval = t;
+                               t = cp->swlab;
+                               cp->swlab = cp[1].swlab;
+                               cp[1].swlab = t;
+                       }
+               }
+               if (intch==0)
+                       break;
+       }
+       return(0);
+}
+
+ispow2(atree)
+{
+       register int d;
+       register struct tnode *tree;
+
+       tree = atree;
+       if (!isfloat(tree) && tree->tr2->op==CON) {
+               d = tree->tr2->value;
+               if (d>1 && (d&(d-1))==0)
+                       return(d);
+       }
+       return(0);
+}
+
+pow2(atree)
+struct tnode *atree;
+{
+       register int d, i;
+       register struct tnode *tree;
+
+       tree = atree;
+       if (d = ispow2(tree)) {
+               for (i=0; (d=>>1)!=0; i++);
+               tree->tr2->value = i;
+               d = tree->op;
+               tree->op = d==TIMES? LSHIFT:
+                         (d==DIVIDE? RSHIFT:
+                         (d==ASTIMES? ASLSH: ASRSH));
+               tree = optim(tree);
+       }
+       return(tree);
+}
+
+cbranch(atree, albl, cond, areg)
+struct tnode *atree;
+{
+       int l1, op;
+       register lbl, reg;
+       register struct tnode *tree;
+
+       lbl = albl;
+       reg = areg;
+       if ((tree=atree)==0)
+               return;
+       switch(tree->op) {
+
+       case LOGAND:
+               if (cond) {
+                       cbranch(tree->tr1, l1=isn++, 0, reg);
+                       cbranch(tree->tr2, lbl, 1, reg);
+                       label(l1);
+               } else {
+                       cbranch(tree->tr1, lbl, 0, reg);
+                       cbranch(tree->tr2, lbl, 0, reg);
+               }
+               return;
+
+       case LOGOR:
+               if (cond) {
+                       cbranch(tree->tr1, lbl, 1, reg);
+                       cbranch(tree->tr2, lbl, 1, reg);
+               } else {
+                       cbranch(tree->tr1, l1=isn++, 1, reg);
+                       cbranch(tree->tr2, lbl, 0, reg);
+                       label(l1);
+               }
+               return;
+
+       case EXCLA:
+               cbranch(tree->tr1, lbl, !cond, reg);
+               return;
+
+       case COMMA:
+               rcexpr(tree->tr1, efftab, reg);
+               tree = tree->tr2;
+               break;
+       }
+       op = tree->op;
+       if (tree->type==LONG || opdope[op]&RELAT&&tree->tr1->type==LONG) {
+               if (tree->type!=LONG) {
+                       tree->op = MINUS;
+                       tree->type = LONG;
+                       tree = optim(tree);
+               } else
+                       op = NEQUAL;
+               rcexpr(tree, regtab, 0);
+               printf("ashc    $0,r0\n");
+               branch(lbl, op, !cond);
+               return;
+       }
+       rcexpr(tree, cctab, reg);
+       op = tree->op;
+       if ((opdope[op]&RELAT)==0)
+               op = NEQUAL;
+       else {
+               l1 = tree->tr2->op;
+               if ((l1==CON || l1==SFCON) && tree->tr2->value==0)
+                       op =+ 200;              /* special for ptr tests */
+               else
+                       op = maprel[op-EQUAL];
+       }
+       if (isfloat(tree))
+               printf("cfcc\n");
+       branch(lbl, op, !cond);
+}
+
+branch(lbl, aop, c)
+{
+       register op;
+
+       if(op=aop)
+               prins(op, c, branchtab);
+       else
+               printf("jbr");
+       printf("\tL%d\n", lbl);
+}
+
+label(l)
+{
+       printf("L%d:", l);
+}
+
+popstk(a)
+{
+       switch(a) {
+
+       case 0:
+               return;
+
+       case 2:
+               printf("tst     (sp)+\n");
+               return;
+
+       case 4:
+               printf("cmp     (sp)+,(sp)+\n");
+               return;
+       }
+       printf("add     $%o,sp\n", a);
+}
+
+error(s, p1, p2, p3, p4, p5, p6)
+{
+       register f;
+       extern fout;
+
+       nerror++;
+       flush();
+       f = fout;
+       fout = 1;
+       printf("%d: ", line);
+       printf(s, p1, p2, p3, p4, p5, p6);
+       putchar('\n');
+       flush();
+       fout = f;
+}
+
+psoct(an)
+{
+       register int n, sign;
+
+       sign = 0;
+       if ((n = an) < 0) {
+               n = -n;
+               sign = '-';
+       }
+       printf("%c%o", sign, n);
+}
+
+/*
+ * Read in an intermediate file.
+ */
+getree()
+{
+       struct tnode *expstack[20];
+       register struct tnode **sp;
+       register t, op;
+       static char s[9];
+       struct swtab *swp;
+
+       spacep = treespace;
+       sp = expstack;
+       for (;;) {
+               if (sp >= &expstack[20])
+                       error("Stack botch");
+               op = getw(ascbuf);
+               if ((op&0177400) != 0177000) {
+                       error("Intermediate file error");
+                       exit(1);
+               }
+               switch(op =& 0377) {
+
+       case EOF:
+               return;
+
+       case BDATA:
+               printf(".byte ");
+               seq(',');
+               break;
+
+       case WDATA:
+               seq(';');
+               break;
+
+       case PROG:
+               printf(".text\n");
+               break;
+
+       case DATA:
+               printf(".data\n");
+               break;
+
+       case BSS:
+               printf(".bss\n");
+               break;
+
+       case SYMDEF:
+               printf(".globl  _%s\n", outname(s));
+               break;
+
+       case RETRN:
+               printf("jmp     cret\n");
+               break;
+
+       case CSPACE:
+               t = outname(s);
+               printf(".comm   _%s,%o\n", t, getw(ascbuf));
+               break;
+
+       case SSPACE:
+               printf(".=.+%o\n", getw(ascbuf));
+               break;
+
+       case EVEN:
+               printf(".even\n");
+               break;
+
+       case SAVE:
+               printf("jsr     r5,csv\n");
+               t = getw(ascbuf)-6;
+               if (t==2)
+                       printf("tst     -(sp)\n");
+               else if (t > 2)
+                       printf("sub     $%o,sp\n", t);
+               break;
+
+       case PROFIL:
+               t = getw(ascbuf);
+               printf("mov     $L%d,r0\njsr    pc,mcount\n", t);
+               printf(".bss\nL%d:.=.+2\n.text\n", t);
+               break;
+
+       case SNAME:
+               t = outname(s);
+               printf("~%s=L%d\n", t, getw(ascbuf));
+               break;
+
+       case ANAME:
+               t = outname(s);
+               printf("~%s=%o\n", t, getw(ascbuf));
+               break;
+
+       case RNAME:
+               t = outname(s);
+               printf("~%s=r%d\n", t, getw(ascbuf));
+               break;
+
+       case SWIT:
+               t = getw(ascbuf);
+               line = getw(ascbuf);
+               swp = treespace;
+               while (swp->swlab = getw(ascbuf)) {
+                       swp->swval = getw(ascbuf);
+                       swp++;
+               }
+               pswitch(treespace, swp, t);
+               break;
+
+       case EXPR:
+               line = getw(ascbuf);
+               if (sp != &expstack[1]) {
+                       error("Expression input botch\n");
+                       exit(1);
+               }
+               nstack = 0;
+               rcexpr(optim(*--sp), efftab, 0);
+               spacep = treespace;
+               break;
+
+       case NAME:
+               t = getw(ascbuf);
+               if (t==EXTERN) {
+                       t = getw(ascbuf);
+                       *sp = block(6, NAME, t, 0, EXTERN, 0, 0,0,0,0);
+                       outname(&(*sp)->nloc);
+                       sp++;
+                       break;
+               }
+               *sp = block(3, NAME, 0, 0, t, 0, 0);
+               (*sp)->type = getw(ascbuf);
+               (*sp)->nloc = getw(ascbuf);
+               sp++;
+               break;
+
+       case CON:
+       case SFCON:
+       case FCON:
+               t = getw(ascbuf);
+               *sp++ = block(1, op, t, 0, getw(ascbuf));
+               break;
+
+       case FSEL:
+               t = getw(ascbuf);
+               sp[-1] = block(2, op, t, 0, sp[-1], getw(ascbuf));
+               break;
+
+       case NULL:
+               *sp++ = block(0, 0, 0, 0);
+               break;
+
+       case CBRANCH:
+               t = getw(ascbuf);
+               sp[-1] = block(1, CBRANCH, sp[-1], t, getw(ascbuf));
+               break;
+
+       case LABEL:
+               label(getw(ascbuf));
+               break;
+
+       case NLABEL:
+               printf("_%s:\n", outname(s));
+               break;
+
+       case RLABEL:
+               t = outname(s);
+               printf("_%s:\n~~%s:\n", t, t);
+               break;
+
+       case BRANCH:
+               branch(getw(ascbuf), 0);
+               break;
+
+       case SETREG:
+               nreg = getw(ascbuf)-1;
+               break;
+
+       default:
+               if (opdope[op]&BINARY) {
+                       if (sp < &expstack[1]) {
+                               error("Binary expression botch");
+                               exit(1);
+                       }
+                       t = *--sp;
+                       *sp++ = block(2, op, getw(ascbuf), 0, *--sp, t);
+               } else {
+                       sp[-1] = block(1, op, getw(ascbuf), 0, sp[-1]);
+               }
+               break;
+       }
+       }
+}
+
+outname(s)
+{
+       register char *p, c;
+       register n;
+
+       p = s;
+       n = 0;
+       while (c = getc(ascbuf)) {
+               *p++ = c;
+               n++;
+       }
+       while (n++ < 8)
+               *p++ = 0;
+       return(s);
+}
+
+seq(c)
+{
+       register o;
+
+       if (getw(ascbuf) == 0)
+               return;
+       for (;;) {
+               printf("%o", getw(ascbuf));
+               if ((o = getw(ascbuf)) != 1)
+                       break;
+               printf("%c", c);
+       }
+       printf("\n");
+}
diff --git a/usr/source/c/c12.c b/usr/source/c/c12.c
new file mode 100644 (file)
index 0000000..69961f2
--- /dev/null
@@ -0,0 +1,621 @@
+#
+/*
+ *             C compiler part 2 -- expression optimizer
+ *
+ */
+
+#include "c1h.c"
+
+optim(atree)
+struct tnode *atree;
+{
+       register op, dope;
+       int d1, d2;
+       struct tnode *t;
+       register struct tnode *tree;
+
+       if ((tree=atree)==0)
+               return(0);
+       if ((op = tree->op)==0)
+               return(tree);
+       if (op==NAME && tree->class==AUTO) {
+               tree->class = OFFS;
+               tree->regno = 5;
+               tree->offset = tree->nloc;
+       }
+       dope = opdope[op];
+       if ((dope&LEAF) != 0)
+               return(tree);
+       if ((dope&BINARY) == 0)
+               return(unoptim(tree));
+       /* is known to be binary */
+       if (tree->type==CHAR)
+               tree->type = INT;
+       if ((dope&COMMUTE)!=0) {
+       acomm:  d1 = tree->type;
+               tree = acommute(tree);
+               tree->type = d1;
+               /*
+                * PDP-11 special:
+                * replace a&b by a NAND ~ b.
+                * This will be undone when in
+                * truth-value context.
+                */
+               if (tree->op!=AND)
+                       return(tree);
+               tree->op = NAND;
+               tree->tr2 = block(1, COMPL, tree->tr2->type, 0, tree->tr2);
+       }
+    again:
+       tree->tr1 = optim(tree->tr1);
+       tree->tr2 = optim(tree->tr2);
+       if ((dope&RELAT) != 0) {
+               if ((d1=degree(tree->tr1)) < (d2=degree(tree->tr2))
+                || d1==d2 && tree->tr1->op==NAME && tree->tr2->op!=NAME) {
+                       t = tree->tr1;
+                       tree->tr1 = tree->tr2;
+                       tree->tr2 = t;
+                       tree->op = maprel[op-EQUAL];
+               }
+               if (tree->tr1->type==CHAR && tree->tr2->op==CON
+                && (dcalc(tree->tr1) <= 12 || tree->tr1->op==STAR)
+                && tree->tr2->value <= 127 && tree->tr2->value >= 0)
+                       tree->tr2->type = CHAR;
+       }
+       d1 = max(degree(tree->tr1), islong(tree->type));
+       d2 = max(degree(tree->tr2), 0);
+       if (tree->tr1->type==LONG && dope&RELAT)
+               d1 = 10;
+       switch (op) {
+
+       case LTIMES:
+       case LDIV:
+       case LMOD:
+       case LASTIMES:
+       case LASDIV:
+       case LASMOD:
+               tree->degree = 10;
+               break;
+
+       /*
+        * PDP-11 special:
+        * generate new =&~ operator out of =&
+        * by complementing the RHS.
+        */
+       case ASSAND:
+               op = ASSNAND;
+               tree->op = op;
+               tree->tr2 = block(2, COMPL, tree->tr2->type, 0, tree->tr2);
+               goto again;
+
+       case NAND:
+               if (isconstant(tree->tr2) && tree->tr2->value==0)
+                       return(tree->tr1);
+               goto def;
+
+       case CALL:
+               tree->degree = 10;
+               break;
+
+       case QUEST:
+       case COLON:
+               tree->degree = max(d1, d2);
+               break;
+
+       case MINUS:
+               if (t = isconstant(tree->tr2)) {
+                       tree->op = PLUS;
+                       if (t->type==DOUBLE)
+                               /* PDP-11 FP representation */
+                               t->value =^ 0100000;
+                       else
+                               t->value = -t->value;
+                       goto acomm;
+               }
+               goto def;
+
+       case DIVIDE:
+       case ASDIV:
+       case ASTIMES:
+               if (tree->tr2->op==CON && tree->tr2->value==1)
+                       return(tree->tr1);
+               if (ispow2(tree) == 0) {
+
+               case MOD:
+               case ASMOD:
+                       d1 =+ 2;
+                       d2 =+ 2;
+               }
+               if (tree->type==LONG)
+                       return(hardlongs(tree));
+               goto constant;
+
+       case LSHIFT:
+       case RSHIFT:
+       case ASRSH:
+       case ASLSH:
+               if (tree->tr2->op==CON && tree->tr2->value==0)
+                       return(tree->tr1);
+               /*
+                * PDP-11 special: turn right shifts into negative
+                * left shifts
+                */
+               if (op==LSHIFT||op==ASLSH)
+                       goto constant;
+               if (tree->tr2->op==CON && tree->tr2->value==1)
+                       goto constant;
+               op =+ (LSHIFT-RSHIFT);
+               tree->op = op;
+               tree->tr2 = block(1, NEG, tree->type, 0, tree->tr2);
+               goto again;
+
+       constant:
+               if (tree->tr1->op==CON && tree->tr2->op==CON) {
+                       const(op, &tree->tr1->value, tree->tr2->value);
+                       return(tree->tr1);
+               }
+
+
+       def:
+       default:
+               tree->degree = d1==d2? d1+islong(tree->type): max(d1, d2);
+               break;
+       }
+       return(tree);
+}
+
+unoptim(atree)
+struct tnode *atree;
+{
+       register struct tnode *subtre, *tree;
+       register int *p;
+       double static fv;
+       struct { int integer; };
+
+       if ((tree=atree)==0)
+               return(0);
+       if (tree->op==CBRANCH) {
+               tree->btree = optim(tree->btree);
+               return(tree);
+       }
+       subtre = tree->tr1 = optim(tree->tr1);
+       switch (tree->op) {
+
+       case FSEL:
+               tree->tr1 = block(2, RSHIFT, INT, 0, subtre,
+                   block(1, CON, INT, 0, tree->bitoffs));
+               tree->op = AND;
+               tree->type = INT;
+               tree->tr2 = block(1, CON, INT, 0, (1<<tree->flen)-1);
+               return(optim(tree));
+
+       case AMPER:
+               if (subtre->op==STAR)
+                       return(subtre->tr1);
+               if (subtre->op==NAME && subtre->class == OFFS) {
+                       p = block(2, PLUS, tree->type, 1, subtre, tree);
+                       subtre->type = tree->type;
+                       tree->op = CON;
+                       tree->type = INT;
+                       tree->degree = 0;
+                       tree->value = subtre->offset;
+                       subtre->class = REG;
+                       subtre->nloc = subtre->regno;
+                       subtre->offset = 0;
+                       return(p);
+               }
+               break;
+
+       case STAR:
+               if (subtre->op==AMPER)
+                       return(subtre->tr1);
+               if (subtre->op==NAME && subtre->class==REG) {
+                       subtre->type = tree->type;
+                       subtre->class = OFFS;
+                       subtre->regno = subtre->nloc;
+                       return(subtre);
+               }
+               p = subtre->tr1;
+               if ((subtre->op==INCAFT||subtre->op==DECBEF)&&tree->type!=LONG
+                && p->op==NAME && p->class==REG && p->type==subtre->type) {
+                       p->type = tree->type;
+                       p->op = subtre->op==INCAFT? AUTOI: AUTOD;
+                       return(p);
+               }
+               if (subtre->op==PLUS && p->op==NAME && p->class==REG) {
+                       if (subtre->tr2->op==CON) {
+                               p->offset =+ subtre->tr2->value;
+                               p->class = OFFS;
+                               p->type = tree->type;
+                               p->regno = p->nloc;
+                               return(p);
+                       }
+                       if (subtre->tr2->op==AMPER) {
+                               subtre = subtre->tr2->tr1;
+                               subtre->class =+ XOFFS-EXTERN;
+                               subtre->regno = p->nloc;
+                               subtre->type = tree->type;
+                               return(subtre);
+                       }
+               }
+               break;
+       case EXCLA:
+               if ((opdope[subtre->op]&RELAT)==0)
+                       break;
+               tree = subtre;
+               tree->op = notrel[tree->op-EQUAL];
+               break;
+
+       case NEG:
+       case COMPL:
+               if (tree->type==CHAR)
+                       tree->type = INT;
+               if (tree->op == subtre->op)
+                       return(subtre->tr1);
+               if (subtre->op==ITOL) {
+                       subtre->op = tree->op;
+                       subtre->type = INT;
+                       tree->op = ITOL;
+               }
+       }
+       if (subtre->op == CON) switch(tree->op) {
+
+       case NEG:
+               subtre->value = -subtre->value;
+               return(subtre);
+
+       case COMPL:
+               subtre->value = ~subtre->value;
+               return(subtre);
+
+       case ITOF:
+               fv = subtre->value;
+               p = &fv;
+               p++;
+               if (*p++==0 && *p++==0 && *p++==0) {
+                       subtre->type = DOUBLE;
+                       subtre->value = fv.integer;
+                       subtre->op = SFCON;
+                       return(subtre);
+               }
+               break;
+       }
+       tree->degree = max(islong(tree->type), degree(subtre));
+       return(tree);
+}
+
+struct acl {
+       int nextl;
+       int nextn;
+       struct tnode *nlist[20];
+       struct tnode *llist[21];
+};
+
+acommute(atree)
+{
+       struct acl acl;
+       int d, i, op, flt;
+       register struct tnode *t1, **t2, *tree;
+       struct tnode *t;
+
+       acl.nextl = 0;
+       acl.nextn = 0;
+       tree = atree;
+       op = tree->op;
+       flt = isfloat(tree);
+       insert(op, tree, &acl);
+       acl.nextl--;
+       t2 = &acl.llist[acl.nextl];
+       if (!flt) {
+               /* put constants together */
+               for (i=acl.nextl;i>0&&t2[0]->op==CON&&t2[-1]->op==CON;i--) {
+                       acl.nextl--;
+                       t2--;
+                       const(op, &t2[0]->value, t2[1]->value);
+               }
+       }
+       if (op==PLUS || op==OR) {
+               /* toss out "+0" */
+               if (acl.nextl>0 && (t1 = isconstant(*t2)) && t1->value==0) {
+                       acl.nextl--;
+                       t2--;
+               }
+               if (acl.nextl <= 0)
+                       return(*t2);
+               /* subsume constant in "&x+c" */
+               if (op==PLUS && t2[0]->op==CON && t2[-1]->op==AMPER) {
+                       t2--;
+                       t2[0]->tr1->offset =+ t2[1]->value;
+                       acl.nextl--;
+               }
+       } else if (op==TIMES || op==AND) {
+               t1 = acl.llist[acl.nextl];
+               if (t1->op==CON) {
+                       if (t1->value==0)
+                               return(t1);
+                       if (op==TIMES && t1->value==1 && acl.nextl>0)
+                               if (--acl.nextl <= 0)
+                                       return(acl.llist[0]);
+               }
+       }
+       if (op==PLUS && !flt)
+               distrib(&acl);
+       tree = *(t2 = &acl.llist[0]);
+       d = max(degree(tree), islong(tree->type));
+       if (op==TIMES && !flt)
+               d++;
+       for (i=0; i<acl.nextl; i++) {
+               t1 = acl.nlist[i];
+               t1->tr2 = t = *++t2;
+               t1->degree = d = d==degree(t)? d+islong(t1->type): max(d, degree(t));
+               t1->tr1 = tree;
+               tree = t1;
+               if (tree->type==LONG) {
+                       if (tree->op==TIMES)
+                               tree = hardlongs(tree);
+                       else if (tree->op==PLUS && (t = isconstant(tree->tr1))
+                              && t->value < 0) {
+                               tree->op = MINUS;
+                               t->value = - t->value;
+                               t = tree->tr1;
+                               tree->tr1 = tree->tr2;
+                               tree->tr2 = t;
+                       }
+               }
+       }
+       if (tree->op==TIMES && ispow2(tree))
+               tree->degree = max(degree(tree->tr1), islong(tree->type));
+       return(tree);
+}
+
+distrib(list)
+struct acl *list;
+{
+/*
+ * Find a list member of the form c1c2*x such
+ * that c1c2 divides no other such constant, is divided by
+ * at least one other (say in the form c1*y), and which has
+ * fewest divisors. Reduce this pair to c1*(y+c2*x)
+ * and iterate until no reductions occur.
+ */
+       register struct tnode **p1, **p2;
+       struct tnode *t;
+       int ndmaj, ndmin;
+       struct tnode **dividend, **divisor;
+       struct tnode **maxnod, **mindiv;
+
+    loop:
+       maxnod = &list->llist[list->nextl];
+       ndmaj = 1000;
+       dividend = 0;
+       for (p1 = list->llist; p1 <= maxnod; p1++) {
+               if ((*p1)->op!=TIMES || (*p1)->tr2->op!=CON)
+                       continue;
+               ndmin = 0;
+               for (p2 = list->llist; p2 <= maxnod; p2++) {
+                       if (p1==p2 || (*p2)->op!=TIMES || (*p2)->tr2->op!=CON)
+                               continue;
+                       if ((*p1)->tr2->value == (*p2)->tr2->value) {
+                               (*p2)->tr2 = (*p1)->tr1;
+                               (*p2)->op = PLUS;
+                               (*p1)->tr1 = (*p2);
+                               *p1 = optim(*p1);
+                               squash(p2, maxnod);
+                               list->nextl--;
+                               goto loop;
+                       }
+                       if (((*p2)->tr2->value % (*p1)->tr2->value) == 0)
+                               goto contmaj;
+                       if (((*p1)->tr2->value % (*p2)->tr2->value) == 0) {
+                               ndmin++;
+                               mindiv = p2;
+                       }
+               }
+               if (ndmin > 0 && ndmin < ndmaj) {
+                       ndmaj = ndmin;
+                       dividend = p1;
+                       divisor = mindiv;
+               }
+    contmaj:;
+       }
+       if (dividend==0)
+               return;
+       t = list->nlist[--list->nextn];
+       p1 = dividend;
+       p2 = divisor;
+       t->op = PLUS;
+       t->type = (*p1)->type;
+       t->tr1 = (*p1);
+       t->tr2 = (*p2)->tr1;
+       (*p1)->tr2->value =/ (*p2)->tr2->value;
+       (*p2)->tr1 = t;
+       t = optim(*p2);
+       if (p1 < p2) {
+               *p1 = t;
+               squash(p2, maxnod);
+       } else {
+               *p2 = t;
+               squash(p1, maxnod);
+       }
+       list->nextl--;
+       goto loop;
+}
+
+squash(p, maxp)
+struct tnode **p, **maxp;
+{
+       register struct tnode **np;
+
+       for (np = p; np < maxp; np++)
+               *np = *(np+1);
+}
+
+const(op, vp, av)
+int *vp;
+{
+       register int v;
+
+       v = av;
+       switch (op) {
+
+       case PLUS:
+               *vp =+ v;
+               return;
+
+       case TIMES:
+               *vp =* v;
+               return;
+
+       case AND:
+               *vp =& v;
+               return;
+
+       case OR:
+               *vp =| v;
+               return;
+
+       case EXOR:
+               *vp =^ v;
+               return;
+
+       case DIVIDE:
+       case MOD:
+               if (v==0)
+                       error("Divide check");
+               else
+                       if (op==DIVIDE)
+                               *vp =/ v;
+                       else
+                               *vp =% v;
+               return;
+
+       case RSHIFT:
+               *vp =>> v;
+               return;
+
+       case LSHIFT:
+               *vp =<< v;
+               return;
+
+       case NAND:
+               *vp =& ~ v;
+               return;
+       }
+       error("C error: const");
+}
+
+insert(op, atree, alist)
+struct acl *alist;
+{
+       register d;
+       register struct acl *list;
+       register struct tnode *tree;
+       int d1, i;
+       struct tnode *t;
+
+       tree = atree;
+       list = alist;
+       if (tree->op == op) {
+       ins:    list->nlist[list->nextn++] = tree;
+               insert(op, tree->tr1, list);
+               insert(op, tree->tr2, list);
+               return;
+       }
+       tree = optim(tree);
+       if (tree->op == op)
+               goto ins;
+       if (!isfloat(tree)) {
+               /* c1*(x+c2) -> c1*x+c1*c2 */
+               if ((tree->op==TIMES||tree->op==LSHIFT)
+                 && tree->tr2->op==CON && tree->tr2->value>0
+                 && tree->tr1->op==PLUS && tree->tr1->tr2->op==CON) {
+                       d = tree->tr2->value;
+                       if (tree->op==TIMES)
+                               tree->tr2->value =* tree->tr1->tr2->value;
+                       else
+                               tree->tr2->value = tree->tr1->tr2->value << d;
+                       tree->tr1->tr2->value = d;
+                       tree->tr1->op = tree->op;
+                       tree->op = PLUS;
+                       if (op==PLUS)
+                               goto ins;
+               }
+       }
+       d = degree(tree);
+       for (i=0; i<list->nextl; i++) {
+               if ((d1=degree(list->llist[i]))<d) {
+                       t = list->llist[i];
+                       list->llist[i] = tree;
+                       tree = t;
+                       d = d1;
+               }
+       }
+       list->llist[list->nextl++] = tree;
+}
+
+block(an, args)
+{
+       register int *p;
+       int *oldp;
+       register *argp, n;
+
+       oldp = p = spacep;
+       n = an+3;
+       argp = &args;
+       do
+               *p++ = *argp++;
+       while (--n);
+       if (p >= &treespace[ossiz]) {
+               error("Exp. ov. pass 2");
+               exit(1);
+       }
+       spacep = p;
+       return(oldp);
+}
+
+islong(t)
+{
+       if (t==LONG)
+               return(2);
+       return(1);
+}
+
+isconstant(at)
+struct tnode *at;
+{
+       register struct tnode *t;
+
+       t = at;
+       if (t->op==CON || t->op==SFCON)
+               return(t);
+       if (t->op==ITOL && t->tr1->op==CON)
+               return(t->tr1);
+       return(0);
+}
+
+hardlongs(at)
+struct tnode *at;
+{
+       register struct tnode *t;
+
+       t = at;
+       switch(t->op) {
+
+       case TIMES:
+       case DIVIDE:
+       case MOD:
+               t->op =+ LTIMES-TIMES;
+               break;
+
+       case ASTIMES:
+       case ASDIV:
+       case ASMOD:
+               t->op =+ LASTIMES-ASTIMES;
+               t->tr1 = block(1, AMPER, LONG+PTR, 0, t->tr1);
+               break;
+
+       default:
+               return(t);
+       }
+       return(optim(t));
+}
diff --git a/usr/source/c/c13.c b/usr/source/c/c13.c
new file mode 100644 (file)
index 0000000..49cf6a6
--- /dev/null
@@ -0,0 +1,227 @@
+int opdope[] {
+       000000, /* EOF */
+       000000, /* ; */
+       000000, /* { */
+       000000, /* } */
+       036000, /* [ */
+       002000, /* ] */
+       036000, /* ( */
+       002000, /* ) */
+       014201, /* : */
+       007001, /* , */
+       000000, /* field selection */
+       000000, /* 11 */
+       000000, /* 12 */
+       000000, /* 13 */
+       000000, /* 14 */
+       000000, /* 15 */
+       000000, /* 16 */
+       000000, /* 17 */
+       000000, /* 18 */
+       000000, /* 19 */
+       000400, /* name */
+       000400, /* short constant */
+       000400, /* string */
+       000400, /* float */
+       000400, /* double */
+       000000, /* 25 */
+       000000, /* 26 */
+       000400, /* autoi, *r++ */
+       000400, /* autod, *--r */
+       000000, /* 29 */
+       034203, /* ++pre */
+       034203, /* --pre */
+       034203, /* ++post */
+       034203, /* --post */
+       034220, /* !un */
+       034202, /* &un */
+       034220, /* *un */
+       034200, /* -un */
+       034220, /* ~un */
+       036001, /* . (structure reference) */
+       030101, /* + */
+       030001, /* - */
+       032101, /* * */
+       032001, /* / */
+       032001, /* % */
+       026061, /* >> */
+       026061, /* << */
+       020161, /* & */
+       016161, /* | */
+       016161, /* ^ */
+       036001, /* -> */
+       001000, /* int -> double */
+       001000, /* double -> int */
+       000001, /* && */
+       000001, /* || */
+       030001, /* &~ */
+       001000, /* double -> long */
+       001000, /* long -> double */
+       001000, /* integer -> long */
+       001000, /* long -> integer */
+       022005, /* == */
+       022005, /* != */
+       024005, /* <= */
+       024005, /* < */
+       024005, /* >= */
+       024005, /* > */
+       024005, /* <p */
+       024005, /* <=p */
+       024005, /* >p */
+       024005, /* >=p */
+       012213, /* =+ */
+       012213, /* =- */
+       012213, /* =* */
+       012213, /* =/ */
+       012213, /* =% */
+       012253, /* =>> */
+       012253, /* =<< */
+       012253, /* =& */
+       012253, /* =| */
+       012253, /* =^ */
+       012213, /* = */
+       030001, /* & for tests */
+       032101, /*  * (long) */
+       032001, /*  / (long) */
+       032001, /* % (long) */
+       012253, /* =& ~ */
+       012213, /* =* (long) */
+       012213, /* / (long) */
+       012213, /* % (long) */
+       000000, /* 89 */
+       014201, /* ? */
+       026061, /* long << */
+       012253, /* long =<< */
+       000000, /* 93 */
+       000000, /* 94 */
+       000000, /* 95 */
+       000000, /* 96 */
+       000000, /* 97 */
+       000000, /* 98 */
+       000000, /* 99 */
+       036001, /* call */
+       036000, /* mcall */
+       000000, /* goto */
+       000000, /* jump cond */
+       000000, /* branch cond */
+       000400, /* set nregs */
+       000000, /* 106 */
+       000000, /* 107 */
+       000000, /* 108 */
+       000000, /* 109 */
+       000000  /* force r0 */
+};
+
+char   *opntab[] {
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       ":",
+       ",",
+       "field select",
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       0,
+       "name",
+       "short constant",
+       "string",
+       "float",
+       "double",
+       0,
+       0,
+       "*r++",
+       "*--r",
+       0,
+       "++pre",
+       "--pre",
+       "++post",
+       "--post",
+       "!un",
+       "&",
+       "*",
+       "-",
+       "~",
+       ".",
+       "+",
+       "-",
+       "*",
+       "/",
+       "%",
+       ">>",
+       "<<",
+       "&",
+       "|",
+       "^",
+       "->",
+       "int->double",
+       "double->int",
+       "&&",
+       "||",
+       "&~",
+       "double->long",
+       "long->double",
+       "integer->long",
+       "long->integer",
+       "==",
+       "!=",
+       "<=",
+       "<",
+       ">=",
+       ">",
+       "<p",
+       "<=p",
+       ">p",
+       ">=p",
+       "=+",
+       "=-",
+       "=*",
+       "=/",
+       "=%",
+       "=>>",
+       "=<<",
+       "=&",
+       "=|",
+       "=^",
+       "=",
+       "& for tests",
+       "*",
+       "/",
+       "%",
+       "=& ~",
+       "=*",
+       "=/",
+       "=%",
+       0,
+       "?",
+       "<<",
+       "=<<",
+       0,
+       0,
+       0,
+       0,
+       0,
+       "call",
+       "call",
+       "call",
+       0,
+       "goto",
+       "jump cond",
+       "branch cond",
+       "set nregs",
+       "load value",
+       0,
+       0,
+       0,
+       "force register"
+};
diff --git a/usr/source/c/c1h.c b/usr/source/c/c1h.c
new file mode 100644 (file)
index 0000000..ea972a6
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ *     C pass 2 header
+ */
+
+#define        swsiz   200
+#define        ossiz   500
+
+struct tnode {
+       int     op;
+       int     type;
+       int     degree;
+       struct  tnode *tr1, *tr2;
+};
+
+struct bnode {
+       int     bop;
+       struct  tnode *btree;
+       int     lbl;
+       int     cond;
+};
+
+struct tname {
+       int     nop;
+       int     ntype;
+       int     elsize;
+       char    class;
+       char    regno;
+       int     offset;
+       int     nloc;
+};
+
+/*
+ * for field selections
+ */
+struct tsel {
+       int     op;
+       int     type;
+       int     degree;
+       struct  tnode *tr1;
+       char    flen;
+       char    bitoffs;
+};
+
+struct tconst {
+       int     cop;
+       int     ctype;
+       int     cdeg;
+       int     value;
+};
+
+struct optab {
+       char    tabdeg1;
+       char    tabtyp1;
+       char    tabdeg2;
+       char    tabtyp2;
+       char    *tabstring;
+};
+
+struct table {
+       int     tabop;
+       struct  optab *tabp;
+};
+
+struct instab {
+       int     iop;
+       char    *str1;
+       char    *str2;
+};
+
+struct swtab {
+       int     swlab;
+       int     swval;
+};
+
+char   maprel[];
+char   notrel[];
+int    nreg;
+int    isn;
+int    namsiz;
+int    line;
+char   ascbuf[518];
+int    nerror;
+struct table   cctab[];
+struct table   efftab[];
+struct table   regtab[];
+struct table   sptab[];
+struct table   lsptab[];
+struct instab  instab[];
+struct instab  branchtab[];
+int    opdope[];
+char   *opntab[];
+int    nstack;
+int    nfloat;
+int    *spacep;
+int    treespace[ossiz];
+int    eolflg;
+struct tconst czero, cone, fczero;
+
+/*
+       operators
+*/
+#define        EOF     0
+#define        SEMI    1
+#define        LBRACE  2
+#define        RBRACE  3
+#define        LBRACK  4
+#define        RBRACK  5
+#define        LPARN   6
+#define        RPARN   7
+#define        COLON   8
+#define        COMMA   9
+#define        FSEL    10
+
+#define        KEYW    19
+#define        NAME    20
+#define        CON     21
+#define        STRING  22
+#define        FCON    23
+#define        SFCON   24
+
+#define        AUTOI   27
+#define        AUTOD   28
+#define        INCBEF  30
+#define        DECBEF  31
+#define        INCAFT  32
+#define        DECAFT  33
+#define        EXCLA   34
+#define        AMPER   35
+#define        STAR    36
+#define        NEG     37
+#define        COMPL   38
+
+#define        DOT     39
+#define        PLUS    40
+#define        MINUS   41
+#define        TIMES   42
+#define        DIVIDE  43
+#define        MOD     44
+#define        RSHIFT  45
+#define        LSHIFT  46
+#define        AND     47
+#define        NAND    55
+#define        OR      48
+#define        EXOR    49
+#define        ARROW   50
+#define        ITOF    51
+#define        FTOI    52
+#define        LOGAND  53
+#define        LOGOR   54
+#define        FTOL    56
+#define        LTOF    57
+#define        ITOL    58
+#define        LTOI    59
+
+#define        EQUAL   60
+#define        NEQUAL  61
+#define        LESSEQ  62
+#define        LESS    63
+#define        GREATEQ 64
+#define        GREAT   65
+#define        LESSEQP 66
+#define        LESSP   67
+#define        GREATQP 68
+#define        GREATP  69
+
+#define        ASPLUS  70
+#define        ASMINUS 71
+#define        ASTIMES 72
+#define        ASDIV   73
+#define        ASMOD   74
+#define        ASRSH   75
+#define        ASLSH   76
+#define        ASSAND  77
+#define        ASOR    78
+#define        ASXOR   79
+#define        ASSIGN  80
+#define        TAND    81
+#define        LTIMES  82
+#define        LDIV    83
+#define        LMOD    84
+#define        ASSNAND 85
+#define        LASTIMES 86
+#define        LASDIV  87
+#define        LASMOD  88
+
+#define        QUEST   90
+#define        LLSHIFT 91
+#define        ASLSHL  92
+#define        CALL1   98
+#define        CALL2   99
+#define        CALL    100
+#define        MCALL   101
+#define        JUMP    102
+#define        CBRANCH 103
+#define        INIT    104
+#define        SETREG  105
+#define        LOAD    106
+#define        RFORCE  110
+
+/*
+ * Intermediate code operators
+ */
+#define        BRANCH  111
+#define        LABEL   112
+#define        NLABEL  113
+#define        RLABEL  114
+#define        BDATA   200
+#define        WDATA   201
+#define        PROG    202
+#define        DATA    203
+#define        BSS     204
+#define        CSPACE  205
+#define        SSPACE  206
+#define        SYMDEF  207
+#define        SAVE    208
+#define        RETRN   209
+#define        EVEN    210
+#define        PROFIL  212
+#define        SWIT    213
+#define        EXPR    214
+#define        SNAME   215
+#define        RNAME   216
+#define        ANAME   217
+#define        NULL    218
+
+/*
+ *     types
+ */
+#define        INT     0
+#define        CHAR    1
+#define        FLOAT   2
+#define        DOUBLE  3
+#define        STRUCT  4
+#define        RSTRUCT 5
+#define        LONG    6
+
+#define        TYLEN   2
+#define        TYPE    07
+#define        XTYPE   (03<<3)
+#define        PTR     010
+#define        FUNC    020
+#define        ARRAY   030
+
+/*
+       storage classes
+*/
+#define        KEYWC   1
+#define        MOS     10
+#define        AUTO    11
+#define        EXTERN  12
+#define        STATIC  13
+#define        REG     14
+#define        STRTAG  15
+#define        ARG     16
+#define        OFFS    20
+#define        XOFFS   21
+#define        SOFFS   22
+
+/*
+       Flag    bits
+*/
+
+#define        BINARY  01
+#define        LVALUE  02
+#define        RELAT   04
+#define        ASSGOP  010
+#define        LWORD   020
+#define        RWORD   040
+#define        COMMUTE 0100
+#define        RASSOC  0200
+#define        LEAF    0400
+#define        CNVRT   01000
diff --git a/usr/source/c/c1t.s b/usr/source/c/c1t.s
new file mode 100644 (file)
index 0000000..8cc6ca6
--- /dev/null
@@ -0,0 +1,85 @@
+/ C operator tables
+
+.globl fltused; fltused=.
+.globl _instab
+.globl _branchtab
+
+.data
+_instab:
+       80.; 1f; 2f; .text; 1:<mov\0>; 2:<clr\0>; .data
+       60.; 1f; 2f; .text; 1: <cmp\0>; 2: <tst\0>; .data
+       106.; 1b; 2b
+       61.; 1b; 2b
+       62.; 1b; 2b
+       63.; 1b; 2b
+       64.; 1b; 2b
+       65.; 1b; 2b
+       66.; 1b; 2b
+       67.; 1b; 2b
+       68.; 1b; 2b
+       69.; 1b; 2b
+       40.; 1f; 3f; .text; 1:<add\0>; .data
+       70.; 1b; 3f
+       41.; 2f; 4f; .text; 2:<sub\0>; .data
+       71.; 2b; 4f
+       30.; 1b; 3f; .text; 3:<inc\0>; .data
+       31.; 2b; 4f; .text; 4:<dec\0>; .data
+       32.; 1b; 3b
+       33.; 2b; 4b
+       42.; 5f; 5f; .text; 5:<mul>; .data
+       72.; 5b; 5b
+       43.; 6f; 6f; .text; 6:<div\0>; .data
+       73.; 6b; 6b
+       44.; 5b; 6b
+       74.; 5b; 6b
+       45.; 5f; 6f; .text;     6:<asr\0>; .data
+       75.; 5f; 6b
+       46.; 5f; 6f; .text; 5:<ash\0>; 6:<asl\0>; .data
+       76.; 5b; 6b
+       47.; 5f; 5f; .text; 5:<bic\0>; 6:<bic $1,\0>; .data
+       55.; 5b; 6b
+       85.; 5b; 6b
+       81.; 5f; 6f; .text; 5:<bit\0>; 6:<bit $1,\0>; .data
+       48.; 5f; 6f; .text; 5:<bis\0>; 6:<bis $1,\0>; .data
+       78.; 5b; 6b
+       49.; 5f; 5f; .text; 5:<xor\0>; .data
+       79.; 5b; 5b
+       37.; 1f; 1f; .text; 1:<neg\0>; .data
+       38.; 1f; 1f; .text; 1:<com\0>; .data
+
+       98.; 1f; 1f; .text; 1:<*$\0>; .data
+       99.; 1b+2; 1b+2
+       91.; 1f; 1f; .text; 1: <ashc\0>; .data
+       92.; 1b; 1b
+       82.; 1f; 1f; .text; 1:<lmul\0>; .data
+       83.; 1f; 1f; .text; 1:<ldiv\0>; .data
+       84.; 1f; 1f; .text; 1:<lrem\0>; .data
+       86.; 1f; 1f; .text; 1:<almul\0>; .data
+       87.; 1f; 1f; .text; 1:<aldiv\0>; .data
+       88.; 1f; 1f; .text; 1:<alrem\0>; .data
+       0
+
+.data
+_branchtab:
+       60.; 0f; 1f; .text; 0:<jeq\0>; 1:<jne\0>; .data
+       61.; 1b; 0b
+       62.; 2f; 5f; .text; 2:<jle\0>; 5:<jgt\0>; .data
+       63.; 3f; 4f; .text; 3:<jlt\0>; 4:<jge\0>; .data
+       64.; 4b; 3b
+       65.; 5b; 2b
+       66.; 6f; 9f; .text; 6:<jlos\0>; 9:<jhi\0>; .data
+       67.; 7f; 8f; .text; 7:<jlo\0>; 8:<jhis\0>; .data
+       68.; 8b; 7b
+       69.; 9b; 6b
+
+       260.; 0b; 1b
+       261.; 1b; 0b
+       262.; 2b; 5b
+       263.; 3b; 4b
+       264.; 4b; 3b
+       265.; 5b; 2b
+       266.; 0b; 1b
+       267.; 7f; 8f; .text; 7:</nop\0>; 8:<jbr\0>; .data
+       268.; 8b; 7b
+       269.; 1b; 0b
+       0
diff --git a/usr/source/c/c20.c b/usr/source/c/c20.c
new file mode 100644 (file)
index 0000000..d06571f
--- /dev/null
@@ -0,0 +1,673 @@
+#
+/*
+ *      C object code improver
+ */
+
+#include "c2h.c"
+
+struct optab optab[] {
+       "jbr",  JBR,
+       "jeq",  CBR | JEQ<<8,
+       "jne",  CBR | JNE<<8,
+       "jle",  CBR | JLE<<8,
+       "jge",  CBR | JGE<<8,
+       "jlt",  CBR | JLT<<8,
+       "jgt",  CBR | JGT<<8,
+       "jlo",  CBR | JLO<<8,
+       "jhi",  CBR | JHI<<8,
+       "jlos", CBR | JLOS<<8,
+       "jhis", CBR | JHIS<<8,
+       "jmp",  JMP,
+       ".globl",EROU,
+       "mov",  MOV,
+       "clr",  CLR,
+       "com",  COM,
+       "inc",  INC,
+       "dec",  DEC,
+       "neg",  NEG,
+       "tst",  TST,
+       "asr",  ASR,
+       "asl",  ASL,
+       "sxt",  SXT,
+       "cmp",  CMP,
+       "add",  ADD,
+       "sub",  SUB,
+       "bit",  BIT,
+       "bic",  BIC,
+       "bis",  BIS,
+       "mul",  MUL,
+       "ash",  ASH,
+       "xor",  XOR,
+       ".text",TEXT,
+       ".data",DATA,
+       ".bss", BSS,
+       ".even",EVEN,
+       "movf", MOVF,
+       "movof",MOVOF,
+       "movfo",MOVFO,
+       "addf", ADDF,
+       "subf", SUBF,
+       "divf", DIVF,
+       "mulf", MULF,
+       "clrf", CLRF,
+       "cmpf", CMPF,
+       "negf", NEGF,
+       "tstf", TSTF,
+       "cfcc", CFCC,
+       "sob",  SOB,
+       "jsr",  JSR,
+       ".end", END,
+       0,      0};
+
+char   revbr[] { JNE, JEQ, JGT, JLT, JGE, JLE, JHIS, JLOS, JHI, JLO };
+int    isn     20000;
+
+main(argc, argv)
+char **argv;
+{
+       register int niter, maxiter, isend;
+       extern end;
+       extern fin, fout;
+       int nflag;
+
+       if (argc>1 && argv[1][0]=='+') {
+               argc--;
+               argv++;
+               debug++;
+       }
+       if (argc>1 && argv[1][0]=='-') {
+               argc--;
+               argv++;
+               nflag++;
+       }
+       if (argc>1) {
+               if ((fin = open(argv[1], 0)) < 0) {
+                       printf("C2: can't find %s\n", argv[1]);
+                       exit(1);
+               }
+       } else
+               fin = dup(0);
+       if (argc>2) {
+               if ((fout = creat(argv[2], 0666)) < 0) {
+                       fout = 1;
+                       printf("C2: can't create %s\n", argv[2]);
+                       exit(1);
+               }
+       } else
+               fout = dup(1);
+       lasta = firstr = lastr = sbrk(2);
+       maxiter = 0;
+       opsetup();
+       do {
+               isend = input();
+               movedat();
+               niter = 0;
+               do {
+                       refcount();
+                       do {
+                               iterate();
+                               clearreg();
+                               niter++;
+                       } while (nchange);
+                       comjump();
+                       rmove();
+               } while (nchange || jumpsw());
+               addsob();
+               output();
+               if (niter > maxiter)
+                       maxiter = niter;
+               lasta = firstr;
+       } while (isend);
+       flush();
+       fout = 2;
+       if (nflag) {
+               printf("%d iterations\n", maxiter);
+               printf("%d jumps to jumps\n", nbrbr);
+               printf("%d inst. after jumps\n", iaftbr);
+               printf("%d jumps to .+2\n", njp1);
+               printf("%d redundant labels\n", nrlab);
+               printf("%d cross-jumps\n", nxjump);
+               printf("%d code motions\n", ncmot);
+               printf("%d branches reversed\n", nrevbr);
+               printf("%d redundant moves\n", redunm);
+               printf("%d simplified addresses\n", nsaddr);
+               printf("%d loops inverted\n", loopiv);
+               printf("%d redundant jumps\n", nredunj);
+               printf("%d common seqs before jmp's\n", ncomj);
+               printf("%d skips over jumps\n", nskip);
+               printf("%d sob's added\n", nsob);
+               printf("%d redundant tst's\n", nrtst);
+               printf("%d literals eliminated\n", nlit);
+               printf("%dK core\n", ((lastr+01777)>>10)&077);
+               flush();
+       }
+       exit(0);
+}
+
+input()
+{
+       register struct node *p, *lastp;
+       register int op;
+
+       lastp = &first;
+       for (;;) {
+               op = getline();
+               switch (op.op) {
+       
+               case LABEL:
+                       p = alloc(sizeof first);
+                       if (line[0] == 'L') {
+                               p->combop = LABEL;
+                               p->labno = getnum(line+1);
+                               p->code = 0;
+                       } else {
+                               p->combop = DLABEL;
+                               p->labno = 0;
+                               p->code = copy(line);
+                       }
+                       break;
+       
+               case JBR:
+               case CBR:
+               case JMP:
+               case JSW:
+                       p = alloc(sizeof first);
+                       p->combop = op;
+                       if (*curlp=='L' && (p->labno = getnum(curlp+1)))
+                               p->code = 0;
+                       else {
+                               p->labno = 0;
+                               p->code = copy(curlp);
+                       }
+                       break;
+
+               default:
+                       p = alloc(sizeof first);
+                       p->combop = op;
+                       p->labno = 0;
+                       p->code = copy(curlp);
+                       break;
+
+               }
+               p->forw = 0;
+               p->back = lastp;
+               lastp->forw = p;
+               lastp = p;
+               p->ref = 0;
+               if (op==EROU)
+                       return(1);
+               if (op==END)
+                       return(0);
+       }
+}
+
+getline()
+{
+       register char *lp;
+       register c;
+
+       lp = line;
+       while (c = getchar()) {
+               if (c==':') {
+                       *lp++ = 0;
+                       return(LABEL);
+               }
+               if (c=='\n') {
+                       *lp++ = 0;
+                       return(oplook());
+               }
+               *lp++ = c;
+       }
+       *lp++ = 0;
+       return(END);
+}
+
+getnum(ap)
+char *ap;
+{
+       register char *p;
+       register n, c;
+
+       p = ap;
+       n = 0;
+       while ((c = *p++) >= '0' && c <= '9')
+               n = n*10 + c - '0';
+       if (*--p != 0)
+               return(0);
+       return(n);
+}
+
+output()
+{
+       register struct node *t;
+       register struct optab *op;
+       register int byte;
+
+       t = &first;
+       while (t = t->forw) switch (t->op) {
+
+       case END:
+               return;
+
+       case LABEL:
+               printf("L%d:", t->labno);
+               continue;
+
+       case DLABEL:
+               printf("%s:", t->code);
+               continue;
+
+       default:
+               if ((byte = t->subop) == BYTE)
+                       t->subop = 0;
+               for (op = optab; op->opstring!=0; op++) 
+                       if (op->opcode == t->combop) {
+                               printf("%s", op->opstring);
+                               if (byte==BYTE)
+                                       printf("b");
+                               break;
+                       }
+               if (t->code) {
+                       reducelit(t);
+                       printf("\t%s\n", t->code);
+               } else if (t->op==JBR || t->op==CBR)
+                       printf("\tL%d\n", t->labno);
+               else
+                       printf("\n");
+               continue;
+
+       case JSW:
+               printf("L%d\n", t->labno);
+               continue;
+
+       case SOB:
+               printf("sob     %s,L%d\n", t->code, t->labno);
+               continue;
+
+       case 0:
+               if (t->code)
+                       printf("%s", t->code);
+               printf("\n");
+               continue;
+       }
+}
+
+/*
+ * Notice addresses of the form
+ * $xx,xx(r)
+ * and replace them with (pc),xx(r)
+ *     -- Thanx and a tip of the Hatlo hat to Bliss-11.
+ */
+reducelit(at)
+struct node *at;
+{
+       register char *c1, *c2;
+       char *c2s;
+       register struct node *t;
+
+       t = at;
+       if (*t->code != '$')
+               return;
+       c1 = t->code;
+       while (*c1 != ',')
+               if (*c1++ == '\0')
+                       return;
+       c2s = c1;
+       c1++;
+       if (*c1=='*')
+               c1++;
+       c2 = t->code+1;
+       while (*c1++ == *c2++);
+       if (*--c1!='(' || *--c2!=',')
+               return;
+       t->code = copy("(pc)", c2s);
+       nlit++;
+}
+
+copy(ap)
+char *ap;
+{
+       register char *p, *np;
+       char *onp;
+       register n;
+       int na;
+
+       na = nargs();
+       p = ap;
+       n = 0;
+       if (*p==0)
+               return(0);
+       do
+               n++;
+       while (*p++);
+       if (na>1) {
+               p = (&ap)[1];
+               while (*p++)
+                       n++;
+       }
+       onp = np = alloc(n);
+       p = ap;
+       while (*np++ = *p++);
+       if (na>1) {
+               p = (&ap)[1];
+               np--;
+               while (*np++ = *p++);
+       }
+       return(onp);
+}
+
+opsetup()
+{
+       register struct optab *optp, **ophp;
+       register char *p;
+
+       for (optp = optab; p = optp->opstring; optp++) {
+               ophp = &ophash[(((p[0]<<3)+(p[1]<<1)+p[2])&077777) % OPHS];
+               while (*ophp++)
+                       if (ophp > &ophash[OPHS])
+                               ophp = ophash;
+               *--ophp = optp;
+       }
+}
+
+oplook()
+{
+       register struct optab *optp;
+       register char *lp, *op;
+       static char tmpop[32];
+       struct optab **ophp;
+
+       op = tmpop;
+       for (lp = line; *lp && *lp!=' ' && *lp!='\t';)
+               *op++ = *lp++;
+       *op++ = 0;
+       while (*lp=='\t' || *lp==' ')
+               lp++;
+       curlp = lp;
+       ophp = &ophash[(((tmpop[0]<<3)+(tmpop[1]<<1)+tmpop[2])&077777) % OPHS];
+       while (optp = *ophp) {
+               op = optp->opstring;
+               lp = tmpop;
+               while (*lp == *op++)
+                       if (*lp++ == 0)
+                               return(optp->opcode);
+               if (*lp++=='b' && *lp++==0 && *--op==0)
+                       return(optp->opcode + (BYTE<<8));
+               ophp++;
+               if (ophp >= &ophash[OPHS])
+                       ophp = ophash;
+       }
+       if (line[0]=='L') {
+               lp = &line[1];
+               while (*lp)
+                       if (*lp<'0' || *lp++>'9')
+                               return(0);
+               curlp = line;
+               return(JSW);
+       }
+       curlp = line;
+       return(0);
+}
+
+refcount()
+{
+       register struct node *p, *lp;
+       static struct node *labhash[LABHS];
+       register struct node **hp;
+
+       for (hp = labhash; hp < &labhash[LABHS];)
+               *hp++ = 0;
+       for (p = first.forw; p!=0; p = p->forw)
+               if (p->op==LABEL) {
+                       labhash[p->labno % LABHS] = p;
+                       p->refc = 0;
+               }
+       for (p = first.forw; p!=0; p = p->forw) {
+               if (p->op==JBR || p->op==CBR || p->op==JSW) {
+                       p->ref = 0;
+                       lp = labhash[p->labno % LABHS];
+                       if (lp==0 || p->labno!=lp->labno)
+                       for (lp = first.forw; lp!=0; lp = lp->forw) {
+                               if (lp->op==LABEL && p->labno==lp->labno)
+                                       break;
+                       }
+                       if (lp) {
+                               hp = nonlab(lp)->back;
+                               if (hp!=lp) {
+                                       p->labno = hp->labno;
+                                       lp = hp;
+                               }
+                               p->ref = lp;
+                               lp->refc++;
+                       }
+               }
+       }
+       for (p = first.forw; p!=0; p = p->forw)
+               if (p->op==LABEL && p->refc==0
+                && (lp = nonlab(p))->op && lp->op!=JSW)
+                       decref(p);
+}
+
+iterate()
+{
+       register struct node *p, *rp, *p1;
+
+       nchange = 0;
+       for (p = first.forw; p!=0; p = p->forw) {
+               if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) {
+                       rp = nonlab(p->ref);
+                       if (rp->op==JBR && rp->labno && p!=rp) {
+                               nbrbr++;
+                               p->labno = rp->labno;
+                               decref(p->ref);
+                               rp->ref->refc++;
+                               p->ref = rp->ref;
+                               nchange++;
+                       }
+               }
+               if (p->op==CBR && (p1 = p->forw)->op==JBR) {
+                       rp = p->ref;
+                       do
+                               rp = rp->back;
+                       while (rp->op==LABEL);
+                       if (rp==p1) {
+                               decref(p->ref);
+                               p->ref = p1->ref;
+                               p->labno = p1->labno;
+                               p1->forw->back = p;
+                               p->forw = p1->forw;
+                               p->subop = revbr[p->subop];
+                               nchange++;
+                               nskip++;
+                       }
+               }
+               if (p->op==JBR || p->op==JMP) {
+                       while (p->forw && p->forw->op!=LABEL
+                               && p->forw->op!=EROU && p->forw->op!=END) {
+                               nchange++;
+                               iaftbr++;
+                               if (p->forw->ref)
+                                       decref(p->forw->ref);
+                               p->forw = p->forw->forw;
+                               p->forw->back = p;
+                       }
+                       rp = p->forw;
+                       while (rp && rp->op==LABEL) {
+                               if (p->ref == rp) {
+                                       p->back->forw = p->forw;
+                                       p->forw->back = p->back;
+                                       p = p->back;
+                                       decref(rp);
+                                       nchange++;
+                                       njp1++;
+                                       break;
+                               }
+                               rp = rp->forw;
+                       }
+                       xjump(p);
+                       p = codemove(p);
+               }
+       }
+}
+
+xjump(ap)
+{
+       register int *p1, *p2, *p3;
+       int nxj;
+
+       nxj = 0;
+       p1 = ap;
+       if ((p2 = p1->ref)==0)
+               return(0);
+       for (;;) {
+               while ((p1 = p1->back) && p1->op==LABEL);
+               while ((p2 = p2->back) && p2->op==LABEL);
+               if (!equop(p1, p2) || p1==p2)
+                       return(nxj);
+               p3 = insertl(p2);
+               p1->combop = JBR;
+               p1->ref = p3;
+               p1->labno = p3->labno;
+               p1->code = 0;
+               nxj++;
+               nxjump++;
+               nchange++;
+       }
+}
+
+insertl(ap)
+struct node *ap;
+{
+       register struct node *lp, *op;
+
+       op = ap;
+       if (op->op == LABEL) {
+               op->refc++;
+               return(op);
+       }
+       if (op->back->op == LABEL) {
+               op = op->back;
+               op->refc++;
+               return(op);
+       }
+       lp = alloc(sizeof first);
+       lp->combop = LABEL;
+       lp->labno = isn++;
+       lp->ref = 0;
+       lp->code = 0;
+       lp->refc = 1;
+       lp->back = op->back;
+       lp->forw = op;
+       op->back->forw = lp;
+       op->back = lp;
+       return(lp);
+}
+
+codemove(ap)
+struct node *ap;
+{
+       register struct node *p1, *p2, *p3;
+       struct node *t, *tl;
+       int n;
+
+       p1 = ap;
+       if (p1->op!=JBR || (p2 = p1->ref)==0)
+               return(p1);
+       while (p2->op == LABEL)
+               if ((p2 = p2->back) == 0)
+                       return(p1);
+       if (p2->op!=JBR && p2->op!=JMP)
+               goto ivloop;
+       p2 = p2->forw;
+       p3 = p1->ref;
+       while (p3) {
+               if (p3->op==JBR || p3->op==JMP) {
+                       if (p1==p3)
+                               return(p1);
+                       ncmot++;
+                       nchange++;
+                       p1->back->forw = p2;
+                       p1->forw->back = p3;
+                       p2->back->forw = p3->forw;
+                       p3->forw->back = p2->back;
+                       p2->back = p1->back;
+                       p3->forw = p1->forw;
+                       decref(p1->ref);
+                       return(p2);
+               } else
+                       p3 = p3->forw;
+       }
+       return(p1);
+ivloop:
+       if (p1->forw->op!=LABEL)
+               return(p1);
+       p3 = p2 = p2->forw;
+       n = 16;
+       do {
+               if ((p3 = p3->forw) == 0 || p3==p1 || --n==0)
+                       return(p1);
+       } while (p3->op!=CBR || p3->labno!=p1->forw->labno);
+       do 
+               if ((p1 = p1->back) == 0)
+                       return(ap);
+       while (p1!=p3);
+       p1 = ap;
+       tl = insertl(p1);
+       p3->subop = revbr[p3->subop];
+       decref(p3->ref);
+       p2->back->forw = p1;
+       p3->forw->back = p1;
+       p1->back->forw = p2;
+       p1->forw->back = p3;
+       t = p1->back;
+       p1->back = p2->back;
+       p2->back = t;
+       t = p1->forw;
+       p1->forw = p3->forw;
+       p3->forw = t;
+       p2 = insertl(p1->forw);
+       p3->labno = p2->labno;
+       p3->ref = p2;
+       decref(tl);
+       if (tl->refc<=0)
+               nrlab--;
+       loopiv++;
+       nchange++;
+       return(p3);
+}
+
+comjump()
+{
+       register struct node *p1, *p2, *p3;
+
+       for (p1 = first.forw; p1!=0; p1 = p1->forw)
+               if (p1->op==JBR && (p2 = p1->ref) && p2->refc > 1)
+                       for (p3 = p1->forw; p3!=0; p3 = p3->forw)
+                               if (p3->op==JBR && p3->ref == p2)
+                                       backjmp(p1, p3);
+}
+
+backjmp(ap1, ap2)
+struct node *ap1, *ap2;
+{
+       register struct node *p1, *p2, *p3;
+
+       p1 = ap1;
+       p2 = ap2;
+       for(;;) {
+               while ((p1 = p1->back) && p1->op==LABEL);
+               p2 = p2->back;
+               if (equop(p1, p2)) {
+                       p3 = insertl(p1);
+                       p2->back->forw = p2->forw;
+                       p2->forw->back = p2->back;
+                       p2 = p2->forw;
+                       decref(p2->ref);
+                       p2->labno = p3->labno;
+                       p2->ref = p3;
+                       nchange++;
+                       ncomj++;
+               } else
+                       return;
+       }
+}
diff --git a/usr/source/c/c21.c b/usr/source/c/c21.c
new file mode 100644 (file)
index 0000000..a423f3a
--- /dev/null
@@ -0,0 +1,659 @@
+#
+/*
+ * C object code improver-- second part
+ */
+
+#include "c2h.c"
+
+rmove()
+{
+       register struct node *p;
+       register char *cp;
+       register int r;
+       int r1, flt;
+
+       for (p=first.forw; p!=0; p = p->forw) {
+       if (debug) {
+               for (r=0; r<2*NREG; r++)
+                       if (regs[r][0])
+                               printf("%d: %s\n", r, regs[r]);
+               printf("-\n");
+       }
+       flt = 0;
+       switch (p->op) {
+
+       case MOVF:
+       case MOVFO:
+       case MOVOF:
+               flt = NREG;
+
+       case MOV:
+               if (p->subop==BYTE)
+                       goto badmov;
+               dualop(p);
+               if ((r = findrand(regs[RT1], flt)) >= 0) {
+                       if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR) {
+                               p->forw->back = p->back;
+                               p->back->forw = p->forw;
+                               redunm++;
+                               continue;
+                       }
+               }
+               repladdr(p, 0, flt);
+               r = isreg(regs[RT1]);
+               r1 = isreg(regs[RT2]);
+               dest(regs[RT2], flt);
+               if (r >= 0)
+                       if (r1 >= 0)
+                               savereg(r1+flt, regs[r+flt]);
+                       else
+                               savereg(r+flt, regs[RT2]);
+               else
+                       if (r1 >= 0)
+                               savereg(r1+flt, regs[RT1]);
+                       else
+                               setcon(regs[RT1], regs[RT2]);
+               source(regs[RT1]);
+               setcc(regs[RT2]);
+               continue;
+
+       case ADDF:
+       case SUBF:
+       case DIVF:
+       case MULF:
+               flt = NREG;
+
+       case ADD:
+       case SUB:
+       case BIC:
+       case BIS:
+       case MUL:
+       case DIV:
+       case ASH:
+       badmov:
+               dualop(p);
+               repladdr(p, 0, flt);
+               source(regs[RT1]);
+               dest(regs[RT2], flt);
+               if (p->op==DIV && (r = isreg(regs[RT2])>=0))
+                       regs[r+1][0] = 0;
+               ccloc[0] = 0;
+               continue;
+
+       case CLRF:
+       case NEGF:
+               flt = NREG;
+
+       case CLR:
+       case COM:
+       case INC:
+       case DEC:
+       case NEG:
+       case ASR:
+       case ASL:
+       case SXT:
+               singop(p);
+               dest(regs[RT1], flt);
+               if (p->op==CLR && flt==0)
+                       if ((r = isreg(regs[RT1])) >= 0)
+                               savereg(r, "$0");
+                       else
+                               setcon("$0", regs[RT1]);
+               setcc(regs[RT1]);
+               continue;
+
+       case TSTF:
+               flt = NREG;
+
+       case TST:
+               singop(p);
+               repladdr(p, 0, flt);
+               source(regs[RT1]);
+               if (equstr(regs[RT1], ccloc)) {
+                       p->back->forw = p->forw;
+                       p->forw->back = p->back;
+                       p = p->back;
+                       nrtst++;
+                       nchange++;
+               }
+               continue;
+
+       case CMPF:
+               flt = NREG;
+
+       case CMP:
+       case BIT:
+               dualop(p);
+               source(regs[RT1]);
+               source(regs[RT2]);
+               repladdr(p, 1, flt);
+               ccloc[0] = 0;
+               continue;
+
+       case CBR:
+       case CFCC:
+               ccloc[0] = 0;
+               continue;
+
+       case JBR:
+               redunbr(p);
+
+       default:
+               clearreg();
+       }
+       }
+}
+
+jumpsw()
+{
+       register struct node *p, *p1;
+       register t;
+       int nj;
+
+       t = 0;
+       nj = 0;
+       for (p=first.forw; p!=0; p = p->forw)
+               p->refc = ++t;
+       for (p=first.forw; p!=0; p = p1) {
+               p1 = p->forw;
+               if (p->op == CBR && p1->op==JBR && p->ref && p1->ref
+                && abs(p->refc - p->ref->refc) > abs(p1->refc - p1->ref->refc)) {
+                       p->subop = revbr[p->subop];
+                       t = p1->ref;
+                       p1->ref = p->ref;
+                       p->ref = t;
+                       t = p1->labno;
+                       p1->labno = p->labno;
+                       p->labno = t;
+                       nrevbr++;
+                       nj++;
+               }
+       }
+       return(nj);
+}
+
+addsob()
+{
+       register struct node *p, *p1;
+
+       for (p = &first; (p1 = p->forw)!=0; p = p1) {
+               if (p->op==DEC && isreg(p->code)>=0
+                && p1->combop==(CBR|JNE<<8)) {
+                       if (p->refc < p1->ref->refc)
+                               continue;
+                       if (p->refc - p1->ref->refc > 50)
+                               continue;
+                       p->labno = p1->labno;
+                       p->combop = SOB;
+                       p1->forw->back = p;
+                       p->forw = p1->forw;
+                       nsob++;
+               }
+       }
+}
+
+abs(x)
+{
+       return(x<0? -x: x);
+}
+
+equop(ap1, p2)
+struct node *ap1, *p2;
+{
+       register char *cp1, *cp2;
+       register struct node *p1;
+
+       p1 = ap1;
+       if (p1->combop != p2->combop)
+               return(0);
+       if (p1->op>0 && p1->op<MOV)
+               return(0);
+       cp1 = p1->code;
+       cp2 = p2->code;
+       if (cp1==0 && cp2==0)
+               return(1);
+       if (cp1==0 || cp2==0)
+               return(0);
+       while (*cp1 == *cp2++)
+               if (*cp1++ == 0)
+                       return(1);
+       return(0);
+}
+
+decref(ap)
+{
+       register struct node *p;
+
+       p = ap;
+       if (--p->refc <= 0) {
+               nrlab++;
+               p->back->forw = p->forw;
+               p->forw->back = p->back;
+       }
+}
+
+nonlab(ap)
+struct node *ap;
+{
+       register struct node *p;
+
+       p = ap;
+       while (p && p->op==LABEL)
+               p = p->forw;
+       return(p);
+}
+
+alloc(an)
+{
+       register int n;
+       register char *p;
+
+       n = an;
+       n++;
+       n =& ~01;
+       if (lasta+n >= lastr) {
+               if (sbrk(2000) == -1) {
+                       write(2, "Optimizer: out of space\n", 14);
+                       exit(1);
+               }
+               lastr =+ 2000;
+       }
+       p = lasta;
+       lasta =+ n;
+       return(p);
+}
+
+clearreg()
+{
+       register int i;
+
+       for (i=0; i<2*NREG; i++)
+               regs[i][0] = '\0';
+       conloc[0] = 0;
+       ccloc[0] = 0;
+}
+
+savereg(ai, as)
+char *as;
+{
+       register char *p, *s, *sp;
+
+       sp = p = regs[ai];
+       s = as;
+       if (source(s))
+               return;
+       while (*p++ = *s) {
+               if (s[0]=='(' && s[1]=='r' && s[2]<'5') {
+                       *sp = 0;
+                       return;
+               }
+               if (*s++ == ',')
+                       break;
+       }
+       *--p = '\0';
+}
+
+dest(as, flt)
+char *as;
+{
+       register char *s;
+       register int i;
+
+       s = as;
+       if ((i = isreg(s)) >= 0)
+               regs[i+flt][0] = 0;
+       while ((i = findrand(s, flt)) >= 0)
+               regs[i][0] = 0;
+       while (*s) {
+               if ((*s=='(' && (*(s+1)!='r' || *(s+2)!='5')) || *s++=='*') {
+                       for (i=flt; i<flt+NREG; i++) {
+                               if (regs[i][0] != '$')
+                                       regs[i][0] = 0;
+                               conloc[0] = 0;
+                       }
+                       return;
+               }
+       }
+}
+
+singop(ap)
+struct node *ap;
+{
+       register char *p1, *p2;
+
+       p1 = ap->code;
+       p2 = regs[RT1];
+       while (*p2++ = *p1++);
+       regs[RT2][0] = 0;
+}
+
+
+dualop(ap)
+struct node *ap;
+{
+       register char *p1, *p2;
+       register struct node *p;
+
+       p = ap;
+       p1 = p->code;
+       p2 = regs[RT1];
+       while (*p1 && *p1!=',')
+               *p2++ = *p1++;
+       *p2++ = 0;
+       p2 = regs[RT2];
+       *p2 = 0;
+       if (*p1++ !=',')
+               return;
+       while (*p2++ = *p1++);
+}
+
+findrand(as, flt)
+char *as;
+{
+       register int i;
+       for (i = flt; i<NREG+flt; i++) {
+               if (equstr(regs[i], as))
+                       return(i);
+       }
+       return(-1);
+}
+
+isreg(as)
+char *as;
+{
+       register char *s;
+
+       s = as;
+       if (s[0]=='r' && s[1]>='0' && s[1]<='4' && s[2]==0)
+               return(s[1]-'0');
+       return(-1);
+}
+
+check()
+{
+       register struct node *p, *lp;
+
+       lp = &first;
+       for (p=first.forw; p!=0; p = p->forw) {
+               if (p->back != lp)
+                       abort();
+               lp = p;
+       }
+}
+
+source(ap)
+char *ap;
+{
+       register char *p1, *p2;
+
+       p1 = ap;
+       p2 = p1;
+       if (*p1==0)
+               return(0);
+       while (*p2++);
+       if (*p1=='-' && *(p1+1)=='('
+        || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='('
+        || *(p2-2)=='+') {
+               while (*p1 && *p1++!='r');
+               if (*p1>='0' && *p1<='4')
+                       regs[*p1 - '0'][0] = 0;
+               return(1);
+       }
+       return(0);
+}
+
+repladdr(p, f, flt)
+struct node *p;
+{
+       register r;
+       int r1;
+       register char *p1, *p2;
+       static char rt1[50], rt2[50];
+
+       if (f)
+               r1 = findrand(regs[RT2], flt);
+       else
+               r1 = -1;
+       r = findrand(regs[RT1], flt);
+       if (r1 >= NREG)
+               r1 =- NREG;
+       if (r >= NREG)
+               r =- NREG;
+       if (r>=0 || r1>=0) {
+               p2 = regs[RT1];
+               for (p1 = rt1; *p1++ = *p2++;);
+               if (regs[RT2][0]) {
+                       p1 = rt2;
+                       *p1++ = ',';
+                       for (p2 = regs[RT2]; *p1++ = *p2++;);
+               } else
+                       rt2[0] = 0;
+               if (r>=0) {
+                       rt1[0] = 'r';
+                       rt1[1] = r + '0';
+                       rt1[2] = 0;
+                       nsaddr++;
+               }
+               if (r1>=0) {
+                       rt2[1] = 'r';
+                       rt2[2] = r1 + '0';
+                       rt2[3] = 0;
+                       nsaddr++;
+               }
+               p->code = copy(rt1, rt2);
+       }
+}
+
+movedat()
+{
+       register struct node *p1, *p2;
+       struct node *p3;
+       register seg;
+       struct node data;
+       struct node *datp;
+
+       if (first.forw == 0)
+               return;
+       datp = &data;
+       for (p1 = first.forw; p1!=0; p1 = p1->forw) {
+               if (p1->op == DATA) {
+                       p2 = p1->forw;
+                       while (p2 && p2->op!=TEXT)
+                               p2 = p2->forw;
+                       if (p2==0)
+                               break;
+                       p3 = p1->back;
+                       p1->back->forw = p2->forw;
+                       p2->forw->back = p3;
+                       p2->forw = 0;
+                       datp->forw = p1;
+                       p1->back = datp;
+                       p1 = p3;
+                       datp = p2;
+               }
+       }
+       if (data.forw) {
+               datp->forw = first.forw;
+               first.forw->back = datp;
+               data.forw->back = &first;
+               first.forw = data.forw;
+       }
+       seg = -1;
+       for (p1 = first.forw; p1!=0; p1 = p1->forw) {
+               if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) {
+                       if (p1->op == seg || p1->forw&&p1->forw->op==seg) {
+                               p1->back->forw = p1->forw;
+                               p1->forw->back = p1->back;
+                               p1 = p1->back;
+                               continue;
+                       }
+                       seg = p1->op;
+               }
+       }
+}
+
+redunbr(ap)
+struct node *ap;
+{
+       register struct node *p, *p1;
+       register char *ap1;
+       char *ap2;
+
+       if ((p1 = p->ref) == 0)
+               return;
+       p1 = nonlab(p1);
+       if (p1->op==TST) {
+               singop(p1);
+               savereg(RT2, "$0");
+       } else if (p1->op==CMP)
+               dualop(p1);
+       else
+               return;
+       if (p1->forw->op!=CBR)
+               return;
+       ap1 = findcon(RT1);
+       ap2 = findcon(RT2);
+       p1 = p1->forw;
+       if (compare(p1->subop, ap1, ap2)) {
+               nredunj++;
+               nchange++;
+               decref(p->ref);
+               p->ref = p1->ref;
+               p->labno = p1->labno;
+               p->ref->refc++;
+       }
+}
+
+findcon(i)
+{
+       register char *p;
+       register r;
+
+       p = regs[i];
+       if (*p=='$')
+               return(p);
+       if ((r = isreg(p)) >= 0)
+               return(regs[r]);
+       if (equstr(p, conloc))
+               return(conval);
+       return(p);
+}
+
+compare(op, acp1, acp2)
+char *acp1, *acp2;
+{
+       register char *cp1, *cp2;
+       register n1;
+       int n2;
+       struct { int i;};
+
+       cp1 = acp1;
+       cp2 = acp2;
+       if (*cp1++ != '$' || *cp2++ != '$')
+               return(0);
+       n1 = 0;
+       while (*cp2 >= '0' && *cp2 <= '7') {
+               n1 =<< 3;
+               n1 =+ *cp2++ - '0';
+       }
+       n2 = n1;
+       n1 = 0;
+       while (*cp1 >= '0' && *cp1 <= '7') {
+               n1 =<< 3;
+               n1 =+ *cp1++ - '0';
+       }
+       if (*cp1=='+')
+               cp1++;
+       if (*cp2=='+')
+               cp2++;
+       do {
+               if (*cp1++ != *cp2)
+                       return(0);
+       } while (*cp2++);
+       cp1 = n1;
+       cp2 = n2;
+       switch(op) {
+
+       case JEQ:
+               return(cp1 == cp2);
+       case JNE:
+               return(cp1 != cp2);
+       case JLE:
+               return(cp1.i <= cp2.i);
+       case JGE:
+               return(cp1.i >= cp2.i);
+       case JLT:
+               return(cp1.i < cp2.i);
+       case JGT:
+               return(cp1.i > cp2.i);
+       case JLO:
+               return(cp1 < cp2);
+       case JHI:
+               return(cp1 > cp2);
+       case JLOS:
+               return(cp1 <= cp2);
+       case JHIS:
+               return(cp1 >= cp2);
+       }
+       return(0);
+}
+
+setcon(ar1, ar2)
+char *ar1, *ar2;
+{
+       register char *cl, *cv, *p;
+
+       cl = ar2;
+       cv = ar1;
+       if (*cv != '$')
+               return;
+       if (!natural(cl))
+               return;
+       p = conloc;
+       while (*p++ = *cl++);
+       p = conval;
+       while (*p++ = *cv++);
+}
+
+equstr(ap1, ap2)
+char *ap1, *ap2;
+{
+       char *p1, *p2;
+
+       p1 = ap1;
+       p2 = ap2;
+       do {
+               if (*p1++ != *p2)
+                       return(0);
+       } while (*p2++);
+       return(1);
+}
+
+setcc(ap)
+char *ap;
+{
+       register char *p, *p1;
+
+       p = ap;
+       if (!natural(p)) {
+               ccloc[0] = 0;
+               return;
+       }
+       p1 = ccloc;
+       while (*p1++ = *p++);
+}
+
+natural(ap)
+char *ap;
+{
+       register char *p;
+
+       p = ap;
+       if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(')
+               return(0);
+       while (*p++);
+       p--;
+       if (*--p == '+' || *p ==')' && *--p != '5')
+               return(0);
+       return(1);
+}
diff --git a/usr/source/c/c2h.c b/usr/source/c/c2h.c
new file mode 100644 (file)
index 0000000..3f37a00
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Header for object code improver
+ */
+
+#define        JBR     1
+#define        CBR     2
+#define        JMP     3
+#define        LABEL   4
+#define        DLABEL  5
+#define        EROU    7
+#define        JSW     9
+#define        MOV     10
+#define        CLR     11
+#define        COM     12
+#define        INC     13
+#define        DEC     14
+#define        NEG     15
+#define        TST     16
+#define        ASR     17
+#define        ASL     18
+#define        SXT     19
+#define        CMP     20
+#define        ADD     21
+#define        SUB     22
+#define        BIT     23
+#define        BIC     24
+#define        BIS     25
+#define        MUL     26
+#define        DIV     27
+#define        ASH     28
+#define        XOR     29
+#define        TEXT    30
+#define        DATA    31
+#define        BSS     32
+#define        EVEN    33
+#define        MOVF    34
+#define        MOVOF   35
+#define        MOVFO   36
+#define        ADDF    37
+#define        SUBF    38
+#define        DIVF    39
+#define        MULF    40
+#define        CLRF    41
+#define        CMPF    42
+#define        NEGF    43
+#define        TSTF    44
+#define        CFCC    45
+#define        SOB     46
+#define        JSR     47
+#define        END     48
+
+#define        JEQ     0
+#define        JNE     1
+#define        JLE     2
+#define        JGE     3
+#define        JLT     4
+#define        JGT     5
+#define        JLO     6
+#define        JHI     7
+#define        JLOS    8
+#define        JHIS    9
+
+#define        BYTE    100
+
+struct node {
+       char    op;
+       char    subop;
+       struct  node    *forw;
+       struct  node    *back;
+       struct  node    *ref;
+       int     labno;
+       char    *code;
+       int     refc;
+};
+
+struct {
+       int     combop;
+};
+
+struct optab {
+       char    *opstring;
+       int     opcode;
+} optab[];
+
+char   line[512];
+struct node    first;
+char   *curlp;
+int    nbrbr;
+int    nsaddr;
+int    redunm;
+int    iaftbr;
+int    njp1;
+int    nrlab;
+int    nxjump;
+int    ncmot;
+int    nrevbr;
+int    loopiv;
+int    nredunj;
+int    nskip;
+int    ncomj;
+int    nsob;
+int    nrtst;
+int    nlit;
+
+int    nchange;
+int    isn;
+int    debug;
+char   *lasta;
+char   *lastr;
+char   *firstr;
+char   revbr[];
+char   regs[12][20];
+char   conloc[20];
+char   conval[20];
+char   ccloc[20];
+
+#define        RT1     10
+#define        RT2     11
+#define        FREG    5
+#define        NREG    5
+#define        LABHS   127
+#define        OPHS    57
+
+struct optab *ophash[OPHS];
+struct { char lbyte; };
diff --git a/usr/source/c/cvopt.c b/usr/source/c/cvopt.c
new file mode 100644 (file)
index 0000000..5b1c3d6
--- /dev/null
@@ -0,0 +1,370 @@
+int    nofloat;
+int    peekc;
+int    obuf[259];
+int    tabflg;
+int    labno   1;
+
+main(argc, argv)
+char **argv;
+{
+/*
+       A1 -> A
+       A2    B
+       A     O
+       B1    C
+       B2    D
+       BE    L
+       BF    P
+       C1    E
+       C2    F
+       F     G
+       H     H
+       R     I
+       R1    J
+       S     K
+       I     M
+       M     N
+
+               *       +1
+               S       +2
+               C       +4
+               1       +8
+
+       z  -> 4
+       c     10
+       a     14
+       e     20
+       n     63
+       *       +0100
+*/
+
+       auto c,snlflg,nlflg,t,smode,m,ssmode;
+       extern fin;
+
+       smode = nlflg = snlflg = ssmode = 0;
+       if (argc>1)
+               if ((fin = open(argv[1], 0)) < 0) {
+                       putchar('?\n');
+                       return;
+               }
+       obuf[0] = 1;
+       if (argc>2) 
+               if ((obuf[0] = creat(argv[2], 0666)) < 0) {
+                       putchar('?\n');
+                       return;
+               }
+loop:
+       c = getc();
+       if (c!='\n' && c!='\t') nlflg = 0;
+       if (ssmode!=0 && c!='%') {
+               ssmode = 0;
+               printf(".data\nL%d:<", labno++);
+       }
+       switch(c) {
+
+       case '\0':
+               printf(".text; 0\n");
+               fflush(obuf);
+               return;
+
+       case ':':
+               if (!smode)
+                       printf("=.+2; 0"); else
+                       putchar(':');
+               goto loop;
+
+       case 'A':
+               if ((c=getc())=='1' || c=='2') {
+                       putchar(c+'A'-'1');
+                       goto loop;
+               }
+               putchar('O');
+               peekc = c;
+               goto loop;
+
+       case 'B':
+               switch (getc()) {
+
+               case '1':
+                       putchar('C');
+                       goto loop;
+
+               case '2':
+                       putchar('D');
+                       goto loop;
+
+               case 'E':
+                       putchar('L');
+                       goto loop;
+
+               case 'F':
+                       putchar('P');
+                       goto loop;
+               }
+               putchar('?');
+               goto loop;
+
+       case 'C':
+               putchar(getc()+'E'-'1');
+               goto loop;
+
+       case 'F':
+               putchar('G');
+               goto subtre;
+
+       case 'R':
+               if ((c=getc()) == '1')
+               putchar('J'); else {
+                       putchar('I');
+                       peekc = c;
+               }
+               goto loop;
+
+       case 'H':
+               putchar('H');
+               goto subtre;
+
+       case 'I':
+               putchar('M');
+               goto loop;
+
+       case 'S':
+               putchar('K');
+subtre:
+               snlflg = 1;
+               t = 'A';
+l1:
+               switch (c=getc()) {
+
+               case '*':
+                       t++;
+                       goto l1;
+
+               case 'S':
+                       t =+ 2;
+                       goto l1;
+
+               case 'C':
+                       t =+ 4;
+                       goto l1;
+
+               case '1':
+                       t =+ 8;
+                       goto l1;
+
+               case '2':
+                       t =+ 16;
+                       goto l1;
+               }
+               peekc = c;
+               putchar(t);
+               goto loop;
+
+       case '#':
+               if(getc()=='1')
+                       putchar('#'); else
+                       putchar('"');
+               goto loop;
+
+       case '%':
+               if (smode)
+                       printf(".text;");
+               if (ssmode==0) {
+                       if ((peekc=getc())=='[') {
+                               peekc = 0;
+                               printf(".data;");
+                               while((c=getc())!=']')
+                                       putchar(c);
+                               getc();
+                               printf(";.text;");
+                               goto loop;
+                       }
+               }
+loop1:
+               switch (c=getc()) {
+
+               case ' ':
+               case '\t':
+                       goto loop1;
+               case 'a':
+                       m = 16;
+                       t = flag();
+                       goto pf;
+
+               case ',':
+                       putchar(';');
+                       goto loop1;
+
+               case 'i':
+                       m = 12;
+                       t = flag();
+                       goto pf;
+               case 'z':
+                       m = 4;
+                       t = flag();
+                       goto pf;
+
+               case 'r':
+                       m = 9;
+                       t = flag();
+                       goto pf;
+
+               case '1':
+                       m = 5;
+                       t = flag();
+                       goto pf;
+
+               case 'c':
+                       t = 0;
+                       m = 8;
+                       goto pf;
+
+               case 'e':
+                       t = flag();
+                       m = 20;
+                       goto pf;
+
+               case 'n':
+                       t = flag();
+                       m = 63;
+pf:
+                       if ((c=getc())=='*')
+                               m =+ 0100; else
+                               peekc = c;
+                       printf(".byte %o,%o", m, t);
+                       goto loop1;
+               case '[':
+                       printf("L%d=", labno++);
+                       while ((c=getc())!=']')
+                               putchar(c);
+                       ssmode = 0;
+                       smode = 0;
+                       goto loop;
+
+               case '\n':
+                       printf("\nL%d\n", labno);
+                       ssmode = 1;
+                       nlflg = 1;
+                       smode = 1;
+                       goto loop;
+               }
+               putchar(c);
+               goto loop1;
+
+       case '\t':
+               if (nlflg) {
+                       nlflg = 0;
+                       goto loop;
+               }
+               if (smode) {
+                       tabflg++;
+                       goto loop;
+               }
+               putchar('\t');
+               goto loop;
+
+       case '\n':
+               if (!smode)  {
+                       putchar('\n');
+                       goto loop;
+               }
+               if (nlflg) {
+                       nlflg = 0;
+                       printf("\\0>\n.text\n");
+                       smode = 0;
+                       goto loop;
+               }
+               if (!snlflg)
+                       printf("\\n");
+               snlflg = 0;
+               printf(">\n<");
+               nlflg = 1;
+               goto loop;
+
+       case 'X':
+       case 'Y':
+       case 'T':
+               snlflg++;
+       }
+       putchar(c);
+       goto loop;
+}
+
+getc() {
+       auto t, ifcnt;
+
+       ifcnt = 0;
+gc:
+       if (peekc) {
+               t = peekc;
+               peekc = 0;
+       } else
+               t = getchar();
+       if (t==0)
+               return(0);
+       if (t=='{') {
+               ifcnt++;
+               t = getchar();
+       }
+       if (t=='}') {
+               t = getc();
+               if (--ifcnt==0)
+                       if (t=='\n')
+                               t = getc();
+       }
+       if (ifcnt && nofloat)
+               goto gc;
+       return(t);
+}
+
+flag() {
+       register c, f;
+
+       f = 0;
+l1:
+       switch(c=getc()) {
+
+       case 'w':
+               f = 1;
+               goto l1;
+
+       case 'i':
+               f = 2;
+               goto l1;
+
+       case 'b':
+               f = 3;
+               goto l1;
+
+       case 'f':
+               f = 4;
+               goto l1;
+
+       case 'd':
+               f = 5;
+               goto l1;
+
+       case 's':
+               f = 6;
+               goto l1;
+
+       case 'l':
+               f = 8;
+               goto l1;
+
+       case 'p':
+               f =+ 16;
+               goto l1;
+       }
+       peekc = c;
+       return(f);
+}
+
+putchar(c)
+{
+       if (tabflg) {
+               tabflg = 0;
+               printf(">;.byte %o;<", c+0200);
+       } else
+               putc(c, obuf);
+}
diff --git a/usr/source/c/table.s b/usr/source/c/table.s
new file mode 100644 (file)
index 0000000..748563f
--- /dev/null
@@ -0,0 +1,1255 @@
+/
+/ c code tables-- compile to register
+/
+
+.globl _regtab
+
+.data
+_regtab=.
+       106.;   cr106
+       30.;    cr70
+       31.;    cr70
+       32.;    cr32
+       33.;    cr32
+       37.;    cr37
+       38.;    cr37
+       98.;    cr100
+       99.;    cr100
+       80.;    cr80
+       40.;    cr40
+       41.;    cr40    / - like +
+       42.;    cr42
+       43.;    cr43
+       44.;    cr43
+       45.;    cr45
+       46.;    cr40
+       55.;    cr40
+       48.;    cr40
+       49.;    cr49
+       70.;    cr70
+       71.;    cr70
+       72.;    cr72
+       73.;    cr73
+       74.;    cr74
+       75.;    cr75
+       76.;    cr72
+       78.;    cr70
+       85.;    cr70
+       79.;    cr79
+       102.;   cr102
+       51.;    cr51
+       52.;    cr52
+       56.;    cr56
+       57.;    cr57
+       58.;    cr58
+       59.;    cr59
+       91.;    cr91
+       82.;    cr82
+       83.;    cr82
+       84.;    cr82
+       86.;    cr86
+       87.;    cr86
+       88.;    cr86
+       0
+.text
+
+/ goto
+cr102:
+%a,n
+       jmp     A1
+
+%n*,n
+       F*
+       jmp     #1(R)
+
+/ call
+cr100:
+%a,n
+       jsr     pc,IA1
+
+%n*,n
+       F*
+       jsr     pc,#1(R)
+
+%n,n
+       F
+       jsr     pc,(R)
+
+/ addressible
+cr106:
+%z,n
+       clr     R
+
+%zf,n
+       clrf    R
+
+%a,n
+%ad,n
+       movB1   A1,R
+
+%af,n
+       movof   A1,R
+
+%n*,n
+%nd*,n
+       F*
+       movB1   #1(R),R
+
+%nf*,n
+       F*
+       movof   #1(R),R
+
+%al,n
+       mov     A1+,R+
+       mov     A1,R
+
+%nl*,n
+       F*
+       mov     #1+2(R),R+
+       mov     #1(R),R
+
+/ ++,-- postfix
+cr32:
+%a,1
+       movB1   A1',R
+       I'B1    A1
+
+%aw,n
+       mov     A1',R
+       I       A2,A1
+
+%e*,1
+       F1*
+       movB1   #1(R1),R
+       I'B1    #1(R1)
+
+%n*,1
+       F*
+       movB1   #1(R),-(sp)
+       I'B1    #1(R)
+       movB1   (sp)+,R
+
+%ew*,n
+       F1*
+       mov     #1(R1),R
+       I       A2,#1(R1)
+
+%nw*,n
+       F*
+       mov     #1(R),-(sp)
+       I       A2,#1(R)
+       mov     (sp)+,R
+
+%al,1
+       F
+       I       $1,A1+
+       V       A1
+
+%el*,1
+       F1*
+       mov     #1+2(R1),R+
+       mov     #1(R1),R
+       I       $1,#1+2(R1)
+       V       #1(R1)
+
+%nl*,1
+       F*
+       mov     #1+2(R),-(sp)
+       mov     #1(R),-(sp)
+       add     $1,#1+2(R)
+       V       #1(R)
+       mov     (sp)+,R
+       mov     (sp)+,R+
+
+/ - unary, ~
+cr37:
+%n,n
+%nf,n
+       F
+       IBF     R
+
+%nl,n
+       F
+       I       R
+       I       R+
+       V       R
+
+/ =
+cr80:
+%a,n
+%ad,nf
+       S
+       movB1   R,A1
+
+%af,nf
+       S
+       movfo   R,A1
+
+%nd*,af
+       F*
+       S
+       movf    R,#1(R)
+
+%n*,a
+       F*
+       movB1   A2,#1(R)
+       movB1   #1(R),R
+
+%nf*,af
+       F*
+       S
+       movfo   R,#1(R)
+
+%n*,e
+       F*
+       S1
+       movB1   R1,#1(R)
+       movB1   R1,R
+
+%ed*,nf
+       S
+       F1*
+       movf    R,#1(R1)
+
+%ef*,nf
+       S
+       F1*
+       movfo   R,#1(R1)
+
+%n*,n
+%nd*,nf
+       FS*
+       S
+       movB1   R,*(sp)+
+
+%nf*,nf
+       FS*
+       S
+       movfo   R,*(sp)+
+
+/ +, -, |, &~, <<
+cr40:
+%n,z
+       F
+
+%n,1
+       F
+       I'      R
+
+%[add1:]
+%n,aw
+%nf,ad
+       F
+       IB2     A2,R
+
+%[add2:]
+%n,ew*
+%nf,ed*
+       F
+       S1*
+       IB2     #2(R1),R
+
+%[add3:]
+%n,e
+%nf,ef
+       F
+       S1
+       IBF     R1,R
+
+%[add4:]
+%n,nw*
+%nf,nd*
+       SS*
+       F
+       IB2     *(sp)+,R
+
+%[add5:]
+%n,n
+%nf,nf
+       SS
+       F
+       IBF     (sp)+,R
+
+%nl,c
+       F
+       I       A2,R+
+       V       R
+
+%nl,al
+       F
+       I       A2,R
+       I       A2+,R+
+       V       R
+
+%nl,el
+       F
+       S1
+       I       R1+,R+
+       V       R
+       I       R1,R
+
+%nl,nl
+       SS
+       F
+       I       (sp)+,R
+       I       (sp)+,R+
+       V       R
+
+/ ^ -- xor
+cr49:
+%n,e
+%      [add3]
+
+%n,n
+       FS
+       S
+       xor     R,(sp)
+       mov     (sp)+,R
+
+/ >> (all complicated cases taken care of by << -)
+cr45:
+%n,1
+       F
+       asr     R
+
+/ * -- R must be odd on integers
+cr42:
+%n,aw
+%nf,ad
+%      [add1]
+
+%n,ew*
+%nf,ed*
+%      [add2]
+
+%n,e
+%nf,ef
+%      [add3]
+
+%n,n
+%nf,nf
+%      [add5]
+
+/ / R must be odd on integers
+cr43:
+%n,aw
+       F
+       T
+       sxt     R-
+       div     A2,R-
+
+%n,ew*
+       F
+       T
+       sxt     R-
+       S1*
+       div     #2(R1),R-
+
+%n,e
+       F
+       T
+       sxt     R-
+       S1
+       div     R1,R-
+
+%n,n
+       SS
+       F
+       T
+       sxt     R-
+       div     (sp)+,R-
+
+%nf,ad
+%      [add1]
+
+%nf,ed*
+%      [add2]
+
+%nf,ef
+%      [add3]
+
+%nf,nf
+%      [add5]
+
+/ =+, =-, =|, =&~
+cr70:
+%[addq1:]
+%aw,aw
+       I       A2,A1'
+       mov     A1,R
+
+%[addq1a:]
+%a,aw
+%ad,ad
+       movB1   A1',R
+       IBF     A2,R
+       movB1   R,A1
+
+%[addq2:]
+%aw,nw*
+       S*
+       I       #2(R),A1'
+       mov     A1,R
+
+%[addq3:]
+%aw,n
+       S
+       I       R,A1'
+       mov     A1,R
+
+%[addq4:]
+%ew*,nw*
+       S*
+       F1*
+       I       #2(R),#1(R1)
+       mov     #1(R1),R
+
+%[addq4a:]
+%ad,ef
+       movf    A1',R
+       S1
+       IBF     R1,R
+       movf    R,A1
+
+%[addq5:]
+%a,n
+%ad,nf
+       SS
+       movB1   A1',R
+       IBF     (sp)+,R
+       movB1   R,A1
+
+%[addq6:]
+%af,nf
+       SS
+       movof   A1',R
+       IBF     (sp)+,R
+       movfo   R,A1
+
+%[addq7:]
+%ew*,n
+       S
+       F1*
+       I       R,#1(R1)
+       mov     #1(R1),R
+
+%[addq8:]
+%nw*,n
+       SS
+       F*
+       I       (sp)+,#1(R)
+       mov     #1(R),R
+
+%[addq9:]
+%n*,n
+       FS*
+       SS
+       movB1   *2(sp),R
+       IBF     (sp)+,R
+       movB1   R,*(sp)+
+
+%[addq9a:]
+%nd*,nf
+       SS
+       F*
+       movB1   #1(R),R
+       IBF     (sp)+,R
+       movB1   R,#1(R)
+
+%[addq10:]
+%nf*,nf
+       SS
+       F*
+       movof   #1(R),R1
+       IBF     (sp)+,R1
+       movfo   R1,#1(R)
+       movf    R1,R
+
+/ =*, =<< (for integer multiply, R must be odd)
+cr72:
+%a,aw
+%ad,ad
+%      [addq1a]
+
+%af,nf
+%      [addq6]
+
+%ad,ef
+%      [addq4a]
+
+%a,n
+%ad,nf
+%      [addq5]
+
+%n*,n
+%      [addq9]
+
+%nd*,nf
+%      [addq9a]
+
+%nf*,nf
+%      [addq10]
+
+/ =/ ;  R must be odd on integers
+cr73:
+%a,aw
+       movB1   A1',R
+       sxt     R-
+       divBF   A2,R-
+       movB1   R-,A1
+
+%a,n
+       SS
+       movB1   A1',R
+       sxt     R-
+       div     (sp)+,R-
+       movB1   R-,A1
+
+%e*,n
+       SS
+       F1*
+       movB1   #1(R1),R
+       sxt     R-
+       div     (sp)+,R-
+       movB1   R-,#1(R1)
+
+%n*,n
+       FS*
+       SS
+       movB1   *2(sp),R
+       sxt     R-
+       div     (sp)+,R-
+       movB1   R-,*(sp)+
+
+%ad,ad
+%      [addq1a]
+
+%ad,ef
+%      [addq4a]
+
+%ad,nf
+%      [addq5]
+
+%af,nf
+%      [addq6]
+
+%nd*,nf
+%      [addq9a]
+
+%nf*,nf
+%      [addq10]
+
+/ =mod; R must be odd on integers
+cr74:
+%a,aw
+       movB1   A1',R
+       sxt     R-
+       div     A2,R-
+       movB1   R,A1
+
+%a,n
+       SS
+       movB1   A1',R
+       sxt     R-
+       div     (sp)+,R-
+       movB1   R,A1
+
+%e*,n
+       SS
+       F1*
+       movB1   #1(R1),R
+       sxt     R-
+       div     (sp)+,R-
+       movB1   R,#1(R1)
+
+%n*,n
+       FS*
+       SS
+       movB1   *2(sp),R
+       sxt     R-
+       div     (sp)+,R-
+       mov     R,*(sp)+
+
+/ =^ -- =xor
+cr79:
+%aw,n
+%      [addq3]
+
+%ab,n
+       SS
+       movb    A1',R
+       xor     R,(sp)
+       mov     (sp)+,R
+       movb    R,A1
+
+%n*,n
+       FS*
+       movB1   *(sp),-(sp)
+       S
+       xor     R,(sp)
+       movB1   (sp)+,R
+       movB1   R,*(sp)+
+
+/ =>> (all complicated cases done by =<< -)
+cr75:
+%a,1
+       asrB1   A1'
+       movB1   A1,R
+
+%n*,1
+       F*
+       asrB1   #1(R)
+       movB1   #1(R),R
+
+/ << for longs
+cr91:
+%nl,aw
+%      [add1]
+
+%nl,ew*
+%      [add2]
+
+%nl,e
+%      [add3]
+
+%nl,nw*
+%      [add4]
+
+%nl,n
+%      [add5]
+
+/ int -> float
+cr51:
+%aw,n
+       movif   A1,R
+
+%nw*,n
+       F*
+       movif   #1(R),R
+
+%n,n
+       F
+       movif   R,R
+
+/ float, double -> int
+cr52:
+%nf,n
+       F
+       movfi   R,R
+
+/ double (float) to long
+cr56:
+%nf,n
+       F
+       setl
+       movfi   R,-(sp)
+       mov     (sp)+,R
+       mov     (sp)+,R+
+       seti
+
+/ long to double
+cr57:
+%al,n
+       setl
+       movif   A1,R
+       seti
+
+%nl*,n
+       F*
+       setl
+       movif   #1(R),R
+       seti
+
+%nl,n
+       FS
+       setl
+       movif   (sp)+,R
+       seti
+
+/ integer to long
+cr58:
+%n,n
+       F1!
+       sxt     R
+
+/ long to integer
+cr59:
+%al,n
+       mov     A1+,R
+
+%nl*,n
+       F*
+       mov     #1+2(R),R
+
+%nl,n
+       F
+       mov     R+,R
+
+/ *, /, remainder for longs.
+cr82:
+%nl,nl
+       SS
+       FS
+       jsr     pc,I
+       add     $10,sp
+
+/ =*, =/, =rem for longs
+/ Operands of the form &x op y, so stack space is known.
+cr86:
+%n,nl
+       SS
+       FS
+       jsr     pc,I
+       add     $6,sp
+
+/
+/ c code tables -- compile for side effects.
+/ Also set condition codes properly (except for ++, --)
+/
+
+.globl _efftab
+
+.data
+_efftab=.
+       30.;    ci70
+       31.;    ci70
+       32.;    ci70
+       33.;    ci70
+       80.;    ci80
+       70.;    ci70
+       71.;    ci70    / - like +
+       78.;    ci78
+       85.;    ci78
+       75.;    ci75
+       76.;    ci76
+       92.;    ci92
+       0
+.text
+
+/ =
+ci80:
+%[move1:]
+%a,z
+%ad,zf
+       I'B1    A1
+
+%[move2:]
+%n*,z
+%nd*,zf
+       F*
+       I'B1    #1(R)
+
+%[move3:]
+%a,aw
+%ab,a
+       IBE     A2,A1
+
+%[move4:]
+%ab,n*
+%a,nw*
+       S*
+       IBE     #2(R),A1
+
+%[move5:]
+%a,n
+       S
+       IB1     R,A1
+
+%[move6:]
+%n*,aw
+%nb*,a
+       F*
+       IBE     A2,#1(R)
+
+%[move7:]
+%n*,ew*
+%nb*,e*
+       F*
+       S1*
+       IBE     #2(R1),#1(R)
+
+%[move8:]
+%n*,e
+       F*
+       S1
+       IB1     R1,#1(R)
+
+%[move9:]
+%e*,nw*
+%eb*,n*
+       S*
+       F1*
+       IBE     #2(R),#1(R1)
+
+%[move10:]
+%e*,n
+       S
+       F1*
+       IB1     R,#1(R1)
+
+%[move11:]
+%n*,nw*
+%nb*,n*
+       FS*
+       S*
+       IBE     #2(R),*(sp)+
+
+%[move12:]
+%n*,n
+       FS*
+       S
+       IB1     R,*(sp)+
+
+%al,z
+       clr     A1
+       clr     A1+
+
+%al,aw
+       mov     A2,A1+
+       sxt     A1
+
+%al,nw*
+       mov     #2(R),A1+
+       sxt     A1
+
+%al,n
+       S
+       mov     R,A1+
+       sxt     A1
+
+%al,nf
+       S
+       setl
+       movfi   R,A1
+       seti
+
+%el*,nf
+       S
+       F1*
+       setl
+       movfi   R,#1(R1)
+       seti
+
+%[move13a:]
+%al,c
+       I       A2,A1+
+       V       A1
+
+%[move13:]
+%al,al
+       I       A2,A1
+       I       A2+,A1+
+       V       A1
+
+%[move14:]
+%al,nl*
+       S*
+       I       #2(R),A1
+       I       #2+2(R),A1+
+       V       A1
+
+%[move14a:]
+%nl*,c
+       F*
+       I       A2,2+#1(R)
+       V       #1(R)
+
+%[move15:]
+%al,nl
+       S
+       I       R,A1
+       I       R+,A1+
+       V       A1
+
+%nl*,aw
+       F*
+       mov     A2,#1+2(R)
+       sxt     #1(R)
+
+%[move16:]
+%el*,nl
+       S
+       F1*
+       I       R+,#1+2(R1)
+       V       #1(R1)
+       I       R,#1(R1)
+
+%nl*,n
+       SS
+       F*
+       mov     (sp)+,#1+2(R)
+       sxt     #1(R)
+
+%[move17:]
+%nl*,nl
+       SS
+       F*
+       I       (sp)+,#1(R)
+       I       (sp)+,#1+2(R)
+       V       #1(R)
+
+/ =| and =& ~
+ci78:
+%a,a
+%      [move3]
+
+%a,n
+%      [move5]
+
+%n*,a
+%      [move6]
+
+%n*,e*
+%      [move7]
+
+%n*,e
+%      [move8]
+
+%e*,n*
+%      [move9]
+
+%e*,n
+%      [move10]
+
+%n*,n*
+%      [move11]
+
+%n*,n
+%      [move12]
+
+%al,c
+%      [move13a]
+
+%al,al
+%      [move13]
+
+%al,nl*
+%      [move14]
+
+%al,nl
+%      [move15]
+
+%nl*,c
+%      [move14a]
+
+%el*,nl
+%      [move16]
+
+%nl*,nl
+%      [move17]
+
+/ =+
+ci70:
+%n*,z
+%a,z
+
+%a,1
+       I'B1    A1
+
+%aw,aw
+%      [move3]
+
+%aw,nw*
+%      [move4]
+
+%aw,n
+%      [move5]
+
+%n*,1
+%      [move2]
+
+%ew*,nw*
+%      [move9]
+
+%a,nw*
+       S*
+       movB1   A1',R1
+       I       #2(R),R1
+       movB1   R1,A1
+
+%a,n
+       S
+       movB1   A1',R1
+       I       R,R1
+       movB1   R1,A1
+
+%ew*,n
+%      [move10]
+
+%nw*,n
+%      [move12]
+
+%n*,n
+       SS
+       F*
+       movB1   #1(R),R1
+       I       (sp)+,R1
+       movB1   R1,#1(R)
+
+%al,c
+%      [move13a]
+
+%al,al
+%      [move13]
+
+%al,nl*
+%      [move14]
+
+%al,nl
+%      [move15]
+
+%nl*,c
+%      [move14a]
+
+%el*,nl
+%      [move16]
+
+%nl*,nl
+%      [move17]
+
+/ =>> (all harder cases handled by =<< -)
+ci75:
+%a,1
+       asrB1   A1
+
+%n*,1
+       F*
+       asrB1   #1(R)
+
+/ =<<
+ci76:
+%a,1
+       aslB1   A1
+
+%n*,1
+       F*
+       aslB1   #1(R)
+
+%r,aw
+       ash     A2,A1
+
+%r,nw*
+       S*
+       ash     #2(R),A1
+
+%r,n
+       S
+       ash     R,A1
+
+/ =<< for longs
+ci92:
+%al,aw
+       F
+       ashc    A2,R
+       mov     R,A1
+       mov     R+,A1+
+
+%al,n
+       SS
+       F
+       ashc    (sp)+,R
+       mov     R,A1
+       mov     R+,A1+
+
+%nl*,n
+       FS*
+       SS
+       mov     2(sp),R
+       mov     2(R),R+
+       mov     (R),R
+       ashc    (sp)+,R
+       mov     R,*(sp)
+       mov     (sp)+,R
+       mov     R+,2(R)
+
+/
+/ c code tables-- set condition codes
+/
+
+.globl _cctab
+
+.data
+_cctab=.
+       106.;   cc60
+       28.;    rest
+       55.;    rest
+       34.;    rest
+       35.;    rest
+       36.;    rest
+       37.;    rest
+       40.;    rest
+       41.;    rest
+       42.;    rest
+       43.;    rest
+       45.;    rest
+       46.;    rest
+       81.;    cc81    / & as in "if ((a&b)==0)"
+       48.;    rest
+       60.;    cc60
+       61.;    cc60
+       62.;    cc60
+       63.;    cc60
+       64.;    cc60
+       65.;    cc60
+       66.;    cc60
+       67.;    cc60
+       68.;    cc60
+       69.;    cc60
+       72.;    rest
+       73.;    rest
+       79.;    rest
+       0
+.text
+
+/ relationals
+cc60:
+%a,z
+%ad,zf
+%      [move1]
+
+%af,z
+       movof   A1,R
+
+%n*,z
+%nd*,zf
+%      [move2]
+
+%nf*,z
+       F*
+       movof   #1(R),R
+
+%n,z
+%nf,zf
+       FC
+
+%aw,aw
+%ab,ab
+%      [move3]
+
+%nw*,aw
+%nb*,ab
+%      [move6]
+
+%n,aw
+%nf,ad
+%      [add1]
+
+%nw*,ew*
+%nb*,eb*
+%      [move7]
+
+%nw*,e
+%      [move8]
+
+%n,ew*
+%nf,ed*
+%      [add2]
+
+%n,e
+%nf,ef
+%      [add3]
+
+%nw*,nw*
+%nb*,nb*
+%      [move11]
+
+%nw*,n
+%      [move12]
+
+%n,n
+%nf,nf
+%      [add5]
+
+/ & as in "if ((a&b) ==0)"
+cc81:
+%a,a
+%      [move3]
+
+%n*,a
+%      [move6]
+
+%n,a
+%      [add1]
+
+%n,e
+%      [add3]
+
+%n,n
+%      [add5]
+
+/ set codes right
+rest:
+%n,n
+%nf,nf
+       H
+
+/
+/ c code tables-- expression to -(sp)
+/
+
+.globl _sptab
+
+.data
+_sptab=.
+       106.;   cs106
+       40.;    cs40
+       41.;    cs40
+       55.;    cs40
+       48.;    cs40
+       58.;    cs58
+       56.;    cs56
+       0
+.text
+
+
+/ name
+cs106:
+%z,n
+%zf,n
+       clrB1   -(sp)
+
+%aw,n
+       mov     A1,-(sp)
+
+%nw*,n
+       F*
+       mov     #1(R),-(sp)
+
+%al,n
+       mov     A1+,-(sp)
+       mov     A1,-(sp)
+
+/ +, -, |, &~
+cs40:
+%n,1
+       FS
+       I'      (sp)
+
+%n,aw
+       FS
+       I       A2,(sp)
+
+%n,nw*
+       FS
+       S*
+       I       #2(R),(sp)
+
+%n,n
+       FS
+       S
+       I       R,(sp)
+
+/ integer to long
+cs58:
+%n,n
+       FS
+       sxt     -(sp)
+
+/ float to long
+cs56:
+%nf,n
+       F
+       setl
+       movfi   R,-(sp)
+       seti
+