New target "hc08" for the Motorola 68hc08 family of micros
[fw/sdcc] / src / SDCCsymt.c
index 9d45864c5814029c7fda074b8fe012ac59b3c25e..35360f205052fbecca4a9b47538cd5220e1a60bc 100644 (file)
@@ -25,6 +25,7 @@
 #include "newalloc.h"
 
 value *aggregateToPointer (value *val);
+void printTypeChainRaw (sym_link * start, FILE * of);
 
 void printFromToType(sym_link *from, sym_link *to) {
   fprintf (stderr, "from type '");
@@ -48,6 +49,7 @@ char *nounName(sym_link *sl) {
     case V_VOID: return "void";
     case V_STRUCT: return "struct";
     case V_LABEL: return "label";
+    case V_BITFIELD: return "bitfield";
     case V_BIT: return "bit";
     case V_SBIT: return "sbit";
     case V_DOUBLE: return "double";
@@ -138,7 +140,7 @@ addSym (bucket ** stab,
   bp->sym = sym;               /* update the symbol pointer  */
   bp->level = level;           /* update the nest level      */
   bp->block = block;
-  strcpy (bp->name, sname);    /* copy the name into place */
+  strncpyz (bp->name, sname, sizeof(bp->name));        /* copy the name into place */
 
   /* if this is the first entry */
   if (stab[i] == NULL)
@@ -287,10 +289,10 @@ newSymbol (char *name, int scope)
 
   sym = Safe_alloc ( sizeof (symbol));
 
-  strcpy (sym->name, name);    /* copy the name    */
+  strncpyz (sym->name, name, sizeof(sym->name));       /* copy the name */
   sym->level = scope;          /* set the level    */
   sym->block = currBlockno;
-  sym->lineDef = yylineno;     /* set the line number */
+  sym->lineDef = mylineno;     /* set the line number */
   return sym;
 }
 
@@ -298,11 +300,12 @@ newSymbol (char *name, int scope)
 /* newLink - creates a new link (declarator,specifier)              */
 /*------------------------------------------------------------------*/
 sym_link *
-newLink ()
+newLink (SYM_LINK_CLASS select)
 {
   sym_link *p;
 
   p = Safe_alloc ( sizeof (sym_link));
+  p->class=select;
 
   return p;
 }
@@ -317,9 +320,40 @@ newStruct (char *tag)
 
   s = Safe_alloc ( sizeof (structdef));
 
-  strcpy (s->tag, tag);                /* copy the tag            */
+  strncpyz (s->tag, tag, sizeof(s->tag));              /* copy the tag */
   return s;
 }
+  
+/*------------------------------------------------------------------*/
+/* sclsFromPtr - Return the storage class a pointer points into.    */
+/*               S_FIXED is returned for generic pointers or other  */
+/*               unexpected cases                                   */
+/*------------------------------------------------------------------*/
+STORAGE_CLASS
+sclsFromPtr(sym_link *ptr)
+{
+  switch (DCL_TYPE (ptr))
+    {
+    case POINTER:
+      return S_DATA;
+    case GPOINTER:
+      return S_FIXED;
+    case FPOINTER:
+      return S_XDATA;
+    case CPOINTER:
+      return S_CODE;
+    case IPOINTER:
+      return S_IDATA;
+    case PPOINTER:
+      return S_PDATA;
+    case EEPPOINTER:
+      return S_EEPROM;
+    case FUNCTION:
+      return S_CODE;
+    default:
+      return S_FIXED;
+    }
+}
 
 /*------------------------------------------------------------------*/
 /* pointerTypes - do the computation for the pointer types          */
@@ -347,8 +381,6 @@ pointerTypes (sym_link * ptr, sym_link * type)
      storage class of the type */
   if (IS_SPEC (type))
     {
-      DCL_PTR_CONST (ptr) = SPEC_CONST (type);
-      DCL_PTR_VOLATILE (ptr) = SPEC_VOLATILE (type);
       switch (SPEC_SCLS (type))
        {
        case S_XDATA:
@@ -364,20 +396,17 @@ pointerTypes (sym_link * ptr, sym_link * type)
          DCL_TYPE (ptr) = POINTER;
          break;
        case S_CODE:
-         DCL_PTR_CONST (ptr) = port->mem.code_ro;
          DCL_TYPE (ptr) = CPOINTER;
          break;
        case S_EEPROM:
          DCL_TYPE (ptr) = EEPPOINTER;
          break;
        default:
-         DCL_TYPE (ptr) = GPOINTER;
+         DCL_TYPE (ptr) = port->unqualified_pointer;
          break;
        }
       /* the storage class of type ends here */
-      SPEC_SCLS (type) =
-       SPEC_CONST (type) =
-       SPEC_VOLATILE (type) = 0;
+      SPEC_SCLS (type) = 0;
     }
 
   /* now change all the remaining unknown pointers
@@ -385,7 +414,7 @@ pointerTypes (sym_link * ptr, sym_link * type)
   while (ptr)
     {
       if (!IS_SPEC (ptr) && DCL_TYPE (ptr) == UPOINTER)
-       DCL_TYPE (ptr) = GPOINTER;
+       DCL_TYPE (ptr) = port->unqualified_pointer;
       ptr = ptr->next;
     }
 
@@ -394,10 +423,9 @@ pointerTypes (sym_link * ptr, sym_link * type)
   while (type)
     {
       if (!IS_SPEC (type) && DCL_TYPE (type) == UPOINTER)
-       DCL_TYPE (type) = GPOINTER;
+       DCL_TYPE (type) = port->unqualified_pointer;
       type = type->next;
     }
-
 }
 
 /*------------------------------------------------------------------*/
@@ -422,7 +450,7 @@ addDecl (symbol * sym, int type, sym_link * p)
     }
   else
     {
-      head = tail = newLink ();
+      head = tail = newLink (DECLARATOR);
       DCL_TYPE (head) = type;
     }
 
@@ -467,12 +495,9 @@ addDecl (symbol * sym, int type, sym_link * p)
     {
       if (!IS_SPEC (sym->etype))
        {
-         sym->etype = sym->etype->next = newLink ();
-         sym->etype->class = SPECIFIER;
+         sym->etype = sym->etype->next = newLink (SPECIFIER);
        }
       SPEC_SCLS (sym->etype) = SPEC_SCLS (DCL_TSPEC (p));
-      SPEC_CONST (sym->etype) = SPEC_CONST (DCL_TSPEC (p));
-      SPEC_VOLATILE (sym->etype) = SPEC_VOLATILE (DCL_TSPEC (p));
       DCL_TSPEC (p) = NULL;
     }
 
@@ -508,7 +533,7 @@ void checkTypeSanity(sym_link *etype, char *name) {
   noun=nounName(etype);
 
   if (getenv("DEBUG_SANITY")) {
-    fprintf (stderr, "checking sanity for %s %x\n", name, (int)etype);
+    fprintf (stderr, "checking sanity for %s %p\n", name, etype);
   }
 
   if ((SPEC_NOUN(etype)==V_CHAR || 
@@ -557,8 +582,6 @@ void checkTypeSanity(sym_link *etype, char *name) {
 sym_link *
 mergeSpec (sym_link * dest, sym_link * src, char *name)
 {
-  sym_link *symlink=dest;
-
   if (!IS_SPEC(dest) || !IS_SPEC(src)) {
 #if 0
     werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "cannot merge declarator");
@@ -622,7 +645,9 @@ mergeSpec (sym_link * dest, sym_link * src, char *name)
   SPEC_BSTR (dest) |= SPEC_BSTR (src);
   SPEC_TYPEDEF (dest) |= SPEC_TYPEDEF (src);
   SPEC_ENUM (dest) |= SPEC_ENUM (src);
-
+  if (SPEC_ARGREG(src) && !SPEC_ARGREG(dest))
+      SPEC_ARGREG(dest) = SPEC_ARGREG(src);
+  
   if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL)
     SPEC_STRUCT (dest) = SPEC_STRUCT (src);
 
@@ -634,27 +659,13 @@ mergeSpec (sym_link * dest, sym_link * src, char *name)
   FUNC_ISREENT(dest) |= FUNC_ISREENT(src);
   FUNC_ISNAKED(dest) |= FUNC_ISNAKED(src);
   FUNC_ISISR(dest) |= FUNC_ISISR(src);
+  FUNC_ISJAVANATIVE(dest) |= FUNC_ISJAVANATIVE(src);
+  FUNC_ISBUILTIN(dest) |= FUNC_ISBUILTIN(src);
+  FUNC_ISOVERLAY(dest) |= FUNC_ISOVERLAY(src);
   FUNC_INTNO(dest) |= FUNC_INTNO(src);
   FUNC_REGBANK(dest) |= FUNC_REGBANK(src);
 
-  return symlink;
-}
-
-/*------------------------------------------------------------------*/
-/* cloneSpec - copies the entire spec and returns a new spec        */
-/*------------------------------------------------------------------*/
-sym_link *
-cloneSpec (sym_link * src)
-{
-  sym_link *spec;
-
-  /* go thru chain till we find the specifier */
-  while (src && src->class != SPECIFIER)
-    src = src->next;
-
-  spec = newLink ();
-  memcpy (spec, src, sizeof (sym_link));
-  return spec;
+  return dest;
 }
 
 /*------------------------------------------------------------------*/
@@ -666,7 +677,7 @@ genSymName (int level)
   static int gCount = 0;
   static char gname[SDCC_NAME_MAX + 1];
 
-  sprintf (gname, "__%04d%04d", level, gCount++);
+  SNPRINTF (gname, sizeof(gname), "__%04d%04d", level, gCount++);
   return gname;
 }
 
@@ -693,8 +704,7 @@ newCharLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_CHAR;
 
   return p;
@@ -708,8 +718,7 @@ newFloatLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_FLOAT;
 
   return p;
@@ -723,8 +732,7 @@ newLongLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_INT;
   SPEC_LONG (p) = 1;
 
@@ -739,8 +747,7 @@ newIntLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_INT;
 
   return p;
@@ -772,8 +779,9 @@ getSize (sym_link * p)
        case V_LABEL:
          return 0;
        case V_SBIT:
-         return BITSIZE;
        case V_BIT:
+         return BITSIZE;
+       case V_BITFIELD:
          return ((SPEC_BLEN (p) / 8) + (SPEC_BLEN (p) % 8 ? 1 : 0));
        default:
          return 0;
@@ -787,8 +795,8 @@ getSize (sym_link * p)
       if (DCL_ELEM(p)) {
        return DCL_ELEM (p) * getSize (p->next);
       } else {
-       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
-               "can not tell the size of an array[]");
+         //    werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+         //    "can not tell the size of an array[]");
        return 0;
       }
     case IPOINTER:
@@ -836,8 +844,9 @@ bitsForType (sym_link * p)
        case V_LABEL:
          return 0;
        case V_SBIT:
-         return 1;
        case V_BIT:
+         return 1;
+       case V_BITFIELD:
          return SPEC_BLEN (p);
        default:
          return 0;
@@ -985,13 +994,16 @@ addSymChain (symbol * symHead)
            werror (E_EXTERN_MISMATCH, csym->name);
            continue;
          }
-         /* delete current entry */
-         deleteSym (SymbolTab, csym, csym->name);
        } else {
          /* not extern */
-         werror (E_DUPLICATE, sym->name);
-         continue;
+         if (compareType (csym->type, sym->type) != 1) {
+           werror (E_DUPLICATE, sym->name);
+           continue;
+         }
        }
+       /* delete current entry */
+       deleteSym (SymbolTab, csym, csym->name);
+       deleteFromSeg(csym);
       }
 
       /* add new entry */
@@ -1016,7 +1028,7 @@ funcInChain (sym_link * lnk)
 }
 
 /*------------------------------------------------------------------*/
-/* structElemType - returns the type info of a sturct member        */
+/* structElemType - returns the type info of a struct member        */
 /*------------------------------------------------------------------*/
 sym_link *
 structElemType (sym_link * stype, value * id)
@@ -1025,25 +1037,31 @@ structElemType (sym_link * stype, value * id)
   sym_link *type, *etype;
   sym_link *petype = getSpec (stype);
 
-  if (!fields || !id)
-    return NULL;
+  if (fields && id) {
+    
+    /* look for the id */
+    while (fields)
+      {
+       if (strcmp (fields->rname, id->name) == 0)
+         {
+           type = copyLinkChain (fields->type);
+           etype = getSpec (type);
+           SPEC_SCLS (etype) = (SPEC_SCLS (petype) == S_REGISTER ?
+                                SPEC_SCLS (etype) : SPEC_SCLS (petype));
+            if (IS_SPEC (type))
+              SPEC_CONST (type) |= SPEC_CONST (stype);
+            else
+              DCL_PTR_CONST (type) |= SPEC_CONST (stype);
+           return type;
+         }
+       fields = fields->next;
+      }
+  }
 
-  /* look for the id */
-  while (fields)
-    {
-      if (strcmp (fields->rname, id->name) == 0)
-       {
-         type = copyLinkChain (fields->type);
-         etype = getSpec (type);
-         SPEC_SCLS (etype) = (SPEC_SCLS (petype) == S_REGISTER ?
-                              SPEC_SCLS (etype) : SPEC_SCLS (petype));
-         return type;
-       }
-      fields = fields->next;
-    }
   werror (E_NOT_MEMBER, id->name);
-
-  return NULL;
+    
+  // the show must go on
+  return newIntLink();
 }
 
 /*------------------------------------------------------------------*/
@@ -1078,63 +1096,89 @@ compStructSize (int su, structdef * sdef)
     while (loop) {
 
        /* create the internal name for this variable */
-       sprintf (loop->rname, "_%s", loop->name);
-       loop->offset = (su == UNION ? sum = 0 : sum);
+       SNPRINTF (loop->rname, sizeof(loop->rname), "_%s", loop->name);
+       if (su == UNION) {
+           sum = 0;
+           bitOffset = 0;
+       }
        SPEC_VOLATILE (loop->etype) |= (su == UNION ? 1 : 0);
 
        /* if this is a bit field  */
        if (loop->bitVar) {
 
            /* change it to a unsigned bit */
-           SPEC_NOUN (loop->etype) = V_BIT;
+           SPEC_NOUN (loop->etype) = V_BITFIELD;
            SPEC_USIGN (loop->etype) = 1;
-           /* check if this fit into the remaining   */
-           /* bits of this byte else align it to the */
-           /* next byte boundary                     */
-           if ((SPEC_BLEN (loop->etype) = loop->bitVar) <= (8 - bitOffset)) {
-               SPEC_BSTR (loop->etype) = bitOffset;
-               if ((bitOffset += (loop->bitVar % 8)) == 8)
-                   sum++;
-           }
-           else /* does not fit */ {
-               bitOffset = 0;
-               SPEC_BSTR (loop->etype) = bitOffset;
-               sum += (loop->bitVar / 8);
-               bitOffset += (loop->bitVar % 8);
+           SPEC_BLEN (loop->etype) = loop->bitVar;
+
+           if (loop->bitVar == BITVAR_PAD) {
+               /* A zero length bitfield forces padding */
+               SPEC_BSTR (loop->etype) = bitOffset;
+               SPEC_BLEN (loop->etype) = 0;
+               bitOffset = 8;
+               loop->offset = sum;
            }
-           /* if this is the last field then pad */
-           if (!loop->next && bitOffset && bitOffset != 8) {
-               bitOffset = 0;
-               sum++;
+           else {
+               if (bitOffset == 8) {
+                   bitOffset = 0;
+                   sum++;
+               }
+               /* check if this fit into the remaining   */
+               /* bits of this byte else align it to the */
+               /* next byte boundary                     */
+               if (loop->bitVar <= (8 - bitOffset)) {
+                   /* fits into current byte */
+                   loop->offset = sum;
+                   SPEC_BSTR (loop->etype) = bitOffset;
+                   bitOffset += loop->bitVar;
+               }
+               else if (!bitOffset) {
+                   /* does not fit, but is already byte aligned */
+                   loop->offset = sum;
+                   SPEC_BSTR (loop->etype) = bitOffset;
+                   bitOffset += loop->bitVar;
+               } 
+               else {
+                   /* does not fit; need to realign first */
+                   sum++;
+                   loop->offset = (su == UNION ? sum = 0 : sum);
+                   bitOffset = 0;
+                   SPEC_BSTR (loop->etype) = bitOffset;
+                   bitOffset += loop->bitVar;
+               }
+               while (bitOffset>8) {
+                   bitOffset -= 8;
+                   sum++;
+               } 
            }
        }
        else {
+           /* This is a non-bit field. Make sure we are */
+           /* byte aligned first */
+           if (bitOffset) {
+               sum++;
+               loop->offset = (su == UNION ? sum = 0 : sum);
+               bitOffset = 0;
+           }
+           loop->offset = sum;
            checkDecl (loop, 1);
            sum += getSize (loop->type);
        }
 
-#if 0 // jwk: this is done now in addDecl()
-       /* if function then do the arguments for it */
-       if (funcInChain (loop->type)) {
-           processFuncArgs (loop);
-       }
-#endif
-
        loop = loop->next;
 
-       /* if this is not a bitfield but the */
-       /* previous one was and did not take */
-       /* the whole byte then pad the rest  */
-       if ((loop && !loop->bitVar) && bitOffset) {
-           bitOffset = 0;
-           sum++;
-       }
-
        /* if union then size = sizeof larget field */
-       if (su == UNION)
+       if (su == UNION) {
+           /* For UNION, round up after each field */
+           sum += ((bitOffset+7)/8);
            usum = max (usum, sum);
+       }
 
     }
+    
+    /* For STRUCT, round up after all fields processed */
+    if (su != UNION)
+       sum += ((bitOffset+7)/8);
 
     return (su == UNION ? usum : sum);
 }
@@ -1145,49 +1189,77 @@ compStructSize (int su, structdef * sdef)
 static void 
 checkSClass (symbol * sym, int isProto)
 {
+  sym_link *t;
+  
   if (getenv("DEBUG_SANITY")) {
     fprintf (stderr, "checkSClass: %s \n", sym->name);
   }
   
-  /* type is literal can happen foe enums change
+  /* type is literal can happen for enums change
      to auto */
   if (SPEC_SCLS (sym->etype) == S_LITERAL && !SPEC_ENUM (sym->etype))
     SPEC_SCLS (sym->etype) = S_AUTO;
   
-  /* if sfr or sbit then must also be */
-  /* volatile the initial value will be xlated */
-  /* to an absolute address */
+  /* if sfr or sbit then must also be volatile */
   if (SPEC_SCLS (sym->etype) == S_SBIT ||
       SPEC_SCLS (sym->etype) == S_SFR)
     {
       SPEC_VOLATILE (sym->etype) = 1;
-      /* if initial value given */
-      if (sym->ival)
-       {
-         SPEC_ABSA (sym->etype) = 1;
-         SPEC_ADDR (sym->etype) =
-           (int) list2int (sym->ival);
-         sym->ival = NULL;
-       }
     }
   
   /* if absolute address given then it mark it as
-     volatile */
-  if (IS_ABSOLUTE (sym->etype))
-    SPEC_VOLATILE (sym->etype) = 1;
+     volatile -- except in the PIC port */
+
+#if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
+  /* The PIC port uses a different peep hole optimizer based on "pCode" */
+  if (!TARGET_IS_PIC && !TARGET_IS_PIC16)
+#endif
+
+    if (IS_ABSOLUTE (sym->etype))
+      SPEC_VOLATILE (sym->etype) = 1;
   
+  /* If code memory is read only, then pointers to code memory */
+  /* implicitly point to constants -- make this explicit       */
+  t = sym->type;
+  while (t && t->next) {
+    if (IS_CODEPTR(t) && port->mem.code_ro) {
+      if (IS_SPEC(t->next)) {
+        SPEC_CONST (t->next) = 1;
+      } else {
+        DCL_PTR_CONST (t->next) = 1;
+      }
+    }
+    t = t->next;
+  }
+
   /* global variables declared const put into code */
+  /* if no other storage class specified */
   if (sym->level == 0 &&
-      SPEC_CONST (sym->etype)) {
-    SPEC_SCLS (sym->etype) = S_CODE;
+      SPEC_SCLS(sym->etype) == S_FIXED &&
+      !IS_FUNC(sym->type)) {
+    /* find the first non-array link */
+    t = sym->type;
+    while (IS_ARRAY(t))
+      t = t->next;
+    if (IS_CONSTANT (t)) {
+      SPEC_SCLS (sym->etype) = S_CODE;
+    }
   }
-  
+
   /* global variable in code space is a constant */
   if (sym->level == 0 &&
       SPEC_SCLS (sym->etype) == S_CODE &&
-      port->mem.code_ro)
-    SPEC_CONST (sym->etype) = 1;
-  
+      port->mem.code_ro) {
+    /* find the first non-array link */
+    t = sym->type;
+    while (IS_ARRAY(t))
+      t = t->next;
+    if (IS_SPEC(t)) {
+      SPEC_CONST (t) = 1;
+    } else {
+      DCL_PTR_CONST (t) = 1;
+    }
+  }
 
   /* if bit variable then no storage class can be */
   /* specified since bit is already a storage */
@@ -1208,7 +1280,7 @@ checkSClass (symbol * sym, int isProto)
       sym->ival = NULL;
     }
 
-  /* if this is an atomatic symbol */
+  /* if this is an automatic symbol */
   if (sym->level && (options.stackAuto || reentrant)) {
     if ((SPEC_SCLS (sym->etype) == S_AUTO ||
         SPEC_SCLS (sym->etype) == S_FIXED ||
@@ -1239,6 +1311,7 @@ checkSClass (symbol * sym, int isProto)
   if ((IS_ARRAY (sym->type) || IS_PTR (sym->type)) &&
       (SPEC_NOUN (sym->etype) == V_BIT ||
        SPEC_NOUN (sym->etype) == V_SBIT ||
+       SPEC_NOUN (sym->etype) == V_BITFIELD ||
        SPEC_SCLS (sym->etype) == S_SFR))
     werror (E_BIT_ARRAY, sym->name);
 
@@ -1278,7 +1351,8 @@ checkSClass (symbol * sym, int isProto)
           * control this allcoation, but the code was originally that way, and
           * changing it for non-390 ports breaks the compiler badly.
           */
-         bool useXdata = TARGET_IS_DS390 ? 1 : options.useXstack;
+         bool useXdata = (TARGET_IS_DS390 || TARGET_IS_DS400) ? 
+               1 : options.useXstack;
          SPEC_SCLS (sym->etype) = (useXdata ?
                                    S_XDATA : S_FIXED);
        }
@@ -1300,7 +1374,7 @@ changePointer (symbol * sym)
   for (p = sym->type; p; p = p->next)
     {
       if (!IS_SPEC (p) && DCL_TYPE (p) == UPOINTER)
-       DCL_TYPE (p) = GPOINTER;
+       DCL_TYPE (p) = port->unqualified_pointer;
       if (IS_PTR (p) && IS_FUNC (p->next))
        DCL_TYPE (p) = CPOINTER;
     }
@@ -1333,11 +1407,11 @@ copyLinkChain (sym_link * p)
   sym_link *head, *curr, *loop;
 
   curr = p;
-  head = loop = (curr ? newLink () : (void *) NULL);
+  head = loop = (curr ? newLink (p->class) : (void *) NULL);
   while (curr)
     {
       memcpy (loop, curr, sizeof (sym_link));  /* copy it */
-      loop->next = (curr->next ? newLink () : (void *) NULL);
+      loop->next = (curr->next ? newLink (curr->next->class) : (void *) NULL);
       loop = loop->next;
       curr = curr->next;
     }
@@ -1429,15 +1503,18 @@ computeType (sym_link * type1, sym_link * type2)
     rType = copyLinkChain (type2);
 
   reType = getSpec (rType);
+#if 0
+  if (SPEC_NOUN (reType) == V_CHAR)
+    SPEC_NOUN (reType) = V_INT;
+#endif
 
   /* if either of them unsigned but not val then make this unsigned */
-  if (((!IS_LITERAL(type1) && SPEC_USIGN (etype1)) || 
-       (!IS_LITERAL(type2) && SPEC_USIGN (etype2))) && 
+  if ((SPEC_USIGN (etype1) || SPEC_USIGN (etype2)) &&
       !IS_FLOAT (reType))
     SPEC_USIGN (reType) = 1;
   else
     SPEC_USIGN (reType) = 0;
-  
+
   /* if result is a literal then make not so */
   if (IS_LITERAL (reType))
     SPEC_SCLS (reType) = S_REGISTER;
@@ -1448,7 +1525,7 @@ computeType (sym_link * type1, sym_link * type2)
 /*--------------------------------------------------------------------*/
 /* compareType - will do type check return 1 if match, -1 if castable */
 /*--------------------------------------------------------------------*/
-int 
+int
 compareType (sym_link * dest, sym_link * src)
 {
   if (!dest && !src)
@@ -1471,6 +1548,9 @@ compareType (sym_link * dest, sym_link * src)
            }
            return compareType (dest->next, src->next);
          }
+         if (IS_PTR (dest) && IS_GENPTR (src) && IS_VOID(src->next)) {
+           return 1;
+         }
          if (IS_PTR (src) && IS_GENPTR (dest))
            return -1;
          if (IS_PTR (dest) && IS_ARRAY (src)) {
@@ -1478,7 +1558,6 @@ compareType (sym_link * dest, sym_link * src)
            int res=compareType (dest, val->type);
            Safe_free(val->type);
            Safe_free(val);
-           //return res ? -1 : 0;
            return res;
          }
          if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src))
@@ -1543,17 +1622,18 @@ compareType (sym_link * dest, sym_link * src)
 /*------------------------------------------------------------------*/
 /* inCalleeSaveList - return 1 if found in callee save list          */
 /*------------------------------------------------------------------*/
-bool 
-inCalleeSaveList (char *s)
+static int
+calleeCmp(void *p1, void *p2)
 {
-  int i;
-
-  if (options.all_callee_saves) return 1;
-  for (i = 0; options.calleeSaves[i]; i++)
-    if (strcmp (options.calleeSaves[i], s) == 0)
-      return 1;
+  return (strcmp((char *)p1, (char *)(p2)) == 0);
+}
 
-  return 0;
+bool
+inCalleeSaveList(char *s)
+{
+  if (options.all_callee_saves)
+    return 1;
+  return isinSetWith(options.calleeSavesSet, s, calleeCmp);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1573,7 +1653,7 @@ aggregateToPointer (value * val)
          sym_link *p = val->type;
 
          werror (W_STRUCT_AS_ARG, val->name);
-         val->type = newLink ();
+         val->type = newLink (DECLARATOR);
          val->type->next = p;
        }
 
@@ -1591,23 +1671,8 @@ aggregateToPointer (value * val)
          if (SPEC_OCLS(val->etype)) {
            DCL_TYPE(val->type)=PTR_TYPE(SPEC_OCLS(val->etype));
          } else {
-#if 1
            // this happens for (external) function parameters
-           DCL_TYPE (val->type) = GPOINTER;
-#else
-           if (TARGET_IS_DS390) {
-             /* The AUTO and REGISTER classes should probably
-              * also become generic pointers, but I haven't yet
-              * devised a test case for that.
-              */
-             DCL_TYPE (val->type) = GPOINTER;
-             break;
-           }
-           if (options.model==MODEL_LARGE) {
-             DCL_TYPE (val->type) = FPOINTER;
-             break;
-           }
-#endif
+           DCL_TYPE (val->type) = port->unqualified_pointer;
          }
          break;
        case S_AUTO:
@@ -1625,7 +1690,7 @@ aggregateToPointer (value * val)
          DCL_TYPE (val->type) = EEPPOINTER;
          break;
        default:
-         DCL_TYPE (val->type) = GPOINTER;
+         DCL_TYPE (val->type) = port->unqualified_pointer;
        }
       
       /* is there is a symbol associated then */
@@ -1679,7 +1744,7 @@ checkFunction (symbol * sym, symbol *csym)
 
   /* check if this function is defined as calleeSaves
      then mark it as such */
-    FUNC_CALLEESAVES(sym->type) = inCalleeSaveList (sym->name);
+  FUNC_CALLEESAVES(sym->type) = inCalleeSaveList (sym->name);
 
   /* if interrupt service routine  */
   /* then it cannot have arguments */
@@ -1691,6 +1756,27 @@ checkFunction (symbol * sym, symbol *csym)
       }
     }
 
+  for (argCnt=1, acargs = FUNC_ARGS(sym->type); 
+       acargs; 
+       acargs=acargs->next, argCnt++) {
+    if (!acargs->sym) { 
+      // this can happen for reentrant functions
+      werror(E_PARAM_NAME_OMITTED, sym->name, argCnt);
+      // the show must go on: synthesize a name and symbol
+      SNPRINTF (acargs->name, sizeof(acargs->name), "_%s_PARM_%d", sym->name, argCnt);
+      acargs->sym = newSymbol (acargs->name, 1);
+      SPEC_OCLS (acargs->etype) = istack;
+      acargs->sym->type = copyLinkChain (acargs->type);
+      acargs->sym->etype = getSpec (acargs->sym->type);
+      acargs->sym->_isparm = 1;
+      strncpyz (acargs->sym->rname, acargs->name, sizeof(acargs->sym->rname));
+    } else if (strcmp(acargs->sym->name, acargs->sym->rname)==0) { 
+      // synthesized name
+      werror(E_PARAM_NAME_OMITTED, sym->name, argCnt);
+    }
+  }
+  argCnt--;
+
   if (!csym && !(csym = findSym (SymbolTab, sym, sym->name)))
     return 1;                  /* not defined nothing more to check  */
 
@@ -1723,6 +1809,17 @@ checkFunction (symbol * sym, symbol *csym)
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "_naked");
     }
+  
+  /* Really, reentrant should match regardless of argCnt, but     */
+  /* this breaks some existing code (the fp lib functions). If    */
+  /* the first argument is always passed the same way, this       */
+  /* lax checking is ok (but may not be true for in future ports) */
+  if (IFFUNC_ISREENT (csym->type) != IFFUNC_ISREENT (sym->type)
+      && argCnt>1)
+    {
+      //printf("argCnt = %d\n",argCnt);
+      werror (E_PREV_DEF_CONFLICT, csym->name, "reentrant");
+    }
 
   /* compare expected args with actual args */
   exargs = FUNC_ARGS(csym->type);
@@ -1769,6 +1866,7 @@ checkFunction (symbol * sym, symbol *csym)
   /* replace with this defition */
   sym->cdef = csym->cdef;
   deleteSym (SymbolTab, csym, csym->name);
+  deleteFromSeg(csym);
   addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
   if (IS_EXTERN (csym->etype) && !
       IS_EXTERN (sym->etype))
@@ -1778,6 +1876,29 @@ checkFunction (symbol * sym, symbol *csym)
   return 1;
 }
 
+/*------------------------------------------------------------------*/
+/* cdbStructBlock - calls struct printing for a blcks               */
+/*------------------------------------------------------------------*/
+void cdbStructBlock (int block)
+{
+  int i;
+  bucket **table = StructTab;
+  bucket *chain;
+
+  /* go thru the entire  table  */
+  for (i = 0; i < 256; i++)
+    {
+      for (chain = table[i]; chain; chain = chain->next)
+       {
+         if (chain->block >= block)
+           {
+             if(debugFile)
+               debugFile->writeType((structdef *)chain->sym, chain->block, 0, NULL);
+           }
+       }
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* processFuncArgs - does some processing with function args       */
 /*-----------------------------------------------------------------*/
@@ -1798,7 +1919,7 @@ processFuncArgs (symbol * func)
 
   /* if this function has variable argument list */
   /* then make the function a reentrant one    */
-  if (IFFUNC_HASVARARGS(funcType))
+  if (IFFUNC_HASVARARGS(funcType) || (options.stackAuto && !func->cdef))
     FUNC_ISREENT(funcType)=1;
 
   /* check if this function is defined as calleeSaves
@@ -1821,13 +1942,17 @@ processFuncArgs (symbol * func)
   /* change it to pointer to the same type */
   while (val)
     {
+       int argreg = 0;
       /* mark it as a register parameter if
          the function does not have VA_ARG
          and as port dictates */
       if (!IFFUNC_HASVARARGS(funcType) &&
-         (*port->reg_parm) (val->type))
+         (argreg = (*port->reg_parm) (val->type)))
        {
          SPEC_REGPARM (val->etype) = 1;
+         SPEC_ARGREG(val->etype) = argreg;
+       } else if (IFFUNC_ISREENT(funcType)) {
+           FUNC_HASSTACKPARM(funcType) = 1;
        }
 
       if (IS_AGGREGATE (val->type))
@@ -1862,30 +1987,38 @@ processFuncArgs (symbol * func)
       /* synthesize a variable name */
       if (!val->sym)
        {
-
-         sprintf (val->name, "_%s_PARM_%d", func->name, pNum++);
+         SNPRINTF (val->name, sizeof(val->name), 
+                   "_%s_PARM_%d", func->name, pNum++);
          val->sym = newSymbol (val->name, 1);
          SPEC_OCLS (val->etype) = port->mem.default_local_map;
          val->sym->type = copyLinkChain (val->type);
          val->sym->etype = getSpec (val->sym->type);
          val->sym->_isparm = 1;
-         strcpy (val->sym->rname, val->name);
-         SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) =
-           SPEC_STAT (func->etype);
+         strncpyz (val->sym->rname, val->name, sizeof(val->sym->rname));
+         if (IS_SPEC(func->etype)) {
+           SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) =
+             SPEC_STAT (func->etype);
+         }
          addSymChain (val->sym);
 
        }
       else                     /* symbol name given create synth name */
        {
 
-         sprintf (val->name, "_%s_PARM_%d", func->name, pNum++);
-         strcpy (val->sym->rname, val->name);
+         SNPRINTF (val->name, sizeof(val->name), "_%s_PARM_%d", func->name, pNum++);
+         strncpyz (val->sym->rname, val->name, sizeof(val->sym->rname));
          val->sym->_isparm = 1;
          SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) =
            (options.model != MODEL_SMALL ? xdata : data);
-         SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) =
-           SPEC_STAT (func->etype);
+         if (IS_SPEC(func->etype)) {
+           SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) =
+             SPEC_STAT (func->etype);
+         }
        }
+      if (!isinSet(operKeyReset, val->sym)) {
+       addSet (&operKeyReset, val->sym);
+       applyToSet (operKeyReset, resetParmKey);
+      }
       val = val->next;
     }
 }
@@ -1923,7 +2056,9 @@ void
 printTypeChain (sym_link * start, FILE * of)
 {
   int nlr = 0;
+  value *args;
   sym_link * type, * search;
+  STORAGE_CLASS scls;
 
   if (!of)
     {
@@ -1936,99 +2071,110 @@ printTypeChain (sym_link * start, FILE * of)
     return;
   }
 
-  /* print the chain as it is written in the source: */
-  /* start with the last entry                       */
+  /* Print the chain as it is written in the source: */
+  /* start with the last entry.                      */
+  /* However, the storage class at the end of the    */
+  /* chain reall applies to the first in the chain!  */
+
   for (type = start; type && type->next; type = type->next)
     ;
+  if (IS_SPEC (type))
+    scls=SPEC_SCLS(type);
+  else
+    scls=0;
   while (type)
     {
+      if (type==start) {
+       switch (scls) 
+         {
+         case S_DATA: fprintf (of, "data-"); break;
+         case S_XDATA: fprintf (of, "xdata-"); break;
+         case S_SFR: fprintf (of, "sfr-"); break;
+         case S_SBIT: fprintf (of, "sbit-"); break;
+         case S_CODE: fprintf (of, "code-"); break;
+         case S_IDATA: fprintf (of, "idata-"); break;
+         case S_PDATA: fprintf (of, "pdata-"); break;
+         case S_LITERAL: fprintf (of, "literal-"); break;
+         case S_STACK: fprintf (of, "stack-"); break;
+         case S_XSTACK: fprintf (of, "xstack-"); break;
+         case S_BIT: fprintf (of, "bit-"); break;
+         case S_EEPROM: fprintf (of, "eeprom-"); break;
+         default: break;
+         }
+      }
+
       if (IS_DECL (type))
        {
-         if (DCL_PTR_VOLATILE (type)) {
-           fprintf (of, "volatile ");
+         if (!IS_FUNC(type)) {
+           if (DCL_PTR_VOLATILE (type)) {
+             fprintf (of, "volatile-");
+           }
+           if (DCL_PTR_CONST (type)) {
+             fprintf (of, "const-");
+           }
          }
          switch (DCL_TYPE (type))
            {
            case FUNCTION:
-             fprintf (of, "function %s", (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "));
+             fprintf (of, "function %s %s", 
+                      (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "),
+                      (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " "));
+             fprintf (of, "( ");
+             for (args = FUNC_ARGS(type); 
+                  args; 
+                  args=args->next) {
+               printTypeChain(args->type, of);
+               if (args->next)
+                 fprintf(of, ", ");
+             }
+             fprintf (of, ") ");
              break;
            case GPOINTER:
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
-             fprintf (of, "generic * ");
+             fprintf (of, "generic* ");
              break;
            case CPOINTER:
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
-             fprintf (of, "code * ");
+             fprintf (of, "code* ");
              break;
            case FPOINTER:
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
-             fprintf (of, "xdata * ");
+             fprintf (of, "xdata* ");
              break;
            case EEPPOINTER:
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
-             fprintf (of, "eeprom * ");
+             fprintf (of, "eeprom* ");
              break;
-
            case POINTER:
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
-             fprintf (of, "near *");
+             fprintf (of, "near* ");
              break;
            case IPOINTER:
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
-             fprintf (of, "idata * ");
+             fprintf (of, "idata* ");
              break;
            case PPOINTER:
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
-             fprintf (of, "pdata * ");
+             fprintf (of, "pdata* ");
              break;
            case UPOINTER:
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
-             fprintf (of, "unkown * ");
+             fprintf (of, "unknown* ");
              break;
            case ARRAY:
-             fprintf (of, "[] ");
+             if (DCL_ELEM(type)) {
+               fprintf (of, "[%d] ", DCL_ELEM(type));
+             } else {
+               fprintf (of, "[] ");
+             }
              break;
            }
        }
       else
        {
-         switch (SPEC_SCLS(type)) 
-           {
-           case S_DATA: fprintf (of, "data "); break;
-           case S_XDATA: fprintf (of, "xdata "); break;
-           case S_SFR: fprintf (of, "sfr "); break;
-           case S_SBIT: fprintf (of, "sbit "); break;
-           case S_CODE: fprintf (of, "code "); break;
-           case S_IDATA: fprintf (of, "idata "); break;
-           case S_PDATA: fprintf (of, "pdata "); break;
-           case S_LITERAL: fprintf (of, "literal "); break;
-           case S_STACK: fprintf (of, "stack "); break;
-           case S_XSTACK: fprintf (of, "xstack "); break;
-           case S_BIT: fprintf (of, "bit "); break;
-           case S_EEPROM: fprintf (of, "eeprom "); break;
-           default: break;
-           }
-
          if (SPEC_VOLATILE (type))
-           fprintf (of, "volatile ");
-         if (SPEC_USIGN (type))
-           fprintf (of, "unsigned ");
+           fprintf (of, "volatile-");
          if (SPEC_CONST (type))
-           fprintf (of, "const ");
-
+           fprintf (of, "const-");
+         if (SPEC_USIGN (type))
+           fprintf (of, "unsigned-");
          switch (SPEC_NOUN (type))
            {
            case V_INT:
              if (IS_LONG (type))
-               fprintf (of, "long ");
+               fprintf (of, "long-");
              fprintf (of, "int");
              break;
 
@@ -2053,7 +2199,11 @@ printTypeChain (sym_link * start, FILE * of)
              break;
 
            case V_BIT:
-             fprintf (of, "bit {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
+             fprintf (of, "bit");
+             break;
+
+           case V_BITFIELD:
+             fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
              break;
 
            case V_DOUBLE:
@@ -2065,217 +2215,187 @@ printTypeChain (sym_link * start, FILE * of)
              break;
            }
        }
-       /* search entry in list before "type" */
-    for (search = start; search && search->next != type;)
-       search = search->next;
-    type = search;
-    if (type)
-      fputc (' ', of);
+      /* search entry in list before "type" */
+      for (search = start; search && search->next != type;)
+       search = search->next;
+      type = search;
+      if (type)
+       fputc (' ', of);
     }
   if (nlr)
     fprintf (of, "\n");
 }
 
-/*-----------------------------------------------------------------*/
-/* cdbTypeInfo - print the type information for debugger           */
-/*-----------------------------------------------------------------*/
+/*--------------------------------------------------------------------*/
+/* printTypeChainRaw - prints the type chain in human readable form   */
+/*                     in the raw data structure ordering             */
+/*--------------------------------------------------------------------*/
 void
-cdbTypeInfo (sym_link * type, FILE * of)
+printTypeChainRaw (sym_link * start, FILE * of)
 {
-  fprintf (of, "{%d}", getSize (type));
+  int nlr = 0;
+  value *args;
+  sym_link * type;
+
+  if (!of)
+    {
+      of = stdout;
+      nlr = 1;
+    }
+
+  if (start==NULL) {
+    fprintf (of, "void");
+    return;
+  }
+
+  type = start;
+  
   while (type)
     {
       if (IS_DECL (type))
        {
+         if (!IS_FUNC(type)) {
+           if (DCL_PTR_VOLATILE (type)) {
+             fprintf (of, "volatile-");
+           }
+           if (DCL_PTR_CONST (type)) {
+             fprintf (of, "const-");
+           }
+         }
          switch (DCL_TYPE (type))
            {
            case FUNCTION:
-             fprintf (of, "DF,");
+             fprintf (of, "function %s %s", 
+                      (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "),
+                      (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " "));
+             fprintf (of, "( ");
+             for (args = FUNC_ARGS(type); 
+                  args; 
+                  args=args->next) {
+               printTypeChain(args->type, of);
+               if (args->next)
+                 fprintf(of, ", ");
+             }
+             fprintf (of, ") ");
              break;
            case GPOINTER:
-             fprintf (of, "DG,");
+             fprintf (of, "generic* ");
              break;
            case CPOINTER:
-             fprintf (of, "DC,");
+             fprintf (of, "code* ");
              break;
            case FPOINTER:
-             fprintf (of, "DX,");
+             fprintf (of, "xdata* ");
+             break;
+           case EEPPOINTER:
+             fprintf (of, "eeprom* ");
              break;
            case POINTER:
-             fprintf (of, "DD,");
+             fprintf (of, "near* ");
              break;
            case IPOINTER:
-             fprintf (of, "DI,");
+             fprintf (of, "idata* ");
              break;
            case PPOINTER:
-             fprintf (of, "DP,");
+             fprintf (of, "pdata* ");
              break;
-           case EEPPOINTER:
-             fprintf (of, "DA,");
+           case UPOINTER:
+             fprintf (of, "unknown* ");
              break;
            case ARRAY:
-             fprintf (of, "DA%d,", DCL_ELEM (type));
-             break;
-           default:
+             if (DCL_ELEM(type)) {
+               fprintf (of, "[%d] ", DCL_ELEM(type));
+             } else {
+               fprintf (of, "[] ");
+             }
              break;
            }
+          if (DCL_TSPEC(type))
+            {
+              fprintf (of, "{");
+              printTypeChainRaw(DCL_TSPEC(type), of);
+              fprintf (of, "}");
+            }
        }
-      else
+      else if (IS_SPEC (type))
        {
+       switch (SPEC_SCLS (type)) 
+         {
+         case S_DATA: fprintf (of, "data-"); break;
+         case S_XDATA: fprintf (of, "xdata-"); break;
+         case S_SFR: fprintf (of, "sfr-"); break;
+         case S_SBIT: fprintf (of, "sbit-"); break;
+         case S_CODE: fprintf (of, "code-"); break;
+         case S_IDATA: fprintf (of, "idata-"); break;
+         case S_PDATA: fprintf (of, "pdata-"); break;
+         case S_LITERAL: fprintf (of, "literal-"); break;
+         case S_STACK: fprintf (of, "stack-"); break;
+         case S_XSTACK: fprintf (of, "xstack-"); break;
+         case S_BIT: fprintf (of, "bit-"); break;
+         case S_EEPROM: fprintf (of, "eeprom-"); break;
+         default: break;
+         }
+         if (SPEC_VOLATILE (type))
+           fprintf (of, "volatile-");
+         if (SPEC_CONST (type))
+           fprintf (of, "const-");
+         if (SPEC_USIGN (type))
+           fprintf (of, "unsigned-");
          switch (SPEC_NOUN (type))
            {
            case V_INT:
              if (IS_LONG (type))
-               fprintf (of, "SL");
-             else
-               fprintf (of, "SI");
+               fprintf (of, "long-");
+             fprintf (of, "int");
              break;
 
            case V_CHAR:
-             fprintf (of, "SC");
+             fprintf (of, "char");
              break;
 
            case V_VOID:
-             fprintf (of, "SV");
+             fprintf (of, "void");
              break;
 
            case V_FLOAT:
-             fprintf (of, "SF");
+             fprintf (of, "float");
              break;
 
            case V_STRUCT:
-             fprintf (of, "ST%s", SPEC_STRUCT (type)->tag);
+             fprintf (of, "struct %s", SPEC_STRUCT (type)->tag);
              break;
 
            case V_SBIT:
-             fprintf (of, "SX");
+             fprintf (of, "sbit");
              break;
 
            case V_BIT:
-             fprintf (of, "SB%d$%d", SPEC_BSTR (type), SPEC_BLEN (type));
+             fprintf (of, "bit");
              break;
 
-           default:
+           case V_BITFIELD:
+             fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
              break;
-           }
-         fputs (":", of);
-         if (SPEC_USIGN (type))
-           fputs ("U", of);
-         else
-           fputs ("S", of);
-       }
-      type = type->next;
-    }
-}
-/*-----------------------------------------------------------------*/
-/* cdbSymbol - prints a symbol & its type information for debugger */
-/*-----------------------------------------------------------------*/
-void 
-cdbSymbol (symbol * sym, FILE * of, int isStructSym, int isFunc)
-{
-  memmap *map;
 
-  if (!sym)
-    return;
-  if (!of)
-    of = stdout;
+           case V_DOUBLE:
+             fprintf (of, "double");
+             break;
 
-  if (isFunc)
-    fprintf (of, "F:");
-  else
-    fprintf (of, "S:");                /* symbol record */
-  /* if this is not a structure symbol then
-     we need to figure out the scope information */
-  if (!isStructSym)
-    {
-      if (!sym->level)
-       {
-         /* global */
-         if (IS_STATIC (sym->etype))
-           fprintf (of, "F%s$", moduleName);   /* scope is file */
-         else
-           fprintf (of, "G$"); /* scope is global */
+           default:
+             fprintf (of, "unknown type");
+             break;
+           }
        }
       else
-       /* symbol is local */
-       fprintf (of, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
-    }
-  else
-    fprintf (of, "S$");                /* scope is structure */
-
-  /* print the name, & mangled name */
-  fprintf (of, "%s$%d$%d(", sym->name,
-          sym->level, sym->block);
-
-  cdbTypeInfo (sym->type, of);
-  fprintf (of, "),");
-
-  /* print the address space */
-  map = SPEC_OCLS (sym->etype);
-  fprintf (of, "%c,%d,%d",
-          (map ? map->dbName : 'Z'), sym->onStack, SPEC_STAK (sym->etype));
-
-  /* if assigned to registers then output register names */
-  /* if this is a function then print
-     if is it an interrupt routine & interrupt number
-     and the register bank it is using */
-  if (isFunc)
-    fprintf (of, ",%d,%d,%d", FUNC_ISISR (sym->type),
-            FUNC_INTNO (sym->type), FUNC_REGBANK (sym->type));
-  /* alternate location to find this symbol @ : eg registers
-     or spillication */
-
-  if (!isStructSym)
-    fprintf (of, "\n");
-}
-
-/*-----------------------------------------------------------------*/
-/* cdbStruct - print a structure for debugger                      */
-/*-----------------------------------------------------------------*/
-void 
-cdbStruct (structdef * sdef, int block, FILE * of,
-          int inStruct, char *tag)
-{
-  symbol *sym;
-
-  fprintf (of, "T:");
-  /* if block # then must have function scope */
-  fprintf (of, "F%s$", moduleName);
-  fprintf (of, "%s[", (tag ? tag : sdef->tag));
-  for (sym = sdef->fields; sym; sym = sym->next)
-    {
-      fprintf (of, "({%d}", sym->offset);
-      cdbSymbol (sym, of, TRUE, FALSE);
-      fprintf (of, ")");
+        fprintf (of, "NOT_SPEC_OR_DECL");
+      type = type->next;
+      if (type)
+       fputc (' ', of);
     }
-  fprintf (of, "]");
-  if (!inStruct)
+  if (nlr)
     fprintf (of, "\n");
 }
 
-/*------------------------------------------------------------------*/
-/* cdbStructBlock - calls struct printing for a blcks               */
-/*------------------------------------------------------------------*/
-void 
-cdbStructBlock (int block, FILE * of)
-{
-  int i;
-  bucket **table = StructTab;
-  bucket *chain;
-  wassert (of);
-
-  /* go thru the entire  table  */
-  for (i = 0; i < 256; i++)
-    {
-      for (chain = table[i]; chain; chain = chain->next)
-       {
-         if (chain->block >= block)
-           {
-             cdbStruct ((structdef *) chain->sym, chain->block, of, 0, NULL);
-           }
-       }
-    }
-}
 
 /*-----------------------------------------------------------------*/
 /* powof2 - returns power of two for the number if number is pow 2 */
@@ -2348,13 +2468,14 @@ _mangleFunctionName(char *in)
 /*                      'x' - xdata                                */
 /*                      'p' - code                                 */
 /*                      'd' - data                                 */                     
+/*                      'F' - function                             */                     
 /* examples : "ig*" - generic int *                               */
 /*            "cx*" - char xdata *                                 */
 /*            "ui" -  unsigned int                                 */
 /*-----------------------------------------------------------------*/
 sym_link *typeFromStr (char *s)
 {
-    sym_link *r = newLink();
+    sym_link *r = newLink(DECLARATOR);
     int usign = 0;
 
     do {
@@ -2388,17 +2509,17 @@ sym_link *typeFromStr (char *s)
            SPEC_NOUN(r) = V_VOID;
            break;
        case '*':
-           DCL_TYPE(r) = GPOINTER;
+           DCL_TYPE(r) = port->unqualified_pointer;
            break;
        case 'g':
        case 'x':
        case 'p':
        case 'd':
+       case 'F':
            assert(*(s+1)=='*');
-           nr = newLink();
+           nr = newLink(DECLARATOR);
            nr->next = r;
            r = nr;
-           r->class = DECLARATOR ;
            switch (*s) {
            case 'g':
                DCL_TYPE(r) = GPOINTER;
@@ -2412,11 +2533,19 @@ sym_link *typeFromStr (char *s)
            case 'd':
                DCL_TYPE(r) = POINTER;
                break;
+           case 'F':
+               DCL_TYPE(r) = FUNCTION;
+               nr = newLink(DECLARATOR);
+               nr->next = r;
+               r = nr;
+               DCL_TYPE(r) = CPOINTER;
+               break;
            }
            s++;
            break;
        default:
-           werror(E_INTERNAL_ERROR,"typeFromStr");
+           werror(E_INTERNAL_ERROR, __FILE__, __LINE__, 
+                  "typeFromStr: unknown type");
            break;
        }
        if (IS_SPEC(r) && usign) {
@@ -2462,7 +2591,7 @@ initCSupport ()
 
   for (bwd = 0; bwd < 3; bwd++)
     {
-      sym_link *l;
+      sym_link *l = NULL;
       switch (bwd)
        {
        case 0:
@@ -2501,25 +2630,27 @@ initCSupport ()
            {
              if (tofrom)
                {
-                 sprintf (buffer, "__fs2%s%s", ssu[su], sbwd[bwd]);
-                 __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], floatType, 1, options.float_rent);
+                 SNPRINTF (buffer, sizeof(buffer), "__fs2%s%s", ssu[su], sbwd[bwd]);
+                 __conv[tofrom][bwd][su] = funcOfType (buffer, __multypes[bwd][su], floatType, 1, options.float_rent);
                }
              else
                {
-                 sprintf (buffer, "__%s%s2fs", ssu[su], sbwd[bwd]);
-                 __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), floatType, __multypes[bwd][su], 1, options.float_rent);
+                 SNPRINTF (buffer, sizeof(buffer), "__%s%s2fs", ssu[su], sbwd[bwd]);
+                 __conv[tofrom][bwd][su] = funcOfType (buffer, floatType, __multypes[bwd][su], 1, options.float_rent);
                }
            }
        }
     }
 
+/*
   for (muldivmod = 0; muldivmod < 3; muldivmod++)
     {
       for (bwd = 0; bwd < 3; bwd++)
        {
          for (su = 0; su < 2; su++)
            {
-             sprintf (buffer, "_%s%s%s",
+             SNPRINTF (buffer, sizeof(buffer),
+                       "_%s%s%s",
                       smuldivmod[muldivmod],
                       ssu[su],
                       sbwd[bwd]);
@@ -2529,13 +2660,67 @@ initCSupport ()
        }
     }
 
+  muluint() and mulsint() resp. mululong() and mulslong() return the same result.
+  Therefore they've been merged into mulint() and mullong().
+*/
+
+  for (bwd = 0; bwd < 3; bwd++)
+    {
+      for (su = 0; su < 2; su++)
+       {
+         for (muldivmod = 1; muldivmod < 3; muldivmod++)
+           {
+             /* div and mod */
+             SNPRINTF (buffer, sizeof(buffer),
+                       "_%s%s%s",
+                      smuldivmod[muldivmod],
+                      ssu[su],
+                      sbwd[bwd]);
+             __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
+             FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+           }
+       }
+    }
+  /* mul only */
+  muldivmod = 0;
+  /* byte */
+  bwd = 0;
+  for (su = 0; su < 2; su++)
+    {
+      /* muluchar and mulschar are still separate functions, because e.g. the z80
+         port is sign/zero-extending to int before calling mulint() */
+      SNPRINTF (buffer, sizeof(buffer),
+               "_%s%s%s",
+               smuldivmod[muldivmod],
+               ssu[su],
+               sbwd[bwd]);
+      __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
+      FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+    }
+  /* signed only */
+  su = 0;
+  /* word and doubleword */
+  for (bwd = 1; bwd < 3; bwd++)
+    {
+      /* mul, int/long */
+      SNPRINTF (buffer, sizeof(buffer),
+               "_%s%s",
+               smuldivmod[muldivmod],
+               sbwd[bwd]);
+      __muldiv[muldivmod][bwd][0] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
+      FUNC_NONBANKED (__muldiv[muldivmod][bwd][0]->type) = 1;
+      /* signed = unsigned */
+      __muldiv[muldivmod][bwd][1] = __muldiv[muldivmod][bwd][0];
+    }
+
   for (rlrr = 0; rlrr < 2; rlrr++)
     {
       for (bwd = 0; bwd < 3; bwd++)
        {
          for (su = 0; su < 2; su++)
            {
-             sprintf (buffer, "_%s%s%s",
+             SNPRINTF (buffer, sizeof(buffer),
+                       "_%s%s%s",
                       srlrr[rlrr],
                       ssu[su],
                       sbwd[bwd]);
@@ -2560,5 +2745,26 @@ void initBuiltIns()
        sym = funcOfTypeVarg(port->builtintable[i].name,port->builtintable[i].rtype,
                             port->builtintable[i].nParms,port->builtintable[i].parm_types);
        FUNC_ISBUILTIN(sym->type) = 1;
+       FUNC_ISREENT(sym->type) = 0;    /* can never be reentrant */
     }
 }
+
+sym_link *validateLink(sym_link        *l, 
+                       const char      *macro,
+                       const char      *args,
+                       const char      select,
+                       const char      *file, 
+                       unsigned        line)
+{    
+  if (l && l->class==select)
+    {
+       return l;
+    }
+    fprintf(stderr, 
+           "Internal error: validateLink failed in %s(%s) @ %s:%u:"
+           " expected %s, got %s\n",
+           macro, args, file, line, 
+           DECLSPEC2TXT(select), l ? DECLSPEC2TXT(l->class) : "null-link");
+    exit(-1);
+    return l; // never reached, makes compiler happy.
+}