* src/SDCCsymt.c (sclsFromPtr),
[fw/sdcc] / src / SDCCsymt.c
index 363e39a467627377ab648d86541a73ddb181ed77..5f538398eb3ae764de52a8ec48911c0235195f55 100644 (file)
 #include "common.h"
 #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 '");
+  printTypeChain (from, stderr);
+  fprintf (stderr, "'\nto type '");
+  printTypeChain (to, stderr);
+  fprintf (stderr, "'\n");
+}
+
 /* noun strings */
 char *nounName(sym_link *sl) {
   switch (SPEC_NOUN(sl)) 
     {
     case V_INT: {
       if (SPEC_LONG(sl)) return "long";
-      if (SPEC_SHORT(sl)) return "short";
+      if (sl->select.s._short) return "short";
       return "int";
     }
     case V_FLOAT: return "float";
@@ -38,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";
@@ -72,7 +84,7 @@ newBucket ()
 {
   bucket *bp;
 
-  bp = Safe_calloc (1, sizeof (bucket));
+  bp = Safe_alloc ( sizeof (bucket));
 
   return bp;
 }
@@ -98,29 +110,37 @@ addSym (bucket ** stab,
        void *sym,
        char *sname,
        int level,
-       int block)
+       int block,
+       int checkType)
 {
   int i;                       /* index into the hash Table */
   bucket *bp;                  /* temp bucket    *         */
 
-  if (getenv("DEBUG_SANITY")) {
-    fprintf (stderr, "addSym: %s ", sname);
-  }
-  /* Make sure sym is a symbol and not a structdef */
-  if (StructTab!=stab) {
+  if (checkType) {
+    symbol *csym = (symbol *)sym;
+
+    if (getenv("DEBUG_SANITY")) {
+      fprintf (stderr, "addSym: %s ", sname);
+    }
     /* make sure the type is complete and sane */
-    checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name);
+    checkTypeSanity(csym->etype, csym->name);
+  }
+
+  /* prevent overflow of the (r)name buffers */
+  if (strlen(sname)>SDCC_SYMNAME_MAX) {
+    werror (W_SYMBOL_NAME_TOO_LONG, SDCC_SYMNAME_MAX);
+    sname[SDCC_SYMNAME_MAX]='\0';
   }
 
   /* the symbols are always added at the head of the list  */
   i = hashKey (sname);
   /* get a free entry */
-  bp = Safe_calloc (1, sizeof (bucket));
+  bp = Safe_alloc ( sizeof (bucket));
 
   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)
@@ -217,13 +237,12 @@ findSymWithLevel (bucket ** stab, symbol * sym)
    **/
   while (bp)
     {
-
       if (strcmp (bp->name, sym->name) == 0 && bp->level <= sym->level)
        {
          /* if this is parameter then nothing else need to be checked */
          if (((symbol *) (bp->sym))->_isparm)
            return (bp->sym);
-         /* if levels match then block numbers hsould also match */
+         /* if levels match then block numbers should also match */
          if (bp->level && bp->level == sym->level && bp->block == sym->block)
            return (bp->sym);
          /* if levels don't match then we are okay */
@@ -268,12 +287,12 @@ newSymbol (char *name, int scope)
 {
   symbol *sym;
 
-  sym = Safe_calloc (1, sizeof (symbol));
+  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;
 }
 
@@ -281,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_calloc (1, sizeof (sym_link));
+  p = Safe_alloc ( sizeof (sym_link));
+  p->class=select;
 
   return p;
 }
@@ -298,11 +318,42 @@ newStruct (char *tag)
 {
   structdef *s;
 
-  s = Safe_calloc (1, sizeof (structdef));
+  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          */
@@ -318,16 +369,18 @@ pointerTypes (sym_link * ptr, sym_link * type)
     ptr = ptr->next;
 
   /* could not find it */
-  if (!ptr || IS_SPEC (ptr) ||
-      DCL_TYPE (ptr) != UPOINTER)
+  if (!ptr || IS_SPEC (ptr))
+    return;
+  
+  if (IS_PTR(ptr) && DCL_TYPE(ptr)!=UPOINTER) {
+    pointerTypes (ptr->next, type);
     return;
+  }
 
   /* change the pointer type depending on the
      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:
@@ -343,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
@@ -364,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;
     }
 
@@ -373,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;
     }
-
 }
 
 /*------------------------------------------------------------------*/
@@ -389,6 +438,9 @@ addDecl (symbol * sym, int type, sym_link * p)
   sym_link *tail;
   sym_link *t;
 
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "SDCCsymt.c:addDecl(%s,%d,%p)\n", sym->name, type, p);
+
   /* if we are passed a link then set head & tail */
   if (p)
     {
@@ -398,7 +450,7 @@ addDecl (symbol * sym, int type, sym_link * p)
     }
   else
     {
-      head = tail = newLink ();
+      head = tail = newLink (DECLARATOR);
       DCL_TYPE (head) = type;
     }
 
@@ -412,7 +464,7 @@ addDecl (symbol * sym, int type, sym_link * p)
     {
       if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail)
        {
-         sym->etype = mergeSpec (sym->etype, head);
+         sym->etype = mergeSpec (sym->etype, head, sym->name);
        }
       else
        {
@@ -432,25 +484,28 @@ addDecl (symbol * sym, int type, sym_link * p)
        }
     }
 
-  /* if the type is a unknown pointer and has
+  /* if the type is an unknown pointer and has
      a tspec then take the storage class const & volatile
      attribute from the tspec & make it those of this
      symbol */
   if (p &&
       !IS_SPEC (p) &&
-      DCL_TYPE (p) == UPOINTER &&
+      //DCL_TYPE (p) == UPOINTER &&
       DCL_TSPEC (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;
     }
+
+  // if there is a function in this type chain
+  if (p && funcInChain(sym->type)) {
+    processFuncArgs (sym);
+  }
+
   return;
 }
 
@@ -478,47 +533,43 @@ void checkTypeSanity(sym_link *etype, char *name) {
   noun=nounName(etype);
 
   if (getenv("DEBUG_SANITY")) {
-    fprintf (stderr, "checking sanity for %s\n", name);
+    fprintf (stderr, "checking sanity for %s %p\n", name, etype);
   }
 
   if ((SPEC_NOUN(etype)==V_CHAR || 
        SPEC_NOUN(etype)==V_FLOAT || 
        SPEC_NOUN(etype)==V_DOUBLE || 
        SPEC_NOUN(etype)==V_VOID) &&
-      (SPEC_SHORT(etype) || SPEC_LONG(etype))) {
+      (etype->select.s._short || SPEC_LONG(etype))) {
     // long or short for char float double or void
     werror (E_LONG_OR_SHORT_INVALID, noun, name);
   }
   if ((SPEC_NOUN(etype)==V_FLOAT || 
        SPEC_NOUN(etype)==V_DOUBLE || 
        SPEC_NOUN(etype)==V_VOID) && 
-      (SPEC_SIGNED(etype) || SPEC_USIGN(etype))) {
+      (etype->select.s._signed || SPEC_USIGN(etype))) {
     // signed or unsigned for float double or void
     werror (E_SIGNED_OR_UNSIGNED_INVALID, noun, name);
   }
 
-  if (!SPEC_NOUN(etype)) {
-    // special case for just "signed" or "unsigned" or "long"
-    if (SPEC_SIGNED(etype) || SPEC_USIGN(etype) || SPEC_LONG(etype)) {
-      SPEC_NOUN(etype)=V_INT;
-    }
-    // special case for just "short"
-    if (SPEC_SHORT(etype)) {
-      SPEC_NOUN(etype)=V_CHAR; // or maybe V_INT
-      SPEC_SHORT(etype)=0;
-    }
+  // special case for "short"
+  if (etype->select.s._short) {
+    SPEC_NOUN(etype) = options.shortis8bits ? V_CHAR : V_INT;
+    etype->select.s._short = 0;
   }
 
-  // if still no noun (e.g. "const a;" or "data b;") assume an int
+  /* if no noun e.g. 
+     "const a;" or "data b;" or "signed s" or "long l"
+     assume an int */
   if (!SPEC_NOUN(etype)) {
     SPEC_NOUN(etype)=V_INT;
   }
 
-  if (SPEC_SIGNED(etype) && SPEC_USIGN(etype)) {
+  if (etype->select.s._signed && SPEC_USIGN(etype)) {
     // signed AND unsigned 
     werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name);
   }
-  if (SPEC_SHORT(etype) && SPEC_LONG(etype)) {
+  if (etype->select.s._short && SPEC_LONG(etype)) {
     // short AND long
     werror (E_LONG_AND_SHORT_INVALID, noun, name);
   }
@@ -529,8 +580,18 @@ void checkTypeSanity(sym_link *etype, char *name) {
 /* mergeSpec - merges two specifiers and returns the new one        */
 /*------------------------------------------------------------------*/
 sym_link *
-mergeSpec (sym_link * dest, sym_link * src)
+mergeSpec (sym_link * dest, sym_link * src, char *name)
 {
+  if (!IS_SPEC(dest) || !IS_SPEC(src)) {
+#if 0
+    werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "cannot merge declarator");
+    exit (1);
+#else
+    werror (E_SYNTAX_ERROR, yytext);
+    // the show must go on
+    return newIntLink();
+#endif
+  }
 
   if (SPEC_NOUN(src)) {
     if (!SPEC_NOUN(dest)) {
@@ -539,8 +600,8 @@ mergeSpec (sym_link * dest, sym_link * src)
       /* we shouldn't redeclare the type */
       if (getenv("DEBUG_SANITY")) {
        fprintf (stderr, "mergeSpec: ");
-       werror(E_TWO_OR_MORE_DATA_TYPES, yylval.yychar);
       }
+      werror(E_TWO_OR_MORE_DATA_TYPES, name);
     }
   }
   
@@ -552,7 +613,7 @@ mergeSpec (sym_link * dest, sym_link * src)
       if (getenv("DEBUG_SANITY")) {
        fprintf (stderr, "mergeSpec: ");
       }
-      werror(E_TWO_OR_MORE_STORAGE_CLASSES, yylval.yychar);
+      werror(E_TWO_OR_MORE_STORAGE_CLASSES, name);
     }
   }
 
@@ -564,52 +625,47 @@ mergeSpec (sym_link * dest, sym_link * src)
     if (SPEC_what(dest)) {
       werror(W_DUPLICATE_SPEC, "what");
     }
-    SPEC_what(dst)=SPEC_what(src);
+    SPEC_what(dst)|=SPEC_what(src);
   }
 #endif
   // but there are more important thing right now
-  
+
   SPEC_LONG (dest) |= SPEC_LONG (src);
-  SPEC_SHORT (dest) |= SPEC_SHORT (src);
+  dest->select.s._short|=src->select.s._short;
   SPEC_USIGN (dest) |= SPEC_USIGN (src);
-  SPEC_SIGNED (dest) |= SPEC_SIGNED (src);
+  dest->select.s._signed|=src->select.s._signed;
   SPEC_STAT (dest) |= SPEC_STAT (src);
   SPEC_EXTR (dest) |= SPEC_EXTR (src);
+  SPEC_CONST(dest) |= SPEC_CONST (src);
   SPEC_ABSA (dest) |= SPEC_ABSA (src);
-  SPEC_RENT (dest) |= SPEC_RENT (src);
-  SPEC_INTN (dest) |= SPEC_INTN (src);
-  SPEC_BANK (dest) |= SPEC_BANK (src);
   SPEC_VOLATILE (dest) |= SPEC_VOLATILE (src);
-  SPEC_CRTCL (dest) |= SPEC_CRTCL (src);
   SPEC_ADDR (dest) |= SPEC_ADDR (src);
   SPEC_OCLS (dest) = SPEC_OCLS (src);
   SPEC_BLEN (dest) |= SPEC_BLEN (src);
   SPEC_BSTR (dest) |= SPEC_BSTR (src);
   SPEC_TYPEDEF (dest) |= SPEC_TYPEDEF (src);
-  SPEC_NONBANKED (dest) |= SPEC_NONBANKED (src);
-  SPEC_NAKED (dest) |= SPEC_NAKED (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);
 
-  return dest;
-}
-
-/*------------------------------------------------------------------*/
-/* 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;
+  /* these are the only function attributes that will be set 
+     in a specifier while parsing */
+  FUNC_NONBANKED(dest) |= FUNC_NONBANKED(src);
+  FUNC_BANKED(dest) |= FUNC_BANKED(src);
+  FUNC_ISCRITICAL(dest) |= FUNC_ISCRITICAL(src);
+  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);
 
-  spec = newLink ();
-  memcpy (spec, src, sizeof (sym_link));
-  return spec;
+  return dest;
 }
 
 /*------------------------------------------------------------------*/
@@ -621,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;
 }
 
@@ -648,8 +704,7 @@ newCharLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_CHAR;
 
   return p;
@@ -663,8 +718,7 @@ newFloatLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_FLOAT;
 
   return p;
@@ -678,8 +732,7 @@ newLongLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_INT;
   SPEC_LONG (p) = 1;
 
@@ -694,8 +747,7 @@ newIntLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_INT;
 
   return p;
@@ -715,7 +767,7 @@ getSize (sym_link * p)
       switch (SPEC_NOUN (p))
        {                       /* depending on the specifier type */
        case V_INT:
-         return (IS_LONG (p) ? LONGSIZE : (IS_SHORT (p) ? SHORTSIZE : INTSIZE));
+         return (IS_LONG (p) ? LONGSIZE : INTSIZE);
        case V_FLOAT:
          return FLOATSIZE;
        case V_CHAR:
@@ -727,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;
@@ -738,10 +791,14 @@ getSize (sym_link * p)
   /* this is a specifier  */
   switch (DCL_TYPE (p))
     {
-    case FUNCTION:
-      return 2;
     case ARRAY:
-      return DCL_ELEM (p) * getSize (p->next);
+      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[]");
+       return 0;
+      }
     case IPOINTER:
     case PPOINTER:
     case POINTER:
@@ -749,6 +806,7 @@ getSize (sym_link * p)
     case EEPPOINTER:
     case FPOINTER:
     case CPOINTER:
+    case FUNCTION:
       return (FPTRSIZE);
     case GPOINTER:
       return (GPTRSIZE);
@@ -774,7 +832,7 @@ bitsForType (sym_link * p)
       switch (SPEC_NOUN (p))
        {                       /* depending on the specifier type */
        case V_INT:
-         return (IS_LONG (p) ? LONGSIZE * 8 : (IS_SHORT (p) ? SHORTSIZE * 8 : INTSIZE * 8));
+         return (IS_LONG (p) ? LONGSIZE * 8 : INTSIZE * 8);
        case V_FLOAT:
          return FLOATSIZE * 8;
        case V_CHAR:
@@ -786,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;
@@ -797,8 +856,6 @@ bitsForType (sym_link * p)
   /* this is a specifier  */
   switch (DCL_TYPE (p))
     {
-    case FUNCTION:
-      return 2;
     case ARRAY:
       return DCL_ELEM (p) * getSize (p->next) * 8;
     case IPOINTER:
@@ -808,6 +865,7 @@ bitsForType (sym_link * p)
     case EEPPOINTER:
     case FPOINTER:
     case CPOINTER:
+    case FUNCTION:
       return (FPTRSIZE * 8);
     case GPOINTER:
       return (GPTRSIZE * 8);
@@ -852,9 +910,7 @@ copySymbol (symbol * src)
   dest->type = copyLinkChain (src->type);
   dest->etype = getSpec (dest->type);
   dest->next = NULL;
-  dest->args = copyValueChain (src->args);
   dest->key = src->key;
-  dest->calleeSave = src->calleeSave;
   dest->allocreq = src->allocreq;
   return dest;
 }
@@ -918,49 +974,40 @@ addSymChain (symbol * symHead)
   symbol *sym = symHead;
   symbol *csym = NULL;
 
-
   for (; sym != NULL; sym = sym->next)
     {
       changePointer(sym);
+      checkTypeSanity(sym->etype, sym->name);
 
       /* if already exists in the symbol table then check if
-         the previous was an extern definition if yes then
+         one of them is an extern definition if yes then
          then check if the type match, if the types match then
          delete the current entry and add the new entry      */
       if ((csym = findSymWithLevel (SymbolTab, sym)) &&
-         csym->level == sym->level)
-       {
-
-         /* previous definition extern ? */
-         if (IS_EXTERN (csym->etype))
-           {
-             /* do types match ? */
-             if (checkType (csym->type, sym->type) != 1)
-               /* no then error */
-               werror (E_DUPLICATE, csym->name);
-
-             /* delete current entry */
-             deleteSym (SymbolTab, csym, csym->name);
-             /* add new entry */
-             addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
-           }
-         else                  /* not extern */
+         csym->level == sym->level) {
+       
+       /* one definition extern ? */
+       if (IS_EXTERN (csym->etype) || IS_EXTERN (sym->etype)) {
+         /* do types match ? */
+         if (compareType (csym->type, sym->type) != 1) {
+           /* no then error */
+           werror (E_EXTERN_MISMATCH, csym->name);
+           continue;
+         }
+       } else {
+         /* not extern */
+         if (compareType (csym->type, sym->type) != 1) {
            werror (E_DUPLICATE, sym->name);
-         continue;
+           continue;
+         }
        }
+       /* delete current entry */
+       deleteSym (SymbolTab, csym, csym->name);
+       deleteFromSeg(csym);
+      }
 
-      /* check if previously defined */
-      if (csym && csym->level == sym->level)
-       {
-         /* if the previous one was declared as extern */
-         /* then check the type with the current one         */
-         if (IS_EXTERN (csym->etype))
-           {
-             if (checkType (csym->type, sym->type) <= 0)
-               werror (W_EXTERN_MISMATCH, csym->name);
-           }
-       }
-      addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
+      /* add new entry */
+      addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
     }
 }
 
@@ -984,35 +1031,33 @@ funcInChain (sym_link * lnk)
 /* structElemType - returns the type info of a sturct member        */
 /*------------------------------------------------------------------*/
 sym_link *
-structElemType (sym_link * stype, value * id, value ** argsp)
+structElemType (sym_link * stype, value * id)
 {
   symbol *fields = (SPEC_STRUCT (stype) ? SPEC_STRUCT (stype)->fields : NULL);
   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));
+           return type;
+         }
+       fields = fields->next;
+      }
+  }
 
-  /* look for the id */
-  while (fields)
-    {
-      if (strcmp (fields->rname, id->name) == 0)
-       {
-         if (argsp)
-           {
-             *argsp = fields->args;
-           }
-         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();
 }
 
 /*------------------------------------------------------------------*/
@@ -1047,61 +1092,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++;
+           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;
            }
-           else /* does not fit */ {
-               bitOffset = 0;
-               SPEC_BSTR (loop->etype) = bitOffset;
-               sum += (loop->bitVar / 8);
-               bitOffset += (loop->bitVar % 8);
-           }
-           /* 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 {
-           checkDecl (loop);
+           /* 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 function then do the arguments for it */
-       if (funcInChain (loop->type)) {
-           processFuncArgs (loop, 1);
-       }
-
        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);
 }
@@ -1110,49 +1183,79 @@ compStructSize (int su, structdef * sdef)
 /* checkSClass - check the storage class specification              */
 /*------------------------------------------------------------------*/
 static void 
-checkSClass (symbol * sym)
+checkSClass (symbol * sym, int isProto)
 {
-  /* type is literal can happen foe enums change
+  sym_link *t;
+  
+  if (getenv("DEBUG_SANITY")) {
+    fprintf (stderr, "checkSClass: %s \n", sym->name);
+  }
+  
+  /* 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_SCLS (sym->etype) == S_CONSTANT)
-    {
+      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;
-      SPEC_CONST (sym->etype) = 1;
     }
+  }
 
   /* 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 */
@@ -1173,23 +1276,22 @@ checkSClass (symbol * sym)
       sym->ival = NULL;
     }
 
-  /* if this is an automatic symbol then */
-  /* storage class will be ignored and   */
-  /* symbol will be allocated on stack/  */
-  /* data depending on flag             */
-  if (sym->level &&
-      (options.stackAuto || reentrant) &&
-      (SPEC_SCLS (sym->etype) != S_AUTO &&
-       SPEC_SCLS (sym->etype) != S_FIXED &&
-       SPEC_SCLS (sym->etype) != S_REGISTER &&
-       SPEC_SCLS (sym->etype) != S_STACK &&
-       SPEC_SCLS (sym->etype) != S_XSTACK &&
-       SPEC_SCLS (sym->etype) != S_CONSTANT))
-    {
-      werror (E_AUTO_ASSUMED, sym->name);
+  /* 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 ||
+        SPEC_SCLS (sym->etype) == S_REGISTER ||
+        SPEC_SCLS (sym->etype) == S_STACK ||
+        SPEC_SCLS (sym->etype) == S_XSTACK)) {
       SPEC_SCLS (sym->etype) = S_AUTO;
+    } else {
+      /* storage class may only be specified for statics */
+      if (!IS_STATIC(sym->etype)) {
+       werror (E_AUTO_ASSUMED, sym->name);
+      }
     }
-
+  }
+  
   /* automatic symbols cannot be given   */
   /* an absolute address ignore it      */
   if (sym->level &&
@@ -1205,6 +1307,7 @@ checkSClass (symbol * sym)
   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);
 
@@ -1216,22 +1319,24 @@ checkSClass (symbol * sym)
       SPEC_BSTR (sym->etype) = 0;
     }
 
-  /* variables declared in CODE space must have */
-  /* initializers if not an extern */
-  if (SPEC_SCLS (sym->etype) == S_CODE &&
-      sym->ival == NULL &&
-      !sym->level &&
-      port->mem.code_ro &&
-      !IS_EXTERN (sym->etype) &&
-      !funcInChain (sym->type))
-    werror (E_CODE_NO_INIT, sym->name);
+  if (!isProto) {
+    /* variables declared in CODE space must have */
+    /* initializers if not an extern */
+    if (SPEC_SCLS (sym->etype) == S_CODE &&
+       sym->ival == NULL &&
+       //!sym->level &&
+       port->mem.code_ro &&
+       !IS_EXTERN (sym->etype) &&
+       !funcInChain (sym->type))
+      werror (E_CODE_NO_INIT, sym->name);
+  }
 
   /* if parameter or local variable then change */
   /* the storage class to reflect where the var will go */
   if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED &&
       !IS_STATIC(sym->etype))
     {
-      if (options.stackAuto || (currFunc && IS_RENT (currFunc->etype)))
+      if (options.stackAuto || (currFunc && IFFUNC_ISREENT (currFunc->type)))
        {
          SPEC_SCLS (sym->etype) = (options.useXstack ?
                                    S_XSTACK : S_STACK);
@@ -1242,7 +1347,8 @@ checkSClass (symbol * sym)
           * 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);
        }
@@ -1264,7 +1370,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;
     }
@@ -1274,10 +1380,10 @@ changePointer (symbol * sym)
 /* checkDecl - does semantic validation of a declaration                   */
 /*------------------------------------------------------------------*/
 int 
-checkDecl (symbol * sym)
+checkDecl (symbol * sym, int isProto)
 {
 
-  checkSClass (sym);           /* check the storage class      */
+  checkSClass (sym, isProto);          /* check the storage class      */
   changePointer (sym);         /* change pointers if required */
 
   /* if this is an array without any dimension
@@ -1297,11 +1403,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;
     }
@@ -1381,11 +1487,11 @@ computeType (sym_link * type1, sym_link * type2)
   else if (IS_BITVAR (etype2) && !IS_BITVAR (etype1))
     rType = copyLinkChain (type1);
   else
-    /* if one of them is a pointer then that
+    /* if one of them is a pointer or array then that
        prevails */
-  if (IS_PTR (type1))
+  if (IS_PTR (type1) || IS_ARRAY (type1))
     rType = copyLinkChain (type1);
-  else if (IS_PTR (type2))
+  else if (IS_PTR (type2) || IS_ARRAY (type2))
     rType = copyLinkChain (type2);
   else if (getSize (type1) > getSize (type2))
     rType = copyLinkChain (type1);
@@ -1393,10 +1499,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 then make this unsigned */
-  if ((SPEC_USIGN (etype1) || SPEC_USIGN (etype2)) && !IS_FLOAT (reType))
+  /* 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))) &&
+      !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))
@@ -1405,11 +1519,11 @@ computeType (sym_link * type1, sym_link * type2)
   return rType;
 }
 
-/*------------------------------------------------------------------*/
-/* checkType - will do type check return 1 if match                 */
-/*------------------------------------------------------------------*/
-int 
-checkType (sym_link * dest, sym_link * src)
+/*--------------------------------------------------------------------*/
+/* compareType - will do type check return 1 if match, -1 if castable */
+/*--------------------------------------------------------------------*/
+int
+compareType (sym_link * dest, sym_link * src)
 {
   if (!dest && !src)
     return 1;
@@ -1425,16 +1539,27 @@ checkType (sym_link * dest, sym_link * src)
     {
       if (IS_DECL (src))
        {
-         if (DCL_TYPE (src) == DCL_TYPE (dest))
-           return checkType (dest->next, src->next);
-         else if (IS_PTR (src) && IS_PTR (dest))
-           return -1;
-         else if (IS_PTR (dest) && IS_ARRAY (src))
+         if (DCL_TYPE (src) == DCL_TYPE (dest)) {
+           if (IS_FUNC(src)) {
+             //checkFunction(src,dest);
+           }
+           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;
-         else if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src))
-           return -1 * checkType (dest->next, src);
-         else
-           return 0;
+         if (IS_PTR (dest) && IS_ARRAY (src)) {
+           value *val=aggregateToPointer (valFromType(src));
+           int res=compareType (dest, val->type);
+           Safe_free(val->type);
+           Safe_free(val);
+           return res;
+         }
+         if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src))
+           return compareType (dest->next, src);
+         return 0;
        }
       else if (IS_PTR (dest) && IS_INTEGRAL (src))
        return -1;
@@ -1456,17 +1581,6 @@ checkType (sym_link * dest, sym_link * src)
       SPEC_NOUN (src) == V_VOID)
     return -1;
 
-  /* char === to short */
-  if (SPEC_NOUN (dest) == V_CHAR &&
-      SPEC_NOUN (src) == V_INT &&
-      SPEC_SHORT (src))
-    return (SPEC_USIGN (src) == SPEC_USIGN (dest) ? 1 : -2);
-
-  if (SPEC_NOUN (src) == V_CHAR &&
-      SPEC_NOUN (dest) == V_INT &&
-      SPEC_SHORT (dest))
-    return (SPEC_USIGN (src) == SPEC_USIGN (dest) ? 1 : -2);
-
   /* if they are both bitfields then if the lengths
      and starts don't match */
   if (IS_BITFIELD (dest) && IS_BITFIELD (src) &&
@@ -1496,36 +1610,35 @@ checkType (sym_link * dest, sym_link * src)
   if (SPEC_LONG (dest) != SPEC_LONG (src))
     return -1;
 
-  if (SPEC_SHORT (dest) != SPEC_SHORT (src))
-    return -1;
-
   if (SPEC_USIGN (dest) != SPEC_USIGN (src))
-    return -2;
+    return -1;
 
   return 1;
 }
 
 /*------------------------------------------------------------------*/
-/* inCalleeSaveList - return 1 if found in calle save list          */
+/* inCalleeSaveList - return 1 if found in callee save list          */
 /*------------------------------------------------------------------*/
-bool 
-inCalleeSaveList (char *s)
+static int
+calleeCmp(void *p1, void *p2)
 {
-  int i;
-
-  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);
 }
 
 /*-----------------------------------------------------------------*/
-/* aggregateArgToPointer:  change an agggregate type function      */
+/* aggregateToPointer:  change an agggregate type function      */
 /*         argument to a pointer to that type.     */
 /*-----------------------------------------------------------------*/
-void 
-aggregateArgToPointer (value * val)
+value *
+aggregateToPointer (value * val)
 {
   if (IS_AGGREGATE (val->type))
     {
@@ -1537,7 +1650,7 @@ aggregateArgToPointer (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;
        }
 
@@ -1552,16 +1665,13 @@ aggregateArgToPointer (value * val)
          DCL_TYPE (val->type) = PPOINTER;
          break;
        case S_FIXED:
-         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;
-           }
-         /* fall through! */
+         if (SPEC_OCLS(val->etype)) {
+           DCL_TYPE(val->type)=PTR_TYPE(SPEC_OCLS(val->etype));
+         } else {
+           // this happens for (external) function parameters
+           DCL_TYPE (val->type) = port->unqualified_pointer;
+         }
+         break;
        case S_AUTO:
        case S_DATA:
        case S_REGISTER:
@@ -1577,9 +1687,9 @@ aggregateArgToPointer (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 */
       /* change the type of the symbol as well */
       if (val->sym)
@@ -1588,15 +1698,16 @@ aggregateArgToPointer (value * val)
          val->sym->etype = getSpec (val->sym->type);
        }
     }
+  return val;
 }
 /*------------------------------------------------------------------*/
 /* checkFunction - does all kinds of check on a function            */
 /*------------------------------------------------------------------*/
 int 
-checkFunction (symbol * sym)
+checkFunction (symbol * sym, symbol *csym)
 {
-  symbol *csym;
   value *exargs, *acargs;
+  value *checkValue;
   int argCnt = 0;
 
   if (getenv("DEBUG_SANITY")) {
@@ -1630,61 +1741,86 @@ checkFunction (symbol * sym)
 
   /* check if this function is defined as calleeSaves
      then mark it as such */
-  sym->calleeSave = inCalleeSaveList (sym->name);
+  FUNC_CALLEESAVES(sym->type) = inCalleeSaveList (sym->name);
 
   /* if interrupt service routine  */
   /* then it cannot have arguments */
-  if (sym->args && IS_ISR (sym->etype) && !IS_VOID (sym->args->type))
+  if (IFFUNC_ARGS(sym->type) && FUNC_ISISR (sym->type))
     {
-      werror (E_INT_ARGS, sym->name);
-      sym->args = NULL;
+      if (!IS_VOID(FUNC_ARGS(sym->type)->type)) {
+       werror (E_INT_ARGS, sym->name);
+       FUNC_ARGS(sym->type)=NULL;
+      }
     }
 
-  if (!(csym = findSym (SymbolTab, sym, sym->name)))
+  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);
+    }
+  }
+
+  if (!csym && !(csym = findSym (SymbolTab, sym, sym->name)))
     return 1;                  /* not defined nothing more to check  */
 
   /* check if body already present */
-  if (csym && csym->fbody)
+  if (csym && IFFUNC_HASBODY(csym->type))
     {
       werror (E_FUNC_BODY, sym->name);
       return 0;
     }
 
   /* check the return value type   */
-  if (checkType (csym->type, sym->type) <= 0)
+  if (compareType (csym->type, sym->type) <= 0)
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "type");
-      werror (E_CONTINUE, "previous definition type ");
-      printTypeChain (csym->type, stderr);
-      fprintf (stderr, "\n");
-      werror (E_CONTINUE, "current definition type ");
-      printTypeChain (sym->type, stderr);
-      fprintf (stderr, "\n");
+      printFromToType(csym->type, sym->type);
       return 0;
     }
 
-  if (SPEC_INTRTN (csym->etype) != SPEC_INTRTN (sym->etype))
+  if (FUNC_ISISR (csym->type) != FUNC_ISISR (sym->type))
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "interrupt");
-      return 0;
     }
 
-  if (SPEC_BANK (csym->etype) != SPEC_BANK (sym->etype))
+  if (FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type))
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "using");
-      return 0;
     }
 
-  /* compare expected agrs with actual args */
-  exargs = csym->args;
-  acargs = sym->args;
+  if (IFFUNC_ISNAKED (csym->type) != IFFUNC_ISNAKED (sym->type))
+    {
+      werror (E_PREV_DEF_CONFLICT, csym->name, "_naked");
+    }
+
+  /* compare expected args with actual args */
+  exargs = FUNC_ARGS(csym->type);
+  acargs = FUNC_ARGS(sym->type);
 
   /* for all the expected args do */
   for (argCnt = 1;
        exargs && acargs;
        exargs = exargs->next, acargs = acargs->next, argCnt++)
     {
-      value *checkValue;
+      if (getenv("DEBUG_SANITY")) {
+       fprintf (stderr, "checkFunction: %s ", exargs->name);
+      }
+      /* make sure the type is complete and sane */
+      checkTypeSanity(exargs->etype, exargs->name);
+
       /* If the actual argument is an array, any prototype
        * will have modified it to a pointer. Duplicate that
        * change here.
@@ -1692,16 +1828,17 @@ checkFunction (symbol * sym)
       if (IS_AGGREGATE (acargs->type))
        {
          checkValue = copyValue (acargs);
-         aggregateArgToPointer (checkValue);
+         aggregateToPointer (checkValue);
        }
       else
        {
          checkValue = acargs;
        }
 
-      if (checkType (exargs->type, checkValue->type) <= 0)
+      if (compareType (exargs->type, checkValue->type) <= 0)
        {
          werror (E_ARG_TYPE, argCnt);
+         printFromToType(exargs->type, checkValue->type);
          return 0;
        }
     }
@@ -1714,7 +1851,8 @@ checkFunction (symbol * sym)
   /* replace with this defition */
   sym->cdef = csym->cdef;
   deleteSym (SymbolTab, csym, csym->name);
-  addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
+  deleteFromSeg(csym);
+  addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
   if (IS_EXTERN (csym->etype) && !
       IS_EXTERN (sym->etype))
     {
@@ -1723,30 +1861,63 @@ checkFunction (symbol * sym)
   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       */
 /*-----------------------------------------------------------------*/
 void 
-processFuncArgs (symbol * func, int ignoreName)
+processFuncArgs (symbol * func)
 {
   value *val;
   int pNum = 1;
+  sym_link *funcType=func->type;
+
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "SDCCsymt.c:processFuncArgs(%s)\n", func->name);
+
+  // if this is a pointer to a function
+  if (IS_PTR(funcType)) {
+    funcType=funcType->next;
+  }
 
   /* if this function has variable argument list */
   /* then make the function a reentrant one    */
-  if (func->hasVargs)
-    SPEC_RENT (func->etype) = 1;
+  if (IFFUNC_HASVARARGS(funcType) || (options.stackAuto && !func->cdef))
+    FUNC_ISREENT(funcType)=1;
 
   /* check if this function is defined as calleeSaves
      then mark it as such */
-  func->calleeSave = inCalleeSaveList (func->name);
+  FUNC_CALLEESAVES(funcType) = inCalleeSaveList (func->name);
 
-  val = func->args;            /* loop thru all the arguments   */
+  /* loop thru all the arguments   */
+  val = FUNC_ARGS(funcType);
 
   /* if it is void then remove parameters */
   if (val && IS_VOID (val->type))
     {
-      func->args = NULL;
+      FUNC_ARGS(funcType) = NULL;
       return;
     }
 
@@ -1756,19 +1927,24 @@ processFuncArgs (symbol * func, int ignoreName)
   /* 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 (!func->hasVargs &&
-         (*port->reg_parm) (val->type))
+      if (!IFFUNC_HASVARARGS(funcType) &&
+         (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))
        {
-         aggregateArgToPointer (val);
+         aggregateToPointer (val);
        }
+
       val = val->next;
       pNum++;
     }
@@ -1777,17 +1953,17 @@ processFuncArgs (symbol * func, int ignoreName)
   if (func->cdef) {
     /* ignore --stack-auto for this one, we don't know how it is compiled */
     /* simply trust on --int-long-reent or --float-reent */
-    if (IS_RENT(func->etype)) {
+    if (IFFUNC_ISREENT(funcType)) {
       return;
     }
   } else {
     /* if this function is reentrant or */
     /* automatics r 2b stacked then nothing */
-    if (IS_RENT (func->etype) || options.stackAuto)
+    if (IFFUNC_ISREENT (funcType) || options.stackAuto)
       return;
   }
 
-  val = func->args;
+  val = FUNC_ARGS(funcType);
   pNum = 1;
   while (val)
     {
@@ -1796,30 +1972,38 @@ processFuncArgs (symbol * func, int ignoreName)
       /* 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;
     }
 }
@@ -1853,10 +2037,13 @@ void PT(sym_link *type)
 /*-----------------------------------------------------------------*/
 /* printTypeChain - prints the type chain in human readable form   */
 /*-----------------------------------------------------------------*/
-void 
-printTypeChain (sym_link * type, FILE * of)
+void
+printTypeChain (sym_link * start, FILE * of)
 {
   int nlr = 0;
+  value *args;
+  sym_link * type, * search;
+  STORAGE_CLASS scls;
 
   if (!of)
     {
@@ -1864,93 +2051,128 @@ printTypeChain (sym_link * type, FILE * of)
       nlr = 1;
     }
 
+  if (start==NULL) {
+    fprintf (of, "void");
+    return;
+  }
+
+  /* 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 ");
+             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, "_generic * ");
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
+             fprintf (of, "generic* ");
              break;
            case CPOINTER:
-             fprintf (of, "_code * ");
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
+             fprintf (of, "code* ");
              break;
            case FPOINTER:
-             fprintf (of, "_far * ");
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
+             fprintf (of, "xdata* ");
              break;
            case EEPPOINTER:
-             fprintf (of, "_eeprom * ");
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
+             fprintf (of, "eeprom* ");
              break;
-
            case POINTER:
-             fprintf (of, "_near * ");
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
+             fprintf (of, "near* ");
              break;
            case IPOINTER:
-             fprintf (of, "_idata *");
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
+             fprintf (of, "idata* ");
              break;
            case PPOINTER:
-             fprintf (of, "_pdata *");
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
+             fprintf (of, "pdata* ");
              break;
            case UPOINTER:
-             fprintf (of, " _unkown *");
-             if (DCL_PTR_CONST (type))
-               fprintf (of, "const ");
+             fprintf (of, "unknown* ");
              break;
            case ARRAY:
-             fprintf (of, "array of ");
+             if (DCL_ELEM(type)) {
+               fprintf (of, "[%d] ", DCL_ELEM(type));
+             } else {
+               fprintf (of, "[] ");
+             }
              break;
            }
        }
       else
        {
          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 ");
-             if (IS_SHORT (type))
-               fprintf (of, "short ");
-             fprintf (of, "int ");
+               fprintf (of, "long-");
+             fprintf (of, "int");
              break;
 
            case V_CHAR:
-             fprintf (of, "char ");
+             fprintf (of, "char");
              break;
 
            case V_VOID:
-             fprintf (of, "void ");
+             fprintf (of, "void");
              break;
 
            case V_FLOAT:
-             fprintf (of, "float ");
+             fprintf (of, "float");
              break;
 
            case V_STRUCT:
@@ -1958,230 +2180,207 @@ printTypeChain (sym_link * type, FILE * of)
              break;
 
            case V_SBIT:
-             fprintf (of, "sbit ");
+             fprintf (of, "sbit");
              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:
-             fprintf (of, "double ");
+             fprintf (of, "double");
              break;
 
            default:
-             fprintf (of, "unknown type ");
+             fprintf (of, "unknown type");
              break;
            }
        }
-      type = type->next;
+      /* 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           */
-/*-----------------------------------------------------------------*/
-void 
-cdbTypeInfo (sym_link * type, FILE * of)
+/*--------------------------------------------------------------------*/
+/* printTypeChainRaw - prints the type chain in human readable form   */
+/*                     in the raw data structure ordering             */
+/*--------------------------------------------------------------------*/
+void
+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 if (IS_SHORT (type))
-               fprintf (of, "SS");
-             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", SPEC_INTRTN (sym->etype),
-            SPEC_INTN (sym->etype), SPEC_BANK (sym->etype));
-  /* 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 */
@@ -2222,25 +2421,127 @@ symbol *__muldiv[3][3][2];
 sym_link *__multypes[3][2];
 /* Dims: to/from float, BYTE/WORD/DWORD, SIGNED/USIGNED */
 symbol *__conv[2][3][2];
+/* Dims: shift left/shift right, BYTE/WORD/DWORD, SIGNED/UNSIGNED */
+symbol *__rlrr[2][3][2];
 
 sym_link *floatType;
 
-static void 
-_makeRegParam (symbol * sym)
+static char *
+_mangleFunctionName(char *in)
 {
-  value *val;
-
-  val = sym->args;             /* loop thru all the arguments   */
-
-  /* reset regparm for the port */
-  (*port->reset_regparms) ();
-  while (val)
+  if (port->getMangledFunctionName) 
     {
-      SPEC_REGPARM (val->etype) = 1;
-      val = val->next;
+      return port->getMangledFunctionName(in);
+    }
+  else
+    {
+      return in;
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* typeFromStr - create a typechain from an encoded string         */
+/* basic types -       'c' - char                                 */
+/*                     's' - short                                */
+/*                     'i' - int                                  */
+/*                     'l' - long                                 */
+/*                      'f' - float                               */
+/*                      'v' - void                                */
+/*                      '*' - pointer - default (GPOINTER)        */
+/* modifiers -          'u' - unsigned                             */
+/* pointer modifiers -  'g' - generic                              */
+/*                      '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(DECLARATOR);
+    int usign = 0;
+
+    do {
+       sym_link *nr;
+       switch (*s) {
+       case 'u' : 
+           usign = 1;
+           s++;
+           continue ;
+           break ;
+       case 'c':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_CHAR;
+           break;
+       case 's':
+       case 'i':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_INT;
+           break;
+       case 'l':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_INT;
+           SPEC_LONG(r) = 1;
+           break;
+       case 'f':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_FLOAT;
+           break;
+       case 'v':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_VOID;
+           break;
+       case '*':
+           DCL_TYPE(r) = port->unqualified_pointer;
+           break;
+       case 'g':
+       case 'x':
+       case 'p':
+       case 'd':
+       case 'F':
+           assert(*(s+1)=='*');
+           nr = newLink(DECLARATOR);
+           nr->next = r;
+           r = nr;
+           switch (*s) {
+           case 'g':
+               DCL_TYPE(r) = GPOINTER;
+               break;
+           case 'x':
+               DCL_TYPE(r) = FPOINTER;
+               break;
+           case 'p':
+               DCL_TYPE(r) = CPOINTER;
+               break;
+           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, __FILE__, __LINE__, 
+                  "typeFromStr: unknown type");
+           break;
+       }
+       if (IS_SPEC(r) && usign) {
+           SPEC_USIGN(r) = 1;
+           usign = 0;
+       }
+       s++;
+    } while (*s);
+    return r;
+}
+
 /*-----------------------------------------------------------------*/
 /* initCSupport - create functions for C support routines          */
 /*-----------------------------------------------------------------*/
@@ -2259,14 +2560,23 @@ initCSupport ()
   {
     "s", "u"
   };
+  const char *srlrr[] =
+  {
+    "rl", "rr"
+  };
+
+  int bwd, su, muldivmod, tofrom, rlrr;
 
-  int bwd, su, muldivmod, tofrom;
+  if (getenv("SDCC_NO_C_SUPPORT")) {
+    /* for debugging only */
+    return;
+  }
 
   floatType = newFloatLink ();
 
   for (bwd = 0; bwd < 3; bwd++)
     {
-      sym_link *l;
+      sym_link *l = NULL;
       switch (bwd)
        {
        case 0:
@@ -2305,33 +2615,141 @@ initCSupport ()
            {
              if (tofrom)
                {
-                 sprintf (buffer, "__fs2%s%s", ssu[su], sbwd[bwd]);
+                 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]);
+                 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]);
+              __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;
+           }
+       }
+    }
+
+  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 (buffer, __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
-             SPEC_NONBANKED (__muldiv[muldivmod][bwd][su]->etype) = 1;
-             if (bwd < port->muldiv.force_reg_param_below)
-               _makeRegParam (__muldiv[muldivmod][bwd][su]);
+             __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++)
+           {
+             SNPRINTF (buffer, sizeof(buffer),
+                       "_%s%s%s",
+                      srlrr[rlrr],
+                      ssu[su],
+                      sbwd[bwd]);
+              __rlrr[rlrr][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[0][0], 2, options.intlong_rent);
+             FUNC_NONBANKED (__rlrr[rlrr][bwd][su]->type) = 1;
+           }
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* initBuiltIns - create prototypes for builtin functions          */
+/*-----------------------------------------------------------------*/
+void initBuiltIns()
+{
+    int i;
+    symbol *sym;
+
+    if (!port->builtintable) return ;
+
+    for (i = 0 ; port->builtintable[i].name ; i++) {
+       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.
 }