Add tests, fixes for tests, reinstate and type-convert stuff marked "bitrot"
[ccom.git] / c03.c
diff --git a/c03.c b/c03.c
index cc173bb..9a36b8b 100644 (file)
--- a/c03.c
+++ b/c03.c
@@ -5,6 +5,7 @@
  * externals.
  */
 
+#include <stdlib.h>
 #include <string.h>
 #include "c0.h"
 
  */
 int declist(sclass) int sclass; {
        register int sc, offset;
-       struct nmlist typer;
+ /*    struct nmlist typer;*/
+ struct type *dtype;
+ static struct type t_int = {INT};
 
        offset = 0;
        sc = sclass;
-       while (getkeywords(&sclass, &typer)) {
-               offset = declare(sclass, &typer, offset);
+       while (/*getkeywords(&sclass, &typer)*/(dtype = getkeywords(&sclass)) != NULL) {
+               offset = declare(sclass, /*&typer*/dtype, offset);
                sclass = sc;
        }
-       return(offset+align(INT, offset, 0));
+       return(offset+align(/*INT*/&t_int, offset, 0));
 }
 
 /*
@@ -29,28 +32,44 @@ int declist(sclass) int sclass; {
  * Store back the storage class, and fill in the type
  * entry, which looks like a hash table entry.
  */
-int getkeywords(scptr, tptr) int *scptr; struct nmlist *tptr; {
+/*int*/struct type *getkeywords(scptr/*, tptr*/) int *scptr; /*struct nmlist *tptr;*/ {
        register int skw, tkw, longf;
        int o, isadecl, ismos, unsignf;
+ struct type *dtype;
+ static struct type basic_types[] = {
+  {INT},
+  {CHAR},
+  {FLOAT},
+  {DOUBLE},
+  {STRUCT},
+  {RSTRUCT},
+  {LONG},
+  {UNSIGN},
+  {UNCHAR},
+  {UNLONG},
+  {VOID}
+ };
 
        isadecl = 0;
        longf = 0;
        unsignf = 0;
      tptr->htype = INT;
-       tptr->hstrp = NULL;
-       tptr->hsubsp = NULL;
/*    tptr->nl_type = INT;
+       tptr->nl_strp = NULL;
+       tptr->nl_subsp = NULL;*/
        tkw = -1;
        skw = *scptr;
        ismos = skw==MOS||skw==MOU? FMOS: 0;
+ dtype = NULL;
        for (;;) {
                mosflg = isadecl? ismos: 0;
                o = symbol();
-               if (o==NAME && csym->hclass==TYPEDEF) {
+               if (o==NAME && csym->nl_class==TYPEDEF) {
                        if (tkw >= 0)
                                error0("type clash");
-                       tkw = csym->htype;
-                       tptr->hsubsp = csym->hsubsp;
-                       tptr->hstrp = csym->hstrp;
+ /*                    tkw = csym->nl_type;
+                       tptr->nl_subsp = csym->nl_subsp;
+                       tptr->nl_strp = csym->nl_strp;*/
+ dtype = csym->nl_dtype;
                        isadecl++;
                        continue;
                }
@@ -78,6 +97,9 @@ int getkeywords(scptr, tptr) int *scptr; struct nmlist *tptr; {
                        break;
 
                case ENUM:
+ /* note: this code accepts silly declarations like "enum a int b;" */
+ /* it also accepts modifiers if placed later like "enum a long b;" */
+ /* eventually we should modify this to be more like the struct case */
                        if (longf || unsignf)
                                error0("Perverse modifier on 'enum'");
                        strdec(ismos, cval);
@@ -86,15 +108,23 @@ int getkeywords(scptr, tptr) int *scptr; struct nmlist *tptr; {
 
                case UNION:
                case STRUCT:
-                       tptr->hstrp = strdec(ismos, cval);
+ /*                    tptr->nl_strp = strdec(ismos, cval); */
+ if (dtype)
+  error0("type clash");
+ dtype = (struct type *)strdec(ismos, cval);
                        cval = STRUCT;
+ goto types_struct;
                case INT:
                case CHAR:
                case FLOAT:
                case DOUBLE:
                case VOID:
                types:
+ if (dtype)
+  goto type_clash;
+ types_struct:
                        if (tkw>=0 && (tkw!=INT || cval!=INT))
+ type_clash:
                                error0("Type clash");
                        tkw = cval;
                        if (unscflg && cval==CHAR)
@@ -104,12 +134,14 @@ int getkeywords(scptr, tptr) int *scptr; struct nmlist *tptr; {
                default:
                        peeksym = o;
                        if (isadecl==0)
-                               return(0);
+                               return(/*0*/NULL);
                        if (tkw<0)
                                tkw = INT;
                        if (skw==0)
                                skw = blklev==0? DEFXTRN: AUTO;
                        if (unsignf) {
+ if (dtype)
+  goto misplaced_unsigned;
                                if (tkw==INT)
                                        tkw = UNSIGN;
                                else if (tkw==CHAR)
@@ -117,9 +149,12 @@ int getkeywords(scptr, tptr) int *scptr; struct nmlist *tptr; {
                                else if (tkw==LONG)
                                        tkw = UNLONG;
                                else
+ misplaced_unsigned:
                                        error0("Misplaced 'unsigned'");
                        }
                        if (longf) {
+ if (dtype)
+  goto misplaced_long;
                                if (tkw==FLOAT)
                                        tkw = DOUBLE;
                                else if (tkw==INT)
@@ -127,11 +162,13 @@ int getkeywords(scptr, tptr) int *scptr; struct nmlist *tptr; {
                                else if (tkw==UNSIGN)
                                        tkw = UNLONG;
                                else
+ misplaced_long:
                                        error0("Misplaced 'long'");
                        }
                        *scptr = skw;
-                       tptr->htype = tkw;
-                       return(1);
+ /*                    tptr->nl_type = tkw;
+                       return(1);*/
+ return dtype ? dtype : basic_types + tkw;
                }
                isadecl++;
        }
@@ -141,18 +178,20 @@ int getkeywords(scptr, tptr) int *scptr; struct nmlist *tptr; {
  * Process a structure, union, or enum declaration; a subroutine
  * of getkeywords.
  */
-union str *strdec(mosf, kind) int mosf; int kind; {
+/*union str*/struct stype *strdec(mosf, kind) int mosf; int kind; {
        register int elsize, o;
        register struct nmlist *ssym;
        int savebits;
        struct nmlist **savememlist;
        union str *savesparent;
        int savenmems;
-       union str *strp;
+ /*    union str *strp;*/
+ struct stype *stype;
        struct nmlist *ds;
        struct nmlist *mems[NMEMS];
-       struct nmlist typer;
+ /*    struct nmlist typer;*/
        int tagkind;
+ static struct type t_int = {INT};
 
        if (kind!=ENUM) {
                tagkind = STRTAG;
@@ -168,30 +207,38 @@ union str *strdec(mosf, kind) int mosf; int kind; {
                ssym = csym;
                mosflg = mosf;
                o = symbol();
-               if (o==LBRACE && ssym->hblklev<blklev)
+               if (o==LBRACE && ssym->nl_blklev<blklev)
                        ssym = pushdecl(ssym);
-               if (ssym->hclass && ssym->hclass!=tagkind) {
+               if (ssym->nl_class && ssym->nl_class!=tagkind) {
                        defsym = ssym;
                        redec();
                        ssym = pushdecl(ssym);
                }
-               if (ssym->hclass==0) {
-                       ssym->hclass = tagkind;
-                       ssym->hstrp = (union str *)Dblock(sizeof(struct SS));
-                       ssym->hstrp->S.ssize = 0;
-                       ssym->hstrp->S.memlist = NULL;
+               if (ssym->nl_class==0) {
+                       ssym->nl_class = tagkind;
+ /*                    ssym->nl_strp = (union str *)Dblock(sizeof(struct SS));*/
+ stype = (struct stype *)Dblock(sizeof(struct stype));
+ stype->st_id = STRUCT;
+                       /*ssym->nl_strp->S.ssize*/stype->st_ssize = 0;
+                       /*ssym->nl_strp->S.memlist*/stype->st_memlist = NULL;
+ /*ssym->nl_strp = (union str *)&stype->st_S;*/
+ ssym->nl_dtype = (struct type *)stype;
                }
-               strp = ssym->hstrp;
+ /*            strp = ssym->nl_strp;*/
+ else
+  stype = (struct stype *)ssym->nl_dtype;
        } else {
-               strp = (union str *)Dblock(sizeof(struct SS));
-               strp->S.ssize = 0;
-               strp->S.memlist = NULL;
+ /*            strp = (union str *)Dblock(sizeof(struct SS));*/
+ stype = (struct stype *)Dblock(sizeof(struct stype));
+ stype->st_id = STRUCT;
+               /*strp->S.ssize*/stype->st_ssize = 0;
+               /*strp->S.memlist*/stype->st_memlist = NULL;
        }
        mosflg = 0;
        if (o != LBRACE) {
                if (ssym==0)
                        goto syntax;
-               if (ssym->hclass!=tagkind)
+               if (ssym->nl_class!=tagkind)
                        error0("Bad structure/union/enum name");
                peeksym = o;
        } else {
@@ -202,18 +249,19 @@ union str *strdec(mosf, kind) int mosf; int kind; {
                savesparent = sparent;
                savenmems = nmems;
                memlist = mems;
-               sparent = strp;
+               sparent = /*strp*/(union str *)&stype->st_S;
                nmems = 2;
                bitoffs = 0;
                if (kind==ENUM) {
-                       typer.htype = INT;
-                       typer.hstrp = strp;
-                       declare(ENUM, &typer, 0);
+ /*                    typer.nl_type = INT;
+                       typer.nl_strp = strp;*/
+ /* strp above seems to be vestigial, I don't think it is ever referenced */
+                       declare(ENUM, /*&typer*/&t_int, 0);
                } else
                        elsize = declist(kind==UNION?MOU:MOS);
                bitoffs = savebits;
 #if 1 /* just save a bit of string space */
-               if (strp->S.ssize) {
+               if (/*strp->S.ssize*/stype->st_ssize) {
                        defsym = ssym;
                        redec();
                }
@@ -221,20 +269,21 @@ union str *strdec(mosf, kind) int mosf; int kind; {
 #else
                defsym = ds;
                if (strp->S.ssize)
-                       error0("%s redeclared", ssym->name);
+                       error0("%s redeclared", ssym->nl_name);
 #endif
-               strp->S.ssize = elsize;
+               /*strp->S.ssize*/stype->st_ssize = elsize;
                *memlist++ = NULL;
-               strp->S.memlist = (struct nmlist **)Dblock((memlist-mems)*sizeof(*memlist));
+               /*strp->S.memlist*/stype->st_memlist = (struct nmlist **)Dblock((memlist-mems)*sizeof(*memlist));
                for (o=0; &mems[o] != memlist; o++)
-                       strp->S.memlist[o] = mems[o];
+                       /*strp->S.memlist*/stype->st_memlist[o] = mems[o];
                memlist = savememlist;
                sparent = savesparent;
                nmems = savenmems;
                if ((o = symbol()) != RBRACE)
                        goto syntax;
        }
-       return(strp);
+ /*fprintf(stderr, "stype=%p,%p\n", stype, &stype->st_S);*/
+       return(/*strp*/stype);
    syntax:
        decsyn(o);
        return(0);
@@ -243,10 +292,11 @@ union str *strdec(mosf, kind) int mosf; int kind; {
 /*
  * Process a comma-separated list of declarators
  */
-int declare(askw, tptr, offset) int askw; struct nmlist *tptr; int offset; {
+int declare(askw, tptr, offset) int askw; struct /*nmlist*/type *tptr; int offset; {
        register unsigned o;
        register int skw, isunion;
        struct nmlist abs, *aptr;
+ static struct type t_char = {CHAR};
 
        skw = askw;
        isunion = 0;
@@ -255,7 +305,7 @@ int declare(askw, tptr, offset) int askw; struct nmlist *tptr; int offset; {
                isunion++;
                mosflg = FMOS;
                if ((peeksym=symbol()) == SEMI) {
-                       o = length((union tree *)tptr);
+                       o = length(/*(struct node *)*/tptr);
                        if (o>offset)
                                offset = o;
                }
@@ -267,21 +317,22 @@ int declare(askw, tptr, offset) int askw; struct nmlist *tptr; int offset; {
                        break;
                }
                if (skw == MOS) {
-                       abs.hclass = 0;
-                       abs.hflag = 0;
-                       abs.htype = 0;
-                       abs.hsubsp = 0;
-                       abs.hstrp = 0;
-                       abs.nextnm = 0;
-                       abs.sparent = 0;
-                       abs.hblklev = blklev;
-                       abs.name = "<none>";
+                       abs.nl_class = 0;
+                       abs.nl_flag = 0;
+ /*                    abs.nl_type = 0;
+                       abs.nl_subsp = 0;
+                       abs.nl_strp = 0;*/
+ abs.nl_dtype = NULL;
+                       abs.nl_nextnm = 0;
+                       abs.nl_sparent = 0;
+                       abs.nl_blklev = blklev;
+                       abs.nl_name = "<none>";
                        aptr = &abs;
                } else
                        aptr = NULL;
                o = decl1(skw, tptr, isunion?0:offset, aptr);
                if (isunion) {
-                       o += align(CHAR, o, 0);
+                       o += align(/*CHAR*/&t_char, o, 0);
                        if (o>offset)
                                offset = o;
                } else
@@ -299,20 +350,116 @@ int declare(askw, tptr, offset) int askw; struct nmlist *tptr; int offset; {
 /*
  * Process a single declarator
  */
-int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offset; struct nmlist *absname; {
+/* convert detailed type description to old type description */
+void XXXdumptype(dtype) struct type *dtype; {
+ static char *basic_types[] = {
+  "INT",
+  "CHAR",
+  "FLOAT",
+  "DOUBLE",
+  "STRUCT",
+  "RSTRUCT",
+  "LONG",
+  "UNSIGN",
+  "UNCHAR",
+  "UNLONG",
+  "VOID",
+  "REF",
+  "BITFLD"
+ };
+ switch (dtype->t_id) {
+ case REF | PTR:
+  fprintf(stderr, "PTR");
+  goto reftype;
+ case REF | FUNC:
+#define fdtype ((struct ftype *)dtype)
+  fprintf(stderr, "FUNC");
+  /*if (fdtype->ft_arglist) {
+   int i;
+   fputc('(', stderr);
+   for (i = 0; fdtype->ft_arglist[i]; ++i) {
+    if (i)
+     fputc(',', stderr);
+    fprintf(stderr, "%s", fdtype->ft_arglist[i]->nl_name);
+   }
+   fputc(')', stderr);
+  }*/
+  goto reftype;
+#undef fdtype
+ case REF | ARRAY:
+  fprintf(stderr, "ARRAY(%d)", ((struct atype *)dtype)->at_nelt);
+ reftype:
+  fputc(',', stderr);
+  XXXdumptype(((struct rtype *)dtype)->rt_reftype);
+  break;
+ default:
+  fprintf(stderr, "%s", basic_types[dtype->t_id]);
+  break;
+ }
+}
+int XXXoldtype(dtype, dimp, strp) struct type *dtype; struct tdim *dimp; struct SS **strp; {
+ int type;
+ switch (dtype->t_id) {
+ case REF | PTR:
+  type = XXXoldtype(((struct rtype *)dtype)->rt_reftype, dimp, strp);
+  if (type & BIGTYPE) {
+   typov();
+   type = 0;
+  }
+  type = (type & TYPE) | (type & ~TYPE) << TYLEN | PTR;
+  break;
+ case REF | FUNC:
+  type = XXXoldtype(((struct ftype *)dtype)->ft_reftype, dimp, strp);
+  if (type & BIGTYPE) {
+   typov();
+   type = 0;
+  }
+  type = (type & TYPE) | (type & ~TYPE) << TYLEN | FUNC;
+  break;
+ case REF | ARRAY:
+  if (dimp->rank>=5) {
+   error0("Rank too large");
+   dimp->rank = 4;
+  }
+  dimp->dimens[dimp->rank++] = ((struct atype *)dtype)->at_nelt;
+  type = XXXoldtype(((struct atype *)dtype)->at_reftype, dimp, strp);
+  if (type & BIGTYPE) {
+   typov();
+   type = 0;
+  }
+  type = (type & TYPE) | (type & ~TYPE) << TYLEN | ARRAY;
+  break;
+ case STRUCT:
+  *strp = &((struct stype *)dtype)->st_S;
+  type = STRUCT;
+  break;
+ case BITFLD:
+  *strp = NULL;
+  type = UNSIGN;
+  break;
+ default:
+  *strp = NULL;
+  type = dtype->t_id;
+  break;
+ }
+ return type;
+}
+int decl1(askw, atptr, offset, absname) int askw; struct /*nmlist*/type *atptr; int offset; struct nmlist *absname; {
        int t1, a, elsize;
        register int skw;
-       int type;
+ struct rtype rtype, *tail;
+ /*    int type;*/
        register struct nmlist *dsym;
-       register struct nmlist *tptr;
-       struct tdim dim;
-       int *dp;
+ /*    register struct nmlist *tptr;
+       struct tdim dim;*/
+ /*struct SS *strp;
+       int *dp;*/
        int isinit;
 
        skw = askw;
-       tptr = atptr;
+ /*    tptr = atptr;*/
        mosflg = skw==MOS? FMOS: 0;
-       dim.rank = 0;
+ /*    dim.rank = 0;*/
        if (((peeksym=symbol())==SEMI || peeksym==RPARN) && absname==NULL)
                return(0);
        /*
@@ -325,24 +472,34 @@ int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offs
                        error0("Negative field width");
                        t1 = 0;
                }
-               elsize = align(tptr->htype, offset, t1);
+               elsize = align(/*tptr->nl_type*/atptr, offset, t1);
                bitoffs += t1;
                return(elsize);
        }
      t1 = getype(&dim, absname);
/*    t1 = getype(&dim, absname);
        if (t1 == -1)
-               return(0);
+               return(0);*/
+ /* we will construct a type which looks like a pointer to the real type, */
+ /* this is so that getype() can check the enclosing type, if REF | ARRAY */
+ /* then dimension must be specified, e.g. a[][10] is OK, but a[][] is not */
+ rtype.rt_id = REF | PTR;
+ tail = getype(&rtype, absname!=NULL);
+ if (tail)
+  tail->rt_reftype = atptr; /* otherwise, had error and set tail to int */
+ /*fprintf(stderr, "name %s type ", defsym ? defsym->nl_name : absname ? absname->nl_name : "???");
+ XXXdumptype(rtype.rt_reftype);
+ fprintf(stderr, "\n");*/
        if (defsym)
                absname = NULL;
      if (tptr->hsubsp) {
-               type = tptr->htype;
/*    if (tptr->nl_subsp) {
+               type = tptr->nl_type;
                for (a=0; type&XTYPE;) {
                        if ((type&XTYPE)==ARRAY)
-                               dim.dimens[dim.rank++] = tptr->hsubsp[a++];
+                               dim.dimens[dim.rank++] = tptr->nl_subsp[a++];
                        type >>= TYLEN;
                }
        }
-       type = tptr->htype & ~TYPE;
+       type = tptr->nl_type & ~TYPE;
        while (t1&XTYPE) {
                if (type&BIGTYPE) {
                        typov();
@@ -351,8 +508,8 @@ int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offs
                type = type<<TYLEN | (t1 & XTYPE);
                t1 >>= TYLEN;
        }
-       type |= tptr->htype&TYPE;
-       if ((type&XTYPE) == FUNC) {
+       type |= tptr->nl_type&TYPE;*/
+       if (/*(type&XTYPE) == FUNC*/rtype.rt_reftype->t_id == (REF | FUNC)) {
                if (skw==AUTO)
                        skw = EXTERN;
                if ((skw!=EXTERN && skw!=TYPEDEF) && absname==NULL)
@@ -367,14 +524,14 @@ int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offs
                return(0);
        }
        if (defsym)
-       if (dsym->hblklev<blklev || dsym->hclass==MOS && skw==MOS) {
-               if (skw==MOS && dsym->sparent==sparent)
+       if (dsym->nl_blklev<blklev || dsym->nl_class==MOS && skw==MOS) {
+               if (skw==MOS && dsym->nl_sparent==sparent)
                        redec();
                defsym = dsym;
                if (skw==EXTERN) {
-                       for (; dsym!=NULL; dsym = dsym->nextnm) {
-                               if (dsym->hclass==EXTERN
-                                && strcmp(dsym->name, defsym->name)==0) {
+                       for (; dsym!=NULL; dsym = dsym->nl_nextnm) {
+                               if (dsym->nl_class==EXTERN
+                                && strcmp(dsym->nl_name, defsym->nl_name)==0) {
                                        defsym = dsym;
                                        break;
                                }
@@ -383,26 +540,27 @@ int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offs
                } else
                        defsym = dsym = pushdecl(dsym);
        }
-       if (dim.rank == 0)
-               dsym->hsubsp = NULL;
+ /* old way */
+ /*    if (dim.rank == 0)
+               dsym->nl_subsp = NULL;
        else {
-               /*
+               *//*
                 * If an array is declared twice, make sure the declarations
                 * agree in dimension.  This happens typically when a .h
                 * and .c file both declare a variable.
-                */
-               if (dsym->hsubsp) {
-                       for (a=0, t1 = dsym->htype;
-                           a<dim.rank && (t1&XTYPE)==ARRAY;
+                *//*
+               if (dsym->nl_subsp) {
+                       for (a=0, t1 = dsym->nl_type;
+                           a<dim.rank && (t1&XTYPE)==ARRAY);
                            a++, t1 >>= TYLEN)
-                               /*
+                               *//*
                                 * If we haven't seen a declaration for this
                                 * dimension yet, take what's been given now.
-                                */
-                               if (!dsym->hsubsp[a])
-                                       dsym->hsubsp[a] = dim.dimens[a];
+                                *//*
+                               if (!dsym->nl_subsp[a])
+                                       dsym->nl_subsp[a] = dim.dimens[a];
                                else if (dim.dimens[a]
-                                   && dim.dimens[a] != dsym->hsubsp[a])
+                                   && dim.dimens[a] != dsym->nl_subsp[a])
                                        redec();
                        if (a<dim.rank || (t1&XTYPE)==ARRAY)
                                redec();
@@ -410,56 +568,114 @@ int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offs
                        dp = (int *)Dblock(dim.rank*sizeof(dim.rank));
                        for (a=0; a<dim.rank; a++)
                                dp[a] = dim.dimens[a];
-                       dsym->hsubsp = dp;
+                       dsym->nl_subsp = dp;
                }
        }
-       if (!(dsym->hclass==0
-          || ((skw==ARG||skw==AREG) && dsym->hclass==ARG1)
-          || (skw==EXTERN && dsym->hclass==EXTERN && dsym->htype==type))) {
+       if (!(dsym->nl_class==0
+          || ((skw==ARG||skw==AREG) && dsym->nl_class==ARG1)
+          || (skw==EXTERN && dsym->nl_class==EXTERN && dsym->nl_type==type))) {
                redec();
                goto syntax;
        }
-       if (dsym->hclass && (dsym->htype&TYPE)==STRUCT && (type&TYPE)==STRUCT)
-               if (dsym->hstrp != tptr->hstrp) {
+       if (dsym->nl_class && (dsym->nl_type&TYPE)==STRUCT && (type&TYPE)==STRUCT)
+               if (dsym->nl_strp != *//*tptr->nl_strp*//*(union str *)&((struct stype *)tptr)->st_S) {
                        error0("structure redeclaration");
                }
-       dsym->htype = type;
-       if (tptr->hstrp)
-               dsym->hstrp = tptr->hstrp;
+       dsym->nl_type = type;
+       if (tptr->nl_strp)
+               dsym->nl_strp = tptr->nl_strp;*/
+ /* new way */
+ if (skw==EXTERN && dsym->nl_class==EXTERN) {
+  /* got redeclaration of previously declared extern symbol */
+  /* compare types, picking up any new dimension information */
+  struct type *dt, *dt1;
+  for (
+   dt = rtype.rt_reftype, dt1 = dsym->nl_dtype;
+   (t1 = dt->t_id) == dt1->t_id;
+   dt=((struct rtype *)dt)->rt_reftype, dt1=((struct rtype *)dt1)->rt_reftype
+  )
+   switch (t1) {
+   case REF | PTR:
+   case FUNC | PTR:
+    break;
+   case REF | ARRAY:
+#define adt ((struct atype *)dt)
+#define adt1 ((struct atype *)dt1)
+    if (!adt1->at_nelt)
+     adt1->at_nelt = adt->at_nelt;
+    else if (adt->at_nelt && adt->at_nelt != adt1->at_nelt)
+     redec();
+    break;
+#undef adt
+#undef adt1
+   case STRUCT:
+    if (dt != dt1)
+     error0("structure redeclaration");
+    /* fallthru */
+   default:
+    goto done;
+   }
+  redec();
+ done:
+  ;
+ }
+ else if (dsym->nl_class==0 || (skw==ARG||skw==AREG) && dsym->nl_class==ARG1)
+  /* new declaration, or real declaration of K&R function argument */
+  /* just clobber the type, no type compatibility check needed */
+  dsym->nl_dtype = rtype.rt_reftype;
+ else {
+  redec();
+  goto syntax;
+ }
+ /*dim.rank = 0;
+ dsym->nl_type = XXXoldtype(dsym->nl_dtype, &dim, (struct SS **)&dsym->nl_strp);
+ if (dim.rank && dsym->nl_subsp == 0)
+  dsym->nl_subsp = (int *)Dblock(dim.rank*sizeof(dim.rank));
+ for (a=0; a<dim.rank; a++)
+  dsym->nl_subsp[a] = dim.dimens[a];*/
        if (skw==TYPEDEF) {
-               dsym->hclass = TYPEDEF;
+               dsym->nl_class = TYPEDEF;
                return(0);
        }
        if (skw==ARG1) {
                if (paraml==NULL)
                        paraml = dsym;
                else
-                       parame->sparent = (union str *)dsym;
+                       parame->nl_sparent = (union str *)dsym;
                parame = dsym;
-               dsym->hclass = skw;
+               dsym->nl_class = skw;
                return(0);
        }
        elsize = 0;
        if (skw==MOS) {
-               elsize = length((union tree *)dsym);
+ /*fprintf(stderr, "mos %p name %s\n", dsym, dsym->nl_name);*/
+               elsize = length(/*(struct node *)dsym*/dsym->nl_dtype);
                if ((peeksym = symbol())==COLON) {
                        elsize = 0;
                        peeksym = -1;
                        t1 = conexp();
-                       a = align(type, offset, t1);
-                       if (dsym->hflag&FFIELD) {
-                               if (dsym->hstrp->F.bitoffs!=bitoffs
-                                || dsym->hstrp->F.flen!=t1)
+                       a = align(/*type*/dsym->nl_dtype, offset, t1);
+ /*fprintf(stderr, "a bitfield strp %p\n", dsym->nl_strp);*/
+                       if (dsym->/*nl_flag&FFIELD*/nl_dtype->t_id == BITFLD) {
+                               if (/*dsym->nl_strp->F.bitoffs*/((struct btype *)dsym->nl_dtype)->bt_bitoffs!=bitoffs
+                                || /*dsym->nl_strp->F.flen*/((struct btype *)dsym->nl_dtype)->bt_flen!=t1)
                                        redec();
                        } else {
-                               dsym->hstrp = (union str *)Dblock(sizeof(struct FS));
+ /*                            dsym->nl_strp = (union str *)Dblock(sizeof(struct FS));*/
+ struct btype *btp = (struct btype *)Dblock(sizeof(struct btype));
+ btp->bt_id = BITFLD;
+ btp->bt_flen = t1;
+ btp->bt_bitoffs = bitoffs;
+ /*dsym->nl_strp = (union str *)&btp->bt_F;*/
+ dsym->nl_dtype = (struct type *)btp;
                        }
-                       dsym->hflag |= FFIELD;
-                       dsym->hstrp->F.bitoffs = bitoffs;
-                       dsym->hstrp->F.flen = t1;
+ /*fprintf(stderr, "b bitfield strp %p\n", dsym->nl_strp);*/
+ /*                    dsym->nl_flag |= FFIELD;
+                       dsym->nl_strp->F.bitoffs = bitoffs;
+                       dsym->nl_strp->F.flen = t1;*/
                        bitoffs += t1;
                } else
-                       a = align(type, offset, 0);
+                       a = align(/*type*/dsym->nl_dtype, offset, 0);
                elsize += a;
                offset += a;
                if (++nmems >= NMEMS) {
@@ -469,14 +685,14 @@ int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offs
                }
                if (a)
                        *memlist++ = &structhole;
-               dsym->hoffset = offset;
+               dsym->nl_offset = offset;
                *memlist++ = dsym;
-               dsym->sparent = sparent;
+               dsym->nl_sparent = sparent;
        }
        if (skw==REG)
-               if ((dsym->hoffset = goodreg(dsym)) < 0)
+               if ((dsym->nl_offset = goodreg(dsym)) < 0)
                        skw = AUTO;
-       dsym->hclass = skw;
+       dsym->nl_class = skw;
        isinit = 0;
        if ((a=symbol()) == ASSIGN)
                isinit++;
@@ -484,13 +700,15 @@ int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offs
                peeksym = a;
        if (skw==AUTO) {
        /*      if (STAUTO < 0) {       */
-                       autolen -= rlength((union tree *)dsym);
-                       dsym->hoffset = autolen;
+ /*fprintf(stderr, "%s autolen %d -> ", dsym->nl_name, autolen);*/
+                       autolen -= rlength(/*(struct node *)dsym*/dsym->nl_dtype);
+                       dsym->nl_offset = autolen;
                        if (autolen < maxauto)
                                maxauto = autolen;
+ /*fprintf(stderr, "%d maxauto %d\n", autolen, maxauto);*/
        /*      } else {                        */
-       /*              dsym->hoffset = autolen;        */
-       /*              autolen += rlength(dsym);       */
+       /*              dsym->nl_offset = autolen;      */
+       /*              autolen += rlength(*//*(struct node *)dsym*//*dsym->nl_dtype);  */
        /*              if (autolen > maxauto)          */
        /*                      maxauto = autolen;      */
        /*      }                       */
@@ -498,27 +716,27 @@ int decl1(askw, atptr, offset, absname) int askw; struct nmlist *atptr; int offs
                        cinit(dsym, 0, AUTO);
                isinit = 0;
        } else if (skw==STATIC) {
-               dsym->hoffset = isn0;
+               dsym->nl_offset = isn0;
                if (isinit) {
                        outcode("BBN", DATA, LABEL, isn0++);
                        if (cinit(dsym, 1, STATIC) & ALIGN)
                                outcode("B", EVEN);
                } else
                        outcode("BBNBN", BSS, LABEL, isn0++, SSPACE,
-                         rlength((union tree *)dsym));
+                         rlength(/*(struct node *)dsym*/dsym->nl_dtype));
                outcode("B", PROG);
                isinit = 0;
        } else if (skw==REG && isinit) {
                cinit(dsym, 0, REG);
                isinit = 0;
        } else if (skw==ENUM) {
-               if (type!=INT)
-                       error0("Illegal enumeration %s", dsym->name);
-               dsym->hclass = ENUMCON;
-               dsym->hoffset = offset;
+               if (/*type*/dsym->nl_dtype->t_id!=INT)
+                       error0("Illegal enumeration %s", dsym->nl_name);
+               dsym->nl_class = ENUMCON;
+               dsym->nl_offset = offset;
                if (isinit)
                        cinit(dsym, 0, ENUMCON);
-               elsize = dsym->hoffset-offset+1;
+               elsize = dsym->nl_offset-offset+1;
                isinit = 0;
        }
        if (absname==0)
@@ -538,16 +756,17 @@ struct nmlist *pushdecl(sp) register struct nmlist *sp; {
 
        nsp = (struct nmlist *)Dblock(sizeof(struct nmlist));
        *nsp = *sp;
-       nsp->hclass = 0;
-       nsp->hflag &= FKIND;
-       nsp->htype = 0;
-       nsp->hoffset = 0;
-       nsp->hblklev = blklev;
-       nsp->hstrp = NULL;
-       nsp->hsubsp = NULL;
-       nsp->sparent = NULL;
-       hsp = &hshtab[hash(sp->name)];
-       nsp->nextnm = *hsp;
+       nsp->nl_class = 0;
+       nsp->nl_flag &= FKIND;
+ /*    nsp->nl_type = 0;*/
+ nsp->nl_dtype = NULL;
+       nsp->nl_offset = 0;
+       nsp->nl_blklev = blklev;
+ /*    nsp->nl_strp = NULL;
+       nsp->nl_subsp = NULL;*/
+       nsp->nl_sparent = NULL;
+       hsp = &hshtab[hash(sp->nl_name)];
+       nsp->nl_nextnm = *hsp;
        *hsp = nsp;
        return(nsp);
 }
@@ -555,31 +774,43 @@ struct nmlist *pushdecl(sp) register struct nmlist *sp; {
 /*
  * Read a declarator and get the implied type
  */
-int getype(dimp, absname) register struct tdim *dimp; struct nmlist *absname; {
-       static struct nmlist argtype;
-       int type;
+/*int getype(dimp, absname) register struct tdim *dimp; struct nmlist *absname;*/ struct rtype *getype(tail, anonok) struct rtype *tail; int anonok; {
+ /*    static struct nmlist argtype;*/
+ static struct type t_int = {INT};
+ /*    int type;*/
+ struct rtype *newtail;
        register int o;
        register struct nmlist *ds;
 
        defsym = 0;
-       type = 0;
+ /*    type = 0;*/
        switch(o=symbol()) {
 
        case TIMES:
              type = getype(dimp, absname);
/*            type = getype(dimp, absname);
                if (type==-1)
-                       return(type);
-               if (type&BIGTYPE) {
+                       return(type);*/
+ tail = getype(tail, anonok);
+ if (tail==NULL)
+  return(NULL);
+ /*            if (type&BIGTYPE) {
                        typov();
                        type = 0;
                }
-               return(type<<TYLEN | PTR);
+               return(type<<TYLEN | PTR);*/
+ newtail = (struct rtype *)Dblock(sizeof(struct rtype));
+ newtail->rt_id = REF | PTR;
+ tail->rt_reftype = (struct type *)newtail;
+ return newtail;
 
        case LPARN:
-               if (absname==NULL || nextchar()!=')') {
                      type = getype(dimp, absname);
+               if (/*absname==NULL*/!anonok || nextchar()!=')') {
/*                    type = getype(dimp, absname);
                        if (type==-1)
-                               return(type);
+                               return(type);*/
+ tail = getype(tail, anonok);
+ if (tail==NULL)
+  return(NULL);
                        if ((o=symbol()) != RPARN)
                                goto syntax;
                        goto getf;
@@ -587,12 +818,12 @@ int getype(dimp, absname) register struct tdim *dimp; struct nmlist *absname; {
 
        default:
                peeksym = o;
-               if (absname)
+               if (/*absname*/anonok)
                        goto getf;
                break;
 
        case NAME:
-               defsym = ds = csym;
+               defsym = /*ds =*/ csym;
        getf:
                switch(o=symbol()) {
 
@@ -600,24 +831,31 @@ int getype(dimp, absname) register struct tdim *dimp; struct nmlist *absname; {
                        if (blklev==0) {
                                blklev++;
                                ds = defsym;
-                               declare(ARG1, &argtype, 0);
+                               declare(ARG1, &/*argtype*/t_int, 0);
                                defsym = ds;
                                blklev--;
                        } else
                                if ((o=symbol()) != RPARN)
                                        goto syntax;
                      if (type&BIGTYPE) {
/*                    if (type&BIGTYPE) {
                                typov();
                                type = 0;
                        }
-                       type = type<<TYLEN | FUNC;
+                       type = type<<TYLEN | FUNC;*/
+#define fnewtail (*(struct ftype **)&newtail)
+ fnewtail = (struct ftype *)Dblock(sizeof(struct ftype));
+ fnewtail->ft_id = REF | FUNC;
+ fnewtail->ft_arglist = NULL;
+ tail->rt_reftype = (struct type *)fnewtail;
+ tail = (struct rtype *)fnewtail;
+#undef fnewtail
                        goto getf;
 
                case LBRACK:
                      if (dimp->rank>=5) {
/*                    if (dimp->rank>=5) {
                                error0("Rank too large");
                                dimp->rank = 4;
-                       }
+                       }*/
                        if ((o=symbol()) != RBRACK) {
                                peeksym = o;
                                ds = defsym;
@@ -626,24 +864,35 @@ int getype(dimp, absname) register struct tdim *dimp; struct nmlist *absname; {
                                if ((o=symbol())!=RBRACK)
                                        goto syntax;
                        } else {
-                               if (dimp->rank!=0)
+ /*                            if (dimp->rank!=0)*/
+ if (tail->rt_id == (REF | ARRAY))
                                        error0("Null dimension");
                                cval = 0;
                        }
                      dimp->dimens[dimp->rank++] = cval;
/*                    dimp->dimens[dimp->rank++] = cval;
                        if (type&BIGTYPE) {
                                typov();
                                type = 0;
                        }
-                       type = type<<TYLEN | ARRAY;
+                       type = type<<TYLEN | ARRAY;*/
+#define anewtail (*(struct atype **)&newtail)
+ anewtail = (struct atype *)Dblock(sizeof(struct atype));
+ anewtail->at_id = REF | ARRAY;
+ anewtail->at_nelt = cval;
+ tail->rt_reftype = (struct type *)anewtail;
+ tail = (struct rtype *)anewtail;
+#undef anewtail
                        goto getf;
                }
                peeksym = o;
-               return(type);
+ /*            return(type);*/
+ return(tail);
        }
 syntax:
        decsyn(o);
-       return(-1);
+ /*    return(-1);*/
+ tail->rt_reftype = &t_int;
+ return(NULL);
 }
 
 /*
@@ -657,34 +906,39 @@ void typov() {
  * Enforce alignment restrictions in structures,
  * including bit-field considerations.
  */
-int align(type, offset, aflen) int type; int offset; int aflen; {
-       register int a, t, flen;
+/* really means make sure aflen bits can be allocated after current position */
+/* takes size in bytes and the global bitoffs, returns size increase in bytes */
+int align(type, offset, aflen) /*int*/struct type *type; int offset; int aflen; {
+       register int a, /*t,*/ flen;
+ register struct type *t;
        char *ftl;
 
        flen = aflen;
        a = offset;
-       t = type;
+ /*    t = type;*/
        ftl = "Field too long";
        if (flen==0) {
                a += (NBPC+bitoffs-1) / NBPC;
                bitoffs = 0;
        }
-       while ((t&XTYPE)==ARRAY)
-               t = decref0(t);
-       if (t!=CHAR && t!=UNCHAR) {
+ /*    while ((t&XTYPE)==ARRAY)
+               t = decref0(t);*/
+ for (t = type; t->t_id == (REF | ARRAY); t = ((struct atype *)t)->at_reftype)
+   ;
+       if (/*t*/t->t_id!=CHAR && /*t*/t->t_id!=UNCHAR) {
                a = (a+ALIGN) & ~ALIGN;
                if (a>offset)
                        bitoffs = 0;
        }
        if (flen) {
-               if (type==INT || type==UNSIGN) {
+               if (/*type*/type->t_id==INT || /*type*/type->t_id==UNSIGN) {
                        if (flen > NBPW)
                                error0(ftl);
                        if (flen+bitoffs > NBPW) {
                                bitoffs = 0;
                                a += NCPW;
                        }
-               } else if (type==CHAR || type==UNCHAR) {
+               } else if (/*type*/type->t_id==CHAR || /*type*/type->t_id==UNCHAR) {
                        if (flen > NBPC)
                                error0(ftl);
                        if (flen+bitoffs > NBPC) {
@@ -698,7 +952,7 @@ int align(type, offset, aflen) int type; int offset; int aflen; {
 }
 
 /*
- * Complain about syntax error0 in declaration
+ * Complain about syntax error in declaration
  */
 void decsyn(o) int o; {
        error0("Declaration syntax");
@@ -709,7 +963,7 @@ void decsyn(o) int o; {
  * Complain about a redeclaration
  */
 void redec() {
-       error0("%s redeclared", defsym->name);
+       error0("%s redeclared", defsym->nl_name);
 }
 
 /*
@@ -717,11 +971,13 @@ void redec() {
  * a register; if so return the register number
  */
 int goodreg(hp) struct nmlist *hp; {
-       int type;
+ /*    int type;*/
+ struct type *dtype;
 
-       type = hp->htype;
-       if ((type!=INT && type!=UNSIGN && (type&XTYPE)==0)
-        || (type&XTYPE)>PTR || regvar<3)
+ /*    type = hp->nl_type;*/
+ dtype = hp->nl_dtype;
+       if ((/*type*/dtype->t_id!=INT && /*type*/dtype->t_id!=UNSIGN && /*(type&XTYPE)==0*/dtype->t_id!=(REF|PTR))
+        || /*(type&XTYPE)>PTR ||*/ regvar<3)
                return(-1);
        return(--regvar);
 }