undid the hackup of const and volatile, the problem is much bigger
[fw/sdcc] / src / SDCCsymt.c
index d19342b5faa11f98638a465218c0201b1f863839..231e4f65b1b13c1514604bd5c944578cf663b70b 100644 (file)
@@ -138,7 +138,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,7 +287,7 @@ 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 */
@@ -298,11 +298,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,7 +318,7 @@ 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;
 }
 
@@ -347,8 +348,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,18 +363,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_SCLS (type) = 
        SPEC_CONST (type) =
        SPEC_VOLATILE (type) = 0;
     }
@@ -385,7 +383,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,7 +392,7 @@ 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 +420,7 @@ addDecl (symbol * sym, int type, sym_link * p)
     }
   else
     {
-      head = tail = newLink ();
+      head = tail = newLink (DECLARATOR);
       DCL_TYPE (head) = type;
     }
 
@@ -457,22 +455,26 @@ addDecl (symbol * sym, int type, sym_link * p)
     }
 
   /* if the type is an unknown pointer and has
-     a tspec then take the storage class const & volatile
+     a tspec then take the const & volatile
      attribute from the tspec & make it those of this
      symbol */
+
   if (p &&
-      !IS_SPEC (p) &&
-      //DCL_TYPE (p) == UPOINTER &&
+      IS_DECL (p) &&
+      DCL_TYPE (p) == UPOINTER &&
       DCL_TSPEC (p))
     {
+      // only for declarators
+      wassert (IS_DECL(sym->type));
+
       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_PTR_CONST (sym->type) = SPEC_CONST (DCL_TSPEC (p));
+      DCL_PTR_VOLATILE (sym->type) = SPEC_VOLATILE (DCL_TSPEC (p));
       DCL_TSPEC (p) = NULL;
     }
 
@@ -508,7 +510,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,17 +559,8 @@ 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");
-    exit (1);
-#else
     werror (E_SYNTAX_ERROR, yytext);
-    // the show must go on
-    return newIntLink();
-#endif
   }
 
   if (SPEC_NOUN(src)) {
@@ -596,17 +589,6 @@ mergeSpec (sym_link * dest, sym_link * src, char *name)
 
   /* copy all the specifications  */
 
-  // we really should do: 
-#if 0
-  if (SPEC_what(src)) {
-    if (SPEC_what(dest)) {
-      werror(W_DUPLICATE_SPEC, "what");
-    }
-    SPEC_what(dst)|=SPEC_what(src);
-  }
-#endif
-  // but there are more important thing right now
-
   SPEC_LONG (dest) |= SPEC_LONG (src);
   dest->select.s._short|=src->select.s._short;
   SPEC_USIGN (dest) |= SPEC_USIGN (src);
@@ -621,7 +603,10 @@ mergeSpec (sym_link * dest, sym_link * src, char *name)
   SPEC_BLEN (dest) |= SPEC_BLEN (src);
   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);
 
@@ -633,27 +618,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;
 }
 
 /*------------------------------------------------------------------*/
@@ -665,7 +636,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;
 }
 
@@ -692,8 +663,7 @@ newCharLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_CHAR;
 
   return p;
@@ -707,8 +677,7 @@ newFloatLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_FLOAT;
 
   return p;
@@ -722,8 +691,7 @@ newLongLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_INT;
   SPEC_LONG (p) = 1;
 
@@ -738,8 +706,7 @@ newIntLink ()
 {
   sym_link *p;
 
-  p = newLink ();
-  p->class = SPECIFIER;
+  p = newLink (SPECIFIER);
   SPEC_NOUN (p) = V_INT;
 
   return p;
@@ -782,10 +749,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:
@@ -793,6 +764,7 @@ getSize (sym_link * p)
     case EEPPOINTER:
     case FPOINTER:
     case CPOINTER:
+    case FUNCTION:
       return (FPTRSIZE);
     case GPOINTER:
       return (GPTRSIZE);
@@ -841,8 +813,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:
@@ -852,6 +822,7 @@ bitsForType (sym_link * p)
     case EEPPOINTER:
     case FPOINTER:
     case CPOINTER:
+    case FUNCTION:
       return (FPTRSIZE * 8);
     case GPOINTER:
       return (GPTRSIZE * 8);
@@ -980,13 +951,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 */
@@ -1020,25 +994,27 @@ 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));
+           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();
 }
 
 /*------------------------------------------------------------------*/
@@ -1073,7 +1049,7 @@ compStructSize (int su, structdef * sdef)
     while (loop) {
 
        /* create the internal name for this variable */
-       sprintf (loop->rname, "_%s", loop->name);
+       SNPRINTF (loop->rname, sizeof(loop->rname), "_%s", loop->name);
        loop->offset = (su == UNION ? sum = 0 : sum);
        SPEC_VOLATILE (loop->etype) |= (su == UNION ? 1 : 0);
 
@@ -1108,13 +1084,6 @@ compStructSize (int su, structdef * sdef)
            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 */
@@ -1167,22 +1136,36 @@ checkSClass (symbol * sym, int isProto)
     }
   
   /* 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
+  /* The PIC port uses a different peep hole optimizer based on "pCode" */
+  if (!TARGET_IS_PIC)
+#endif
+
+    if (IS_ABSOLUTE (sym->etype))
+      SPEC_VOLATILE (sym->etype) = 1;
   
+
   /* global variables declared const put into code */
+  /* if no other storage class specified */
   if (sym->level == 0 &&
-      SPEC_CONST (sym->etype)) {
+      SPEC_CONST (sym->etype) &&
+      SPEC_SCLS(sym->etype) == S_FIXED &&
+      !IS_FUNC(sym->type)) {
     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) {
+    if (IS_SPEC(sym->type)) {
+      SPEC_CONST (sym->type) = 1;
+    } else {
+      DCL_PTR_CONST (sym->type) = 1;
+    }
+  }
 
   /* if bit variable then no storage class can be */
   /* specified since bit is already a storage */
@@ -1295,7 +1278,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;
     }
@@ -1328,11 +1311,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;
     }
@@ -1412,11 +1395,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);
@@ -1466,6 +1449,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)) {
@@ -1473,7 +1459,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,6 +1528,7 @@ inCalleeSaveList (char *s)
 {
   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;
@@ -1567,7 +1553,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;
        }
 
@@ -1584,23 +1570,11 @@ aggregateToPointer (value * val)
        case S_FIXED:
          if (SPEC_OCLS(val->etype)) {
            DCL_TYPE(val->type)=PTR_TYPE(SPEC_OCLS(val->etype));
-           break;
+         } else {
+           // this happens for (external) function parameters
+           DCL_TYPE (val->type) = port->unqualified_pointer;
          }
-
-         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;
-         }
-         /* fall through! */
+         break;
        case S_AUTO:
        case S_DATA:
        case S_REGISTER:
@@ -1616,7 +1590,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 */
@@ -1670,7 +1644,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 */
@@ -1682,6 +1656,26 @@ 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);
+    }
+  }
+
   if (!csym && !(csym = findSym (SymbolTab, sym, sym->name)))
     return 1;                  /* not defined nothing more to check  */
 
@@ -1760,6 +1754,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))
@@ -1789,7 +1784,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
@@ -1812,13 +1807,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))
@@ -1853,30 +1852,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;
     }
 }
@@ -1915,6 +1922,7 @@ printTypeChain (sym_link * start, FILE * of)
 {
   int nlr = 0;
   sym_link * type, * search;
+  STORAGE_CLASS scls;
 
   if (!of)
     {
@@ -1927,99 +1935,98 @@ 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)
     ;
+  scls=SPEC_SCLS(type);
   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" : " "));
              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, "unkown* ");
              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;
 
@@ -2056,12 +2063,12 @@ 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");
@@ -2325,6 +2332,109 @@ _mangleFunctionName(char *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          */
 /*-----------------------------------------------------------------*/
@@ -2359,7 +2469,7 @@ initCSupport ()
 
   for (bwd = 0; bwd < 3; bwd++)
     {
-      sym_link *l;
+      sym_link *l = NULL;
       switch (bwd)
        {
        case 0:
@@ -2398,13 +2508,13 @@ 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);
                }
            }
        }
@@ -2416,7 +2526,8 @@ initCSupport ()
        {
          for (su = 0; su < 2; su++)
            {
-             sprintf (buffer, "_%s%s%s",
+             SNPRINTF (buffer, sizeof(buffer), 
+                       "_%s%s%s",
                       smuldivmod[muldivmod],
                       ssu[su],
                       sbwd[bwd]);
@@ -2432,7 +2543,8 @@ initCSupport ()
        {
          for (su = 0; su < 2; su++)
            {
-             sprintf (buffer, "_%s%s%s",
+             SNPRINTF (buffer, sizeof(buffer), 
+                       "_%s%s%s",
                       srlrr[rlrr],
                       ssu[su],
                       sbwd[bwd]);
@@ -2442,3 +2554,41 @@ initCSupport ()
        }
     }
 }
+
+/*-----------------------------------------------------------------*/
+/* 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.
+}