Use 'ao-dbg' instead of 's51' to communicate with TeleMetrum
[fw/sdcc] / src / SDCCast.c
index 94d3c949d25dbc7b91f1085067da71d4d6a73488..3470ac464fd14634807ae340f78bc699ce23901d 100644 (file)
@@ -31,6 +31,11 @@ set *astList = NULL;
 set *operKeyReset = NULL;
 ast *staticAutos = NULL;
 int labelKey = 1;
+static struct {
+  int count;            /* number of inline functions inserted */
+  symbol * retsym;      /* variable for inlined function return value */
+  symbol * retlab;      /* label ending inlined function (virtual return) */
+} inlineState;
 
 #define LRVAL(x) x->left->rvalue
 #define RRVAL(x) x->right->rvalue
@@ -79,13 +84,12 @@ static ast *
 newAst_ (unsigned type)
 {
   ast *ex;
-  static int oldLineno = 0;
 
   ex = Safe_alloc ( sizeof (ast));
 
   ex->type = type;
-  ex->lineno = (noLineno ? oldLineno : lineno);
-  ex->filename = filename;
+  ex->lineno = (noLineno ? 0 : lexLineno);
+  ex->filename = lexFilename;
   ex->level = NestLevel;
   ex->block = currBlockno;
   ex->initMode = inInitMode;
@@ -164,7 +168,7 @@ newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
 }
 
 /*-----------------------------------------------------------------*/
-/* copyAstValues - copies value portion of ast if needed     */
+/* copyAstValues - copies value portion of ast if needed           */
 /*-----------------------------------------------------------------*/
 void
 copyAstValues (ast * dest, ast * src)
@@ -218,6 +222,7 @@ copyAst (ast * src)
   dest = Safe_alloc ( sizeof (ast));
 
   dest->type = src->type;
+  dest->filename = src->filename;
   dest->lineno = src->lineno;
   dest->level = src->level;
   dest->funcName = src->funcName;
@@ -386,6 +391,9 @@ ast * createRMW (ast *target, unsigned op, ast *operand)
         tempvar1 = replaceAstWithTemporary(&(target->left));
       if (hasSEFcalls(target->right))
         tempvar2 = replaceAstWithTemporary(&(target->right));
+    } else if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
+      /* illegal pre/post-increment/decrement */
+      werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
     } else {
       /* we would have to handle '.', but it is not generated any more */
       wassertl(target->opval.op != '.', "obsolete opcode in tree");
@@ -532,7 +540,6 @@ resolveSymbols (ast * tree)
             werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
                       tree->falseLabel->name);
         }
-
     }
 
   /* if this is a label resolve it from the labelTab */
@@ -540,7 +547,6 @@ resolveSymbols (ast * tree)
       tree->opval.val->sym &&
       tree->opval.val->sym->islbl)
     {
-
       symbol *csym = findSym (LabelTab, tree->opval.val->sym,
                               tree->opval.val->sym->name);
 
@@ -558,10 +564,9 @@ resolveSymbols (ast * tree)
       tree->opval.val->sym &&
       !tree->opval.val->sym->implicit)
     {
-
       symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
 
-      /* if found in the symbol table & they r not the same */
+      /* if found in the symbol table & they are not the same */
       if (csym && tree->opval.val->sym != csym)
         {
           tree->opval.val->sym = csym;
@@ -570,11 +575,10 @@ resolveSymbols (ast * tree)
         }
 
       /* if not found in the symbol table */
-      /* mark it as undefined assume it is */
-      /* an integer in data space         */
+      /* mark it as undefined & assume it */
+      /* is an integer in data space      */
       if (!csym && !tree->opval.val->sym->implicit)
         {
-
           /* if this is a function name then */
           /* mark it as returning an int     */
           if (tree->funcName)
@@ -608,17 +612,18 @@ resolveChildren:
   return tree;
 }
 
-/*-----------------------------------------------------------------*/
-/* setAstLineno - walks a ast tree & sets the line number          */
-/*-----------------------------------------------------------------*/
-int setAstLineno (ast * tree, int lineno)
+/*------------------------------------------------------------------------*/
+/* setAstFileLine - walks a ast tree & sets the file name and line number */
+/*------------------------------------------------------------------------*/
+int setAstFileLine (ast * tree, char *filename, int lineno)
 {
   if (!tree)
     return 0;
 
+  tree->filename = filename;
   tree->lineno = lineno;
-  setAstLineno (tree->left, lineno);
-  setAstLineno (tree->right, lineno);
+  setAstFileLine (tree->left, filename, lineno);
+  setAstFileLine (tree->right, filename, lineno);
   return 0;
 }
 
@@ -775,15 +780,15 @@ processParms (ast *func,
   else
     functype = func->ftype;
 
-  /* if the function is being called via a pointer &   */
-  /* it has not been defined reentrant then we cannot */
-  /* have parameters                                   */
+  /* if the function is being called via a pointer &  */
+  /* it has not been defined reentrant then we cannot */
+  /* have parameters                                  */
   /* PIC16 port can... */
   if (!TARGET_IS_PIC16)
     {
       if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
         {
-          werror (W_NONRENT_ARGS);
+          werror (E_NONRENT_ARGS);
           fatalError++;
           return 1;
         }
@@ -845,8 +850,12 @@ processParms (ast *func,
       ast *newType = NULL;
       sym_link *ftype;
 
-      if (IS_CAST_OP (*actParm)
-          || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
+      /* don't perform integer promotion of explicitly typecasted variable arguments
+       * if sdcc extensions are enabled */
+      if (options.std_sdcc &&
+        (IS_CAST_OP (*actParm) ||
+        (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
+        (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
         {
           /* Parameter was explicitly typecast; don't touch it. */
           return 0;
@@ -854,6 +863,8 @@ processParms (ast *func,
 
       ftype = (*actParm)->ftype;
 
+      resultType = RESULT_TYPE_NONE;
+
       /* If it's a char, upcast to int. */
       if (IS_INTEGRAL (ftype)
           && (getSize (ftype) < (unsigned) INTSIZE))
@@ -865,12 +876,14 @@ processParms (ast *func,
         {
           newType = newAst_LINK (copyLinkChain(ftype));
           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
+          resultType = RESULT_TYPE_GPTR;
         }
 
       if (IS_AGGREGATE (ftype))
         {
           newType = newAst_LINK (copyLinkChain (ftype));
           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
+          resultType = RESULT_TYPE_GPTR;
         }
 
       if (newType)
@@ -878,9 +891,10 @@ processParms (ast *func,
           /* cast required; change this op to a cast. */
           (*actParm)->decorated = 0;
            *actParm = newNode (CAST, newType, *actParm);
+          (*actParm)->filename = (*actParm)->right->filename;
           (*actParm)->lineno = (*actParm)->right->lineno;
 
-          decorateType (*actParm, RESULT_TYPE_NONE);
+          decorateType (*actParm, resultType);
         }
       return 0;
     } /* vararg */
@@ -915,13 +929,25 @@ processParms (ast *func,
       (*actParm)->left = newAst_LINK (defParm->type);
       (*actParm)->right = pTree;
       (*actParm)->decorated = 0; /* force typechecking */
-      decorateType (*actParm, resultType);
+      decorateType (*actParm, IS_GENPTR (defParm->type) ? RESULT_TYPE_GPTR : resultType);
     }
 
   /* make a copy and change the regparm type to the defined parm */
   (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
   SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
   SPEC_ARGREG  ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
+
+  /* if the function is being called via a pointer &  */
+  /* this parameter is not passed in registers        */
+  /* then the function must be defined reentrant      */
+  if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
+      !IFFUNC_ISREENT (functype) && !options.stackAuto)
+    {
+      werror (E_NONRENT_ARGS);
+      fatalError++;
+      return 1;
+    }
+
   (*parmNumber)++;
   return 0;
 }
@@ -935,10 +961,13 @@ createIvalType (ast * sym, sym_link * type, initList * ilist)
   ast *iExpr;
 
   /* if initList is deep */
-  if (ilist->type == INIT_DEEP)
+  if (ilist && ilist->type == INIT_DEEP)
     ilist = ilist->init.deep;
 
-  iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
+  if (ilist)
+    iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
+  else
+    iExpr = newAst_VALUE (valueFromLit (0));
   return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
 }
 
@@ -946,46 +975,51 @@ createIvalType (ast * sym, sym_link * type, initList * ilist)
 /* createIvalStruct - generates initial value for structures       */
 /*-----------------------------------------------------------------*/
 static ast *
-createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
+createIvalStruct (ast *sym, sym_link *type, initList *ilist, ast *rootValue)
 {
   ast *rast = NULL;
   ast *lAst;
   symbol *sflds;
   initList *iloop;
+  sym_link * etype = getSpec (type);
 
-  sflds = SPEC_STRUCT (type)->fields;
-  if (ilist->type != INIT_DEEP)
+  if (ilist && ilist->type != INIT_DEEP)
     {
       werror (E_INIT_STRUCT, "");
       return NULL;
     }
 
-  iloop = ilist->init.deep;
+  iloop = ilist ? ilist->init.deep : NULL;
 
-  for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
+  for (sflds = SPEC_STRUCT (type)->fields; sflds; sflds = sflds->next)
     {
       /* if we have come to end */
-      if (!iloop)
+      if (!iloop && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
         break;
-      sflds->implicit = 1;
-      lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
-      lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
-      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
-                                                       iloop, rast, rootValue)),
-                           RESULT_TYPE_NONE);
 
+      if (!IS_BITFIELD (sflds->type) || !SPEC_BUNNAMED (sflds->etype))
+        {
+          sflds->implicit = 1;
+          lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
+          lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
+          rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast, rootValue)), RESULT_TYPE_NONE);
+          iloop = iloop ? iloop->next : NULL;
+        }
     }
 
-  if (iloop) {
-    werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
-              W_EXCESS_INITIALIZERS, "struct",
-              sym->opval.val->sym->name);
-  }
+  if (iloop)
+    {
+      if (IS_AST_VALUE (sym))
+        werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+                  W_EXCESS_INITIALIZERS, "struct",
+                  sym->opval.val->sym->name);
+      else
+        werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
+    }
 
   return rast;
 }
 
-
 /*-----------------------------------------------------------------*/
 /* createIvalArray - generates code for array initialization       */
 /*-----------------------------------------------------------------*/
@@ -996,6 +1030,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
   initList *iloop;
   int lcnt = 0, size = 0;
   literalList *literalL;
+  sym_link * etype = getSpec (type);
 
   /* take care of the special   case  */
   /* array of characters can be init  */
@@ -1003,23 +1038,29 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
   if (IS_CHAR (type->next))
     if ((rast = createIvalCharPtr (sym,
                                    type,
-                        decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
+                                   decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
                                    rootValue)))
 
       return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 
-  /* not the special case             */
-  if (ilist->type != INIT_DEEP)
-  {
+  /* not the special case */
+  if (ilist && ilist->type != INIT_DEEP)
+    {
       werror (E_INIT_STRUCT, "");
       return NULL;
-  }
+    }
 
-  iloop = ilist->init.deep;
+  iloop = ilist ? ilist->init.deep : NULL;
   lcnt = DCL_ELEM (type);
 
-  if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
-  {
+  if (!iloop &&
+      (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
+    {
+      return NULL;
+    }
+
+  if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL, lcnt))
+    {
       ast *aSym;
 
       aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
@@ -1029,50 +1070,48 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
 
       // Make sure size is set to length of initializer list.
       while (iloop)
-      {
+        {
           size++;
           iloop = iloop->next;
-      }
+        }
 
       if (lcnt && size > lcnt)
-      {
+        {
           // Array size was specified, and we have more initializers than needed.
-          char *name=sym->opval.val->sym->name;
-          int lineno=sym->opval.val->sym->lineDef;
-          char *filename=sym->opval.val->sym->fileDef;
-
-          werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
-      }
-  }
+          werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+                    W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
+        }
+    }
   else
-  {
+    {
       for (;;)
-      {
+        {
           ast *aSym;
 
+          if (!iloop &&
+              (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
+            {
+              break;
+            }
+
           aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
           aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
           rast = createIval (aSym, type->next, iloop, rast, rootValue);
+          lcnt--;
           iloop = (iloop ? iloop->next : NULL);
-          if (!iloop)
-          {
-              break;
-          }
 
           /* no of elements given and we    */
           /* have generated for all of them */
-          if (!--lcnt)
-          {
+          if (!lcnt && iloop)
+            {
               // is this a better way? at least it won't crash
               char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
-              int lineno = iloop->lineno;
-              char *filename = iloop->filename;
-              werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
+              werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
 
               break;
-          }
-      }
-  }
+            }
+        }
+    }
 
   /* if we have not been given a size  */
   if (!DCL_ELEM (type))
@@ -1104,8 +1143,30 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
                         && IS_ARRAY (iexpr->ftype)))
     return newNode ('=', sym, iexpr);
 
-  /* left side is an array so we have to assign each */
-  /* element                                         */
+  /* left side is an array so we have to assign each element */
+  if (!iexpr)
+    {
+      /* for each character generate an assignment */
+      /* to the array element */
+      unsigned int i = 0;
+      unsigned int symsize = getSize (type);
+
+      if (!AST_SYMBOL (rootVal)->islocal || SPEC_STAT (getSpec (type)))
+        return NULL;
+
+      for (i = 0; i < symsize; ++i)
+        {
+          rast = newNode (NULLOP,
+                          rast,
+                          newNode ('=',
+                                   newNode ('[', sym,
+                                            newAst_VALUE (valueFromLit ((float) i))),
+                                   newAst_VALUE (valueFromLit (0))));
+        }
+
+      return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
+    }
+
   if ((IS_LITERAL (iexpr->etype) ||
        SPEC_SCLS (iexpr->etype) == S_CODE)
       && IS_ARRAY (iexpr->ftype))
@@ -1117,9 +1178,9 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
       unsigned int symsize = getSize (type);
 
       size = getSize (iexpr->ftype);
-      if (symsize && size>symsize)
+      if (symsize && size > symsize)
         {
-          if (size>(symsize+1))
+          if (size > symsize)
             {
               char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
 
@@ -1129,15 +1190,14 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
           size = symsize;
         }
 
-      for (i=0;i<size;i++)
+      for (i = 0; i < size; i++)
         {
           rast = newNode (NULLOP,
                           rast,
                           newNode ('=',
                                    newNode ('[', sym,
                                    newAst_VALUE (valueFromLit ((float) i))),
-                                   newAst_VALUE (valueFromLit (*s))));
-          s++;
+                                   newAst_VALUE (valueFromLit (*s++))));
         }
 
       // now WE don't need iexpr's symbol anymore
@@ -1169,7 +1229,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
   ast *iexpr;
 
   /* if deep then   */
-  if (ilist->type == INIT_DEEP)
+  if (ilist && ilist->type == INIT_DEEP)
     ilist = ilist->init.deep;
 
   iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
@@ -1190,7 +1250,7 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootVa
 {
   ast *rast = NULL;
 
-  if (!ilist)
+  if (!ilist && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (getSpec (type))))
     return NULL;
 
   /* if structure then    */
@@ -1218,14 +1278,15 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootVa
 /*-----------------------------------------------------------------*/
 /* initAggregates - initialises aggregate variables with initv     */
 /*-----------------------------------------------------------------*/
-ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
+ast * initAggregates (symbol * sym, initList * ival, ast * wid)
+{
   ast *newAst = newAst_VALUE (symbolVal (sym));
   return createIval (newAst, sym->type, ival, wid, newAst);
 }
 
 /*-----------------------------------------------------------------*/
 /* gatherAutoInit - creates assignment expressions for initial     */
-/*    values                 */
+/*                  values                                         */
 /*-----------------------------------------------------------------*/
 static ast *
 gatherAutoInit (symbol * autoChain)
@@ -1237,7 +1298,6 @@ gatherAutoInit (symbol * autoChain)
   inInitMode = 1;
   for (sym = autoChain; sym; sym = sym->next)
     {
-
       /* resolve the symbols in the ival */
       if (sym->ival)
         resolveIvalSym (sym->ival, sym->type);
@@ -1284,7 +1344,7 @@ gatherAutoInit (symbol * autoChain)
                             list2expr (sym->ival));
           }
 
-          setAstLineno (work, sym->lineDef);
+          setAstFileLine (work, sym->fileDef, sym->lineDef);
 
           sym->ival = NULL;
           if (staticAutos)
@@ -1298,30 +1358,36 @@ gatherAutoInit (symbol * autoChain)
       /* if there is an initial value */
       if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
         {
-          initList *ilist=sym->ival;
+          initList *ilist = sym->ival;
 
-          while (ilist->type == INIT_DEEP) {
-            ilist = ilist->init.deep;
-          }
+          while (ilist->type == INIT_DEEP)
+            {
+              ilist = ilist->init.deep;
+            }
 
           /* update lineno for error msg */
-          lineno=sym->lineDef;
-          setAstLineno (ilist->init.node, lineno);
+          filename = sym->fileDef;
+          lineno = sym->lineDef;
+          setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
 
-          if (IS_AGGREGATE (sym->type)) {
-            work = initAggregates (sym, sym->ival, NULL);
-          } else {
-            if (getNelements(sym->type, sym->ival)>1) {
-              werrorfl (sym->fileDef, sym->lineDef,
-                        W_EXCESS_INITIALIZERS, "scalar",
-                        sym->name);
+          if (IS_AGGREGATE (sym->type))
+            {
+              work = initAggregates (sym, sym->ival, NULL);
+            }
+          else
+            {
+              if (getNelements(sym->type, sym->ival)>1)
+                {
+                  werrorfl (sym->fileDef, sym->lineDef,
+                            W_EXCESS_INITIALIZERS, "scalar",
+                            sym->name);
+                }
+              work = newNode ('=', newAst_VALUE (symbolVal (sym)),
+                              list2expr (sym->ival));
             }
-            work = newNode ('=', newAst_VALUE (symbolVal (sym)),
-                            list2expr (sym->ival));
-          }
 
           // just to be sure
-          setAstLineno (work, sym->lineDef);
+          setAstFileLine (work, sym->fileDef, sym->lineDef);
 
           sym->ival = NULL;
           if (init)
@@ -1361,16 +1427,18 @@ stringToSymbol (value * val)
   unsigned int size;
 
   // have we heard this before?
-  for (sp=statsg->syms; sp; sp=sp->next) {
-    sym=sp->item;
-    size = getSize (sym->type);
-    if (sym->isstrlit && size == getSize (val->type) &&
-        !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
-      // yes, this is old news. Don't publish it again.
-      sym->isstrlit++; // but raise the usage count
-      return symbolVal(sym);
+  for (sp = statsg->syms; sp; sp = sp->next)
+    {
+      sym = sp->item;
+      size = getSize (sym->type);
+      if (sym->isstrlit && size == getSize (val->type) &&
+          !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
+        {
+          // yes, this is old news. Don't publish it again.
+          sym->isstrlit++; // but raise the usage count
+          return symbolVal (sym);
+        }
     }
-  }
 
   SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
   sym = newSymbol (name, 0);    /* make it @ level 0 */
@@ -1433,7 +1501,6 @@ processBlockVars (ast * tree, int *stack, int action)
   return tree;
 }
 
-
 /*-------------------------------------------------------------*/
 /* constExprTree - returns TRUE if this tree is a constant     */
 /*                 expression                                  */
@@ -1533,13 +1600,13 @@ constExprValue (ast * cexpr, int check)
           cexpr->opval.op == CAST &&
           IS_LITERAL (cexpr->right->ftype))
         {
-        return valCastLiteral (cexpr->ftype,
-                               floatFromVal (cexpr->right->opval.val));
+          return valCastLiteral (cexpr->ftype,
+                                 floatFromVal (cexpr->right->opval.val));
         }
 
       if (IS_AST_VALUE (cexpr))
         {
-        return cexpr->opval.val;
+          return cexpr->opval.val;
         }
 
       if (check)
@@ -1553,7 +1620,7 @@ constExprValue (ast * cexpr, int check)
     {
       return cexpr->opval.val;
     }
-   return NULL;
+  return NULL;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1572,7 +1639,6 @@ isLabelInAst (symbol * label, ast * tree)
 
   return isLabelInAst (label, tree->right) &&
     isLabelInAst (label, tree->left);
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -1638,7 +1704,7 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
             {
 
               *end = newNode ('+', condExpr->left->right,
-                              newAst_VALUE (constVal ("1")));
+                              newAst_VALUE (constCharVal (1)));
               break;
             }
           return FALSE;
@@ -1685,7 +1751,7 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
           if (IS_AST_SYM_VALUE (loopExpr->left) &&
               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
               IS_AST_LIT_VALUE (loopExpr->right) &&
-              (int) AST_LIT_VALUE (loopExpr->right) != 1)
+              AST_ULONG_VALUE (loopExpr->right) != 1)
             return TRUE;
         }
     }
@@ -1773,8 +1839,8 @@ astHasDeref (ast * tree)
 }
 
 /*-----------------------------------------------------------------*/
-/* isConformingBody - the loop body has to conform to a set of rules */
-/* for the loop to be considered reversible read on for rules      */
+/* isConformingBody - the loop body has to conform to a set of     */
+/* rules for the loop to be considered reversible read on for rules*/
 /*-----------------------------------------------------------------*/
 bool
 isConformingBody (ast * pbody, symbol * sym, ast * body)
@@ -1783,14 +1849,13 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
   /* we are going to do a pre-order traversal of the
      tree && check for the following conditions. (essentially
      a set of very shallow tests )
-     a) the sym passed does not participate in
-     any arithmetic operation
+     a) the sym passed does not participate in any arithmetic operation
      b) There are no function calls
      c) all jumps are within the body
      d) address of loop control variable not taken
-     e) if an assignment has a pointer on the
-     left hand side make sure right does not have
-     loop control variable */
+     e) if an assignment has a pointer on the left hand side make sure
+        right does not have loop control variable
+  */
 
   /* if we reach the end or a leaf then true */
   if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
@@ -1845,9 +1910,9 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 
       /* if right is NULL then unary operation  */
 /*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*----------------------------*/
       /*  address of                */
-/*----------------------------*/
+      /*----------------------------*/
       if (!pbody->right)
         {
           if (IS_AST_SYM_VALUE (pbody->left) &&
@@ -1947,7 +2012,8 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
       if (astHasVolatile (pbody->left))
         return FALSE;
 
-      if (astHasDeref(pbody->right)) return FALSE;
+      if (astHasDeref(pbody->right))
+        return FALSE;
 
       return isConformingBody (pbody->left, sym, body) &&
         isConformingBody (pbody->right, sym, body);
@@ -1964,27 +2030,31 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
       assert ("Parser should not have generated this\n");
 
 /*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*----------------------------*/
       /*      comma operator        */
-/*----------------------------*/
+      /*----------------------------*/
     case ',':
       return isConformingBody (pbody->left, sym, body) &&
         isConformingBody (pbody->right, sym, body);
 
 /*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*----------------------------*/
       /*       function call        */
-/*----------------------------*/
+      /*----------------------------*/
     case CALL:
-        /* if local & not passed as paramater then ok */
-        if (sym->level && !astHasSymbol(pbody->right,sym))
+        /* if local & not passed as parameter &
+           not used to find the function then ok */
+        if (sym->level && !astHasSymbol (pbody->right, sym) &&
+            !astHasSymbol (pbody->left, sym))
+          {
             return TRUE;
+          }
       return FALSE;
 
 /*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*----------------------------*/
       /*     return statement       */
-/*----------------------------*/
+      /*----------------------------*/
     case RETURN:
       return FALSE;
 
@@ -2003,9 +2073,6 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 
   return isConformingBody (pbody->left, sym, body) &&
     isConformingBody (pbody->right, sym, body);
-
-
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -2059,7 +2126,7 @@ replLoopSym (ast * body, symbol * sym)
           body->type = EX_OP;
           body->opval.op = '-';
           body->left = newAst_VALUE (symbolVal (sym));
-          body->right = newAst_VALUE (constVal ("1"));
+          body->right = newAst_VALUE (constCharVal (1));
 
         }
 
@@ -2099,7 +2166,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
                             end));
 
   replLoopSym (loop->left, sym);
-  setAstLineno (rloop, init->lineno);
+  setAstFileLine (rloop, init->filename, init->lineno);
 
   rloop = newNode (NULLOP,
                    newNode ('=',
@@ -2111,7 +2178,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
                                          newNode (NULLOP,
                                                   newNode (SUB_ASSIGN,
                                                            newAst_VALUE (symbolVal (sym)),
-                                                           newAst_VALUE (constVal ("1"))),
+                                                           newAst_VALUE (constCharVal (1))),
                                                   rloop))));
 
   rloop->lineno=init->lineno;
@@ -2189,8 +2256,7 @@ getResultTypeFromType (sym_link *type)
     }
   if (IS_CHAR (type))
     return RESULT_TYPE_CHAR;
-  if (   IS_INT (type)
-      && !IS_LONG (type))
+  if (IS_INT (type) && !IS_LONG (type))
     return RESULT_TYPE_INT;
   return RESULT_TYPE_OTHER;
 }
@@ -2263,6 +2329,7 @@ addCast (ast *tree, RESULT_TYPE resultType, bool promote)
     }
   tree->decorated = 0;
   tree = newNode (CAST, newAst_LINK (newLink), tree);
+  tree->filename = tree->right->filename;
   tree->lineno = tree->right->lineno;
   /* keep unsigned type during cast to smaller type,
      but not when promoting from char to int */
@@ -2281,17 +2348,22 @@ resultTypePropagate (ast *tree, RESULT_TYPE resultType)
     {
       case AND_OP:
       case OR_OP:
-        return resultType;
+      case '!':
       case '=':
       case '?':
       case ':':
       case '|':
       case '^':
       case '~':
+      case LEFT_OP:
+      case LABEL:
+        return resultType;
       case '*':
       case '+':
       case '-':
-      case LABEL:
+        if ((IS_AST_VALUE (tree->left)  && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
+            (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
+          return RESULT_TYPE_NONE;
         return resultType;
       case '&':
         if (!tree->right)
@@ -2449,15 +2521,14 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 /*----------------------------*/
 /*   leaf has been reached    */
 /*----------------------------*/
-  lineno=tree->lineno;
+  filename = tree->filename;
+  lineno = tree->lineno;
   /* if this is of type value */
   /* just get the type        */
   if (tree->type == EX_VALUE)
     {
-
       if (IS_LITERAL (tree->opval.val->etype))
         {
-
           /* if this is a character array then declare it */
           if (IS_ARRAY (tree->opval.val->type))
             tree->opval.val = stringToSymbol (tree->opval.val);
@@ -2472,7 +2543,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           /* if the undefined flag is set then give error message */
           if (tree->opval.val->sym->undefined)
             {
-              werror (E_ID_UNDEF, tree->opval.val->sym->name);
+              werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
               /* assume int */
               TTYPE (tree) = TETYPE (tree) =
                 tree->opval.val->type = tree->opval.val->sym->type =
@@ -2535,7 +2606,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
        upon tree->opval.op, if resultType can be propagated */
     resultTypeProp = resultTypePropagate (tree, resultType);
 
-    if (tree->opval.op == '?')
+    if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
       dtl = decorateType (tree->left, RESULT_TYPE_IFX);
     else
       dtl = decorateType (tree->left, resultTypeProp);
@@ -2570,6 +2641,12 @@ decorateType (ast * tree, RESULT_TYPE resultType)
              there is resultType available */
           dtr = tree->right;
           break;
+        case SIZEOF:
+          /* don't allocate string if it is a sizeof argument */
+          ++noAlloc;
+          dtr = decorateType (tree->right, resultTypeProp);
+          --noAlloc;
+          break;
         default:
           dtr = decorateType (tree->right, resultTypeProp);
           break;
@@ -2598,31 +2675,31 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* first check if this is a array or a pointer */
       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
         {
-          werror (E_NEED_ARRAY_PTR, "[]");
+          werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
           goto errorTreeReturn;
         }
 
       /* check if the type of the idx */
       if (!IS_INTEGRAL (RTYPE (tree)))
         {
-          werror (E_IDX_NOT_INT);
+          werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
           goto errorTreeReturn;
         }
 
       /* if the left is an rvalue then error */
       if (LRVAL (tree))
         {
-          werror (E_LVALUE_REQUIRED, "array access");
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
           goto errorTreeReturn;
         }
 
       if (IS_LITERAL (RTYPE (tree)))
         {
-          int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree)));
+          int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
           int arraySize = DCL_ELEM (LTYPE (tree));
           if (arraySize && arrayIndex >= arraySize)
             {
-              werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
+              werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
             }
         }
 
@@ -2639,7 +2716,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* if this is not a structure */
       if (!IS_STRUCT (LTYPE (tree)))
         {
-          werror (E_STRUCT_UNION, ".");
+          werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
           goto errorTreeReturn;
         }
       TTYPE (tree) = structElemType (LTYPE (tree),
@@ -2656,13 +2733,13 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* if not pointer to a structure */
       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
         {
-          werror (E_PTR_REQD);
+          werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
           goto errorTreeReturn;
         }
 
       if (!IS_STRUCT (LTYPE (tree)->next))
         {
-          werror (E_STRUCT_UNION, "->");
+          werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
           goto errorTreeReturn;
         }
 
@@ -2752,7 +2829,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
-          werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
+          werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
 
         if (tree->right)
           RLVAL (tree) = 1;
@@ -2772,8 +2849,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
             {
-              werror (E_BITWISE_OP);
-              werror (W_CONTINUE, "left & right types are ");
+              werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
+              werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
               printTypeChain (LTYPE (tree), stderr);
               fprintf (stderr, ",");
               printTypeChain (RTYPE (tree), stderr);
@@ -2875,13 +2952,13 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* if bit field then error */
       if (IS_BITVAR (tree->left->etype))
         {
-          werror (E_ILLEGAL_ADDR, "address of bit variable");
+          werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
           goto errorTreeReturn;
         }
 
       if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
         {
-          werror (E_ILLEGAL_ADDR, "address of register variable");
+          werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
           goto errorTreeReturn;
         }
 
@@ -2893,13 +2970,13 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
       if (IS_LITERAL(LTYPE(tree)))
         {
-          werror (E_ILLEGAL_ADDR, "address of literal");
+          werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
           goto errorTreeReturn;
         }
 
      if (LRVAL (tree))
         {
-          werror (E_LVALUE_REQUIRED, "address of");
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
           goto errorTreeReturn;
         }
       if (!LETYPE (tree))
@@ -2998,8 +3075,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
     case '^':
       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
         {
-          werror (E_BITWISE_OP);
-          werror (W_CONTINUE, "left & right types are ");
+          werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
+          werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
           printTypeChain (LTYPE (tree), stderr);
           fprintf (stderr, ",");
           printTypeChain (RTYPE (tree), stderr);
@@ -3064,7 +3141,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
     case '/':
       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
         {
-          werror (E_INVALID_OP, "divide");
+          werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
           goto errorTreeReturn;
         }
       /* if they are both literal then */
@@ -3093,7 +3170,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* rearrange the tree */
       if (IS_LITERAL (RTYPE (tree))
           /* avoid infinite loop */
-          && (TYPE_TARGET_ULONG) floatFromVal (tree->right->opval.val) != 1)
+          && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
         {
           ast *parent;
           ast *litTree = searchLitOp (tree, &parent, "/");
@@ -3106,9 +3183,10 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                   litTree->right = newNode ('*',
                                             litTree->right,
                                             copyAst (tree->right));
+                  litTree->right->filename = tree->filename;
                   litTree->right->lineno = tree->lineno;
 
-                  tree->right->opval.val = constVal ("1");
+                  tree->right->opval.val = constCharVal (1);
                   decorateType (parent, resultType);
                 }
               else
@@ -3131,8 +3209,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
     case '%':
       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
         {
-          werror (E_BITWISE_OP);
-          werror (W_CONTINUE, "left & right types are ");
+          werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
+          werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
           printTypeChain (LTYPE (tree), stderr);
           fprintf (stderr, ",");
           printTypeChain (RTYPE (tree), stderr);
@@ -3168,16 +3246,16 @@ decorateType (ast * tree, RESULT_TYPE resultType)
         {
           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
             {
-              werror (E_PTR_REQD);
+              werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
               goto errorTreeReturn;
             }
 
           if (LRVAL (tree))
             {
-              werror (E_LVALUE_REQUIRED, "pointer deref");
+              werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
               goto errorTreeReturn;
             }
-          if (IS_ADDRESS_OF_OP(tree->left))
+          if (IS_ADDRESS_OF_OP (tree->left))
             {
               /* replace *&obj with obj */
               return tree->left->left;
@@ -3223,7 +3301,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /*----------------------------*/
       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
         {
-          werror (E_INVALID_OP, "multiplication");
+          werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
           goto errorTreeReturn;
         }
 
@@ -3267,8 +3345,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
         }
 
       LRVAL (tree) = RRVAL (tree) = 1;
-      tree->left  = addCast (tree->left,  resultType, FALSE);
-      tree->right = addCast (tree->right, resultType, FALSE);
+      tree->left  = addCast (tree->left,  resultTypeProp, FALSE);
+      tree->right = addCast (tree->right, resultTypeProp, FALSE);
       TETYPE (tree) = getSpec (TTYPE (tree) =
                                    computeType (LTYPE (tree),
                                                 RTYPE (tree),
@@ -3287,7 +3365,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
         {
           if (!IS_ARITHMETIC (LTYPE (tree)))
             {
-              werror (E_UNARY_OP, '+');
+              werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
               goto errorTreeReturn;
             }
 
@@ -3315,21 +3393,21 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
         {
-          werror (E_PTR_PLUS_PTR);
+          werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
           goto errorTreeReturn;
         }
 
       if (!IS_ARITHMETIC (LTYPE (tree)) &&
           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
         {
-          werror (E_PLUS_INVALID, "+");
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
           goto errorTreeReturn;
         }
 
       if (!IS_ARITHMETIC (RTYPE (tree)) &&
           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
         {
-          werror (E_PLUS_INVALID, "+");
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
           goto errorTreeReturn;
         }
       /* if they are both literal then */
@@ -3337,8 +3415,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
         {
           tree->type = EX_VALUE;
-          tree->left  = addCast (tree->left,  resultType, TRUE);
-          tree->right = addCast (tree->right, resultType, TRUE);
+          tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
+          tree->right = addCast (tree->right, resultTypeProp, TRUE);
           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
                                      valFromType (RETYPE (tree)));
           tree->right = tree->left = NULL;
@@ -3408,8 +3486,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                  LTYPE (tree));
       else
         {
-          tree->left  = addCast (tree->left,  resultType, TRUE);
-          tree->right = addCast (tree->right, resultType, TRUE);
+          tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
+          tree->right = addCast (tree->right, resultTypeProp, TRUE);
           TETYPE (tree) = getSpec (TTYPE (tree) =
                                      computeType (LTYPE (tree),
                                                   RTYPE (tree),
@@ -3430,7 +3508,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
           if (!IS_ARITHMETIC (LTYPE (tree)))
             {
-              werror (E_UNARY_OP, tree->opval.op);
+              werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
               goto errorTreeReturn;
             }
 
@@ -3443,7 +3521,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
               return tree;
             }
-          tree->left  = addCast (tree->left, resultType, TRUE);
+          tree->left  = addCast (tree->left, resultTypeProp, TRUE);
           TETYPE (tree) = getSpec (TTYPE (tree) =
                                      computeType (LTYPE (tree),
                                                   NULL,
@@ -3462,7 +3540,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             IS_ARRAY (LTYPE (tree)) ||
             IS_ARITHMETIC (LTYPE (tree))))
         {
-          werror (E_PLUS_INVALID, "-");
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
           goto errorTreeReturn;
         }
 
@@ -3470,7 +3548,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             IS_ARRAY (RTYPE (tree)) ||
             IS_ARITHMETIC (RTYPE (tree))))
         {
-          werror (E_PLUS_INVALID, "-");
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
           goto errorTreeReturn;
         }
 
@@ -3478,7 +3556,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
             IS_INTEGRAL (RTYPE (tree))))
         {
-          werror (E_PLUS_INVALID, "-");
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
           goto errorTreeReturn;
         }
 
@@ -3487,8 +3565,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
         {
           tree->type = EX_VALUE;
-          tree->left  = addCast (tree->left,  resultType, TRUE);
-          tree->right = addCast (tree->right, resultType, TRUE);
+          tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
+          tree->right = addCast (tree->right, resultTypeProp, TRUE);
           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
                                       valFromType (RETYPE (tree)));
           tree->right = tree->left = NULL;
@@ -3502,7 +3580,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
         {
           tree->type = EX_VALUE;
           tree->left = tree->right = NULL;
-          tree->opval.val = constVal ("0");
+          tree->opval.val = constCharVal (0);
           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
           return tree;
         }
@@ -3520,8 +3598,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                  LTYPE (tree));
       else
         {
-          tree->left  = addCast (tree->left,  resultType, TRUE);
-          tree->right = addCast (tree->right, resultType, TRUE);
+          tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
+          tree->right = addCast (tree->right, resultTypeProp, TRUE);
 
           TETYPE (tree) = getSpec (TTYPE (tree) =
                                      computeType (LTYPE (tree),
@@ -3537,7 +3615,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* rearrange the tree */
       if (IS_LITERAL (RTYPE (tree))
           /* avoid infinite loop */
-          && (TYPE_TARGET_ULONG) floatFromVal (tree->right->opval.val) != 0)
+          && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
         {
           ast *litTree, *litParent;
           litTree = searchLitOp (tree, &litParent, "+-");
@@ -3591,7 +3669,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* can be only integral type */
       if (!IS_INTEGRAL (LTYPE (tree)))
         {
-          werror (E_UNARY_OP, tree->opval.op);
+          werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
           goto errorTreeReturn;
         }
 
@@ -3602,7 +3680,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
           tree->left = NULL;
           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-          return addCast (tree, resultType, TRUE);
+          return addCast (tree, resultTypeProp, TRUE);
         }
 
       if (resultType == RESULT_TYPE_BIT &&
@@ -3613,14 +3691,14 @@ decorateType (ast * tree, RESULT_TYPE resultType)
              bit -> int -> ~int -> bit
              uchar -> int -> ~int -> bit
           */
-          werror(W_COMPLEMENT);
+          werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
 
           /* optimize bit-result, even if we optimize a buggy source */
           tree->type = EX_VALUE;
-          tree->opval.val = constVal ("1");
+          tree->opval.val = constCharVal (1);
         }
       else
-        tree->left = addCast (tree->left, resultType, TRUE);
+        tree->left = addCast (tree->left, resultTypeProp, TRUE);
       LRVAL (tree) = 1;
       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
       return tree;
@@ -3635,19 +3713,25 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           !IS_PTR (LTYPE (tree)) &&
           !IS_ARRAY (LTYPE (tree)))
         {
-          werror (E_UNARY_OP, tree->opval.op);
+          werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
           goto errorTreeReturn;
         }
 
       /* if left is another '!' */
-      if (tree->left->opval.op == '!')
+      if (IS_AST_NOT_OPER (tree->left))
         {
+          if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
+            {
+              /* replace double '!!X' by 'X' */
+              return tree->left->left;
+            }
           /* remove double '!!X' by 'X ? 1 : 0' */
           tree->opval.op = '?';
           tree->left  = tree->left->left;
           tree->right = newNode (':',
-                                  newAst_VALUE (constVal ("1")),
-                                  newAst_VALUE (constVal ("0")));
+                                  newAst_VALUE (constCharVal (1)),
+                                  newAst_VALUE (constCharVal (0)));
+          tree->right->filename = tree->filename;
           tree->right->lineno = tree->lineno;
           tree->decorated = 0;
           return decorateType (tree, resultType);
@@ -3694,8 +3778,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
     case RIGHT_OP:
       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
         {
-          werror (E_SHIFT_OP_INVALID);
-          werror (W_CONTINUE, "left & right types are ");
+          werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
+          werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
           printTypeChain (LTYPE (tree), stderr);
           fprintf (stderr, ",");
           printTypeChain (RTYPE (tree), stderr);
@@ -3705,7 +3789,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
       /* make smaller type only if it's a LEFT_OP */
       if (tree->opval.op == LEFT_OP)
-        tree->left = addCast (tree->left, resultType, TRUE);
+        tree->left = addCast (tree->left, resultTypeProp, TRUE);
 
       /* if they are both literal then */
       /* rewrite the tree */
@@ -3759,18 +3843,17 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* if only the right side is a literal & we are
          shifting more than size of the left operand then zero */
       if (IS_LITERAL (RTYPE (tree)) &&
-          ((TYPE_TARGET_ULONG) floatFromVal (valFromType (RETYPE (tree)))) >=
+          ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
           (getSize (TETYPE (tree)) * 8))
         {
           if (tree->opval.op==LEFT_OP ||
               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
             {
-              lineno=tree->lineno;
-              werror (W_SHIFT_CHANGED,
+              werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
                       (tree->opval.op == LEFT_OP ? "left" : "right"));
               tree->type = EX_VALUE;
               tree->left = tree->right = NULL;
-              tree->opval.val = constVal ("0");
+              tree->opval.val = constCharVal (0);
               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
               return tree;
             }
@@ -3786,7 +3869,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* cannot cast to an aggregate type */
       if (IS_AGGREGATE (LTYPE (tree)))
         {
-          werror (E_CAST_ILLEGAL);
+          werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
           goto errorTreeReturn;
         }
 
@@ -3794,10 +3877,13 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       changePointer(LTYPE(tree));
       checkTypeSanity(LETYPE(tree), "(cast)");
 
-      /* if 'from' and 'to' are the same remove the superfluous cast, */
-      /* this helps other optimizations */
+      /* if 'from' and 'to' are the same remove the superfluous cast,
+       * this helps other optimizations */
       if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
         {
+          /* mark that the explicit cast has been removed,
+           * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
+          tree->right->values.removedCast = 1;
           return tree->right;
         }
 
@@ -3820,33 +3906,41 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
 #if 0
       /* if the right is a literal replace the tree */
-      if (IS_LITERAL (RETYPE (tree))) {
-              if (!IS_PTR (LTYPE (tree))) {
-                      tree->type = EX_VALUE;
-                      tree->opval.val =
-                              valCastLiteral (LTYPE (tree),
-                                              floatFromVal (valFromType (RETYPE (tree))));
-                      tree->left = NULL;
-                      tree->right = NULL;
-                      TTYPE (tree) = tree->opval.val->type;
-                      tree->values.literalFromCast = 1;
-              } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
-                         ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
-                      sym_link *rest = LTYPE(tree)->next;
-                      werror(W_LITERAL_GENERIC);
-                      TTYPE(tree) = newLink(DECLARATOR);
-                      DCL_TYPE(TTYPE(tree)) = FPOINTER;
-                      TTYPE(tree)->next = rest;
-                      tree->left->opval.lnk = TTYPE(tree);
-                      LRVAL (tree) = 1;
-              } else {
-                      TTYPE (tree) = LTYPE (tree);
-                      LRVAL (tree) = 1;
-              }
-      } else {
+      if (IS_LITERAL (RETYPE (tree)))
+        {
+          if (!IS_PTR (LTYPE (tree)))
+            {
+              tree->type = EX_VALUE;
+              tree->opval.val =
+                      valCastLiteral (LTYPE (tree),
+                                      floatFromVal (valFromType (RETYPE (tree))));
+              tree->left = NULL;
+              tree->right = NULL;
+              TTYPE (tree) = tree->opval.val->type;
+              tree->values.literalFromCast = 1;
+            }
+          else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
+                   ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */
+            {
+              sym_link *rest = LTYPE(tree)->next;
+              werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
+              TTYPE(tree) = newLink(DECLARATOR);
+              DCL_TYPE(TTYPE(tree)) = FPOINTER;
+              TTYPE(tree)->next = rest;
+              tree->left->opval.lnk = TTYPE(tree);
+              LRVAL (tree) = 1;
+            }
+          else
+            {
               TTYPE (tree) = LTYPE (tree);
               LRVAL (tree) = 1;
-      }
+            }
+        }
+      else
+        {
+          TTYPE (tree) = LTYPE (tree);
+          LRVAL (tree) = 1;
+        }
 #else
 #if 0 // this is already checked, now this could be explicit
       /* if pointer to struct then check names */
@@ -3854,55 +3948,53 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
         {
-          werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
+          werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
                  SPEC_STRUCT(LETYPE(tree))->tag);
         }
 #endif
       if (IS_ADDRESS_OF_OP(tree->right)
           && IS_AST_SYM_VALUE (tree->right->left)
-          && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
-
-        symbol * sym = AST_SYMBOL (tree->right->left);
-        unsigned int gptype = 0;
-        unsigned int addr = SPEC_ADDR (sym->etype);
+          && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype))
+        {
+          symbol * sym = AST_SYMBOL (tree->right->left);
+          unsigned int gptype = 0;
+          unsigned int addr = SPEC_ADDR (sym->etype);
 
-        if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
-                                        || TARGET_IS_PIC16) )
-          {
-            switch (SPEC_SCLS (sym->etype))
-              {
-              case S_CODE:
-                gptype = GPTYPE_CODE;
-                break;
-              case S_XDATA:
-                gptype = GPTYPE_FAR;
-                break;
-              case S_DATA:
-              case S_IDATA:
-                gptype = GPTYPE_NEAR;
-                break;
-              case S_PDATA:
-                gptype = GPTYPE_XSTACK;
-                break;
-              default:
-                gptype = 0;
+          if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE) || TARGET_IS_PIC16) )
+            {
+              switch (SPEC_SCLS (sym->etype))
+                {
+                case S_CODE:
+                  gptype = GPTYPE_CODE;
+                  break;
+                case S_XDATA:
+                  gptype = GPTYPE_FAR;
+                  break;
+                case S_DATA:
+                case S_IDATA:
+                  gptype = GPTYPE_NEAR;
+                  break;
+                case S_PDATA:
+                  gptype = GPTYPE_XSTACK;
+                  break;
+                default:
+                  gptype = 0;
 
-                if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
-                    gptype = GPTYPE_NEAR;
-              }
-            addr |= gptype << (8*(GPTRSIZE - 1));
-          }
+                  if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
+                      gptype = GPTYPE_NEAR;
+                }
+              addr |= gptype << (8*(GPTRSIZE - 1));
+            }
 
-        tree->type = EX_VALUE;
-        tree->opval.val =
-          valCastLiteral (LTYPE (tree), addr);
-        TTYPE (tree) = tree->opval.val->type;
-        TETYPE (tree) = getSpec (TTYPE (tree));
-        tree->left = NULL;
-        tree->right = NULL;
-        tree->values.literalFromCast = 1;
-        return tree;
-      }
+          tree->type = EX_VALUE;
+          tree->opval.val = valCastLiteral (LTYPE (tree), addr);
+          TTYPE (tree) = tree->opval.val->type;
+          TETYPE (tree) = getSpec (TTYPE (tree));
+          tree->left = NULL;
+          tree->right = NULL;
+          tree->values.literalFromCast = 1;
+          return tree;
+        }
 
       /* handle offsetof macro:            */
       /* #define offsetof(TYPE, MEMBER) \  */
@@ -3912,83 +4004,91 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           && tree->right->left->opval.op == PTR_OP
           && IS_AST_OP (tree->right->left->left)
           && tree->right->left->left->opval.op == CAST
-          && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
-
-        symbol *element = getStructElement (
-          SPEC_STRUCT (LETYPE(tree->right->left)),
-          AST_SYMBOL(tree->right->left->right)
-        );
-
-        if (element) {
-          tree->type = EX_VALUE;
-          tree->opval.val = valCastLiteral (
-            LTYPE (tree),
-            element->offset
-            + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
+          && IS_AST_LIT_VALUE(tree->right->left->left->right))
+        {
+          symbol *element = getStructElement (
+            SPEC_STRUCT (LETYPE(tree->right->left)),
+            AST_SYMBOL(tree->right->left->right)
           );
 
-          TTYPE (tree) = tree->opval.val->type;
-          TETYPE (tree) = getSpec (TTYPE (tree));
-          tree->left = NULL;
-          tree->right = NULL;
-          return tree;
-        }
+          if (element)
+            {
+              tree->type = EX_VALUE;
+              tree->opval.val = valCastLiteral (
+                LTYPE (tree),
+                element->offset
+                + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
+              );
+
+            TTYPE (tree) = tree->opval.val->type;
+            TETYPE (tree) = getSpec (TTYPE (tree));
+            tree->left = NULL;
+            tree->right = NULL;
+            return tree;
+          }
       }
 
       /* if the right is a literal replace the tree */
-      if (IS_LITERAL (RETYPE (tree))) {
-        #if 0
-        if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
-          /* rewrite      (type *)litaddr
-             as           &temp
-             and define   type at litaddr temp
-             (but only if type's storage class is not generic)
-          */
-          ast *newTree = newNode ('&', NULL, NULL);
-          symbol *sym;
-
-          TTYPE (newTree) = LTYPE (tree);
-          TETYPE (newTree) = getSpec(LTYPE (tree));
-
-          /* define a global symbol at the casted address*/
-          sym = newSymbol(genSymName (0), 0);
-          sym->type = LTYPE (tree)->next;
-          if (!sym->type)
-            sym->type = newLink (V_VOID);
-          sym->etype = getSpec(sym->type);
-          SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
-          sym->lineDef = tree->lineno;
-          sym->cdef = 1;
-          sym->isref = 1;
-          SPEC_STAT (sym->etype) = 1;
-          SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
-          SPEC_ABSA(sym->etype) = 1;
-          addSym (SymbolTab, sym, sym->name, 0, 0, 0);
-          allocGlobal (sym);
-
-          newTree->left = newAst_VALUE(symbolVal(sym));
-          newTree->left->lineno = tree->lineno;
-          LTYPE (newTree) = sym->type;
-          LETYPE (newTree) = sym->etype;
-          LLVAL (newTree) = 1;
-          LRVAL (newTree) = 0;
-          TLVAL (newTree) = 1;
-          return newTree;
-        }
-        #endif
-        if (!IS_PTR (LTYPE (tree))) {
-          tree->type = EX_VALUE;
-          tree->opval.val =
-          valCastLiteral (LTYPE (tree),
-                          floatFromVal (valFromType (RTYPE (tree))));
-          TTYPE (tree) = tree->opval.val->type;
-          tree->left = NULL;
-          tree->right = NULL;
-          tree->values.literalFromCast = 1;
-          TETYPE (tree) = getSpec (TTYPE (tree));
-          return tree;
+      if (IS_LITERAL (RETYPE (tree)))
+        {
+          #if 0
+          if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) )
+            {
+              /* rewrite      (type *)litaddr
+                 as           &temp
+                 and define   type at litaddr temp
+                 (but only if type's storage class is not generic)
+              */
+              ast *newTree = newNode ('&', NULL, NULL);
+              symbol *sym;
+
+              TTYPE (newTree) = LTYPE (tree);
+              TETYPE (newTree) = getSpec(LTYPE (tree));
+
+              /* define a global symbol at the casted address*/
+              sym = newSymbol(genSymName (0), 0);
+              sym->type = LTYPE (tree)->next;
+              if (!sym->type)
+                sym->type = newLink (V_VOID);
+              sym->etype = getSpec(sym->type);
+              SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
+              sym->lineDef = tree->lineno;
+              sym->cdef = 1;
+              sym->isref = 1;
+              SPEC_STAT (sym->etype) = 1;
+              SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
+              SPEC_ABSA(sym->etype) = 1;
+              addSym (SymbolTab, sym, sym->name, 0, 0, 0);
+              allocGlobal (sym);
+
+              newTree->left = newAst_VALUE(symbolVal(sym));
+              newTree->left->filename = tree->filename;
+              newTree->left->lineno = tree->lineno;
+              LTYPE (newTree) = sym->type;
+              LETYPE (newTree) = sym->etype;
+              LLVAL (newTree) = 1;
+              LRVAL (newTree) = 0;
+              TLVAL (newTree) = 1;
+              return newTree;
+            }
+          #endif
+          if (!IS_PTR (LTYPE (tree)))
+            {
+              tree->type = EX_VALUE;
+              tree->opval.val =
+                valCastLiteral (LTYPE (tree), floatFromVal (valFromType (RTYPE (tree))));
+              TTYPE (tree) = tree->opval.val->type;
+              tree->left = NULL;
+              tree->right = NULL;
+              tree->values.literalFromCast = 1;
+              TETYPE (tree) = getSpec (TTYPE (tree));
+              return tree;
+            }
+        }
+      if (IS_GENPTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)) && !IS_GENPTR (RTYPE (tree)) && (resultType != RESULT_TYPE_GPTR))
+        {
+          DCL_TYPE (LTYPE (tree)) = DCL_TYPE (RTYPE (tree));
         }
-      }
       TTYPE (tree) = LTYPE (tree);
       LRVAL (tree) = 1;
 
@@ -4008,7 +4108,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           !IS_ARRAY (LTYPE (tree)) &&
           !IS_INTEGRAL (LTYPE (tree)))
         {
-          werror (E_COMPARE_OP);
+          werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
           goto errorTreeReturn;
         }
 
@@ -4016,7 +4116,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           !IS_ARRAY (RTYPE (tree)) &&
           !IS_INTEGRAL (RTYPE (tree)))
         {
-          werror (E_COMPARE_OP);
+          werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
           goto errorTreeReturn;
         }
       /* if they are both literal then */
@@ -4066,7 +4166,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           }
           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
             {
-              werror (E_COMPARE_OP);
+              werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
               fprintf (stderr, "comparing type ");
               printTypeChain (LTYPE (tree), stderr);
               fprintf (stderr, "to type ");
@@ -4083,7 +4183,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
               {
-                werror (E_COMPARE_OP);
+                werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
                 fprintf (stderr, "comparing type ");
                 printTypeChain (LTYPE (tree), stderr);
                 fprintf (stderr, "to type ");
@@ -4110,11 +4210,9 @@ decorateType (ast * tree, RESULT_TYPE resultType)
               case CCR_ALWAYS_TRUE:
               case CCR_ALWAYS_FALSE:
                 if (!options.lessPedantic)
-                  werror (W_COMP_RANGE,
+                  werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
                           ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
-                return decorateType (newAst_VALUE (constVal (
-                                   ccr_result == CCR_ALWAYS_TRUE ? "1" : "0")),
-                                                   resultType);
+                return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
               case CCR_OK:
               default:
                 break;
@@ -4125,9 +4223,9 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (tree->opval.op == '>' &&
           SPEC_USIGN(LETYPE(tree)) &&
           IS_LITERAL(RTYPE(tree))  &&
-          ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
+          ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
         {
-          if (resultType == RESULT_TYPE_IFX)
+          if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
             {
               /* the parent is an ifx: */
               /* if (unsigned value) */
@@ -4137,9 +4235,11 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           /* (unsigned value) ? 1 : 0 */
           tree->opval.op = '?';
           tree->right = newNode (':',
-                                  newAst_VALUE (constVal ("1")),
+                                  newAst_VALUE (constCharVal (1)),
                                   tree->right); /* val 0 */
+          tree->right->filename = tree->filename;
           tree->right->lineno = tree->lineno;
+          tree->right->left->filename = tree->filename;
           tree->right->left->lineno = tree->lineno;
           tree->decorated = 0;
           return decorateType (tree, resultType);
@@ -4149,7 +4249,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (IS_LITERAL(RTYPE(tree))  &&
           floatFromVal (valFromType (RETYPE (tree))) == 0 &&
           tree->opval.op == EQ_OP &&
-          resultType == RESULT_TYPE_IFX)
+          (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
         {
           tree->opval.op = '!';
           tree->right = NULL;
@@ -4184,27 +4284,27 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
               /* the value range of a 'unsigned char' is 0...255;
                  if the actual value is < 128 it can be changed to signed */
-              (int) floatFromVal (valFromType (RETYPE (tree))) < 128)
+              (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
             {
               /* now we've got 2 'signed char'! */
               SPEC_USIGN (RETYPE (tree)) = 0;
             }
                    /* same test for the left operand: */
           else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
-              (int) floatFromVal (valFromType (LETYPE (tree))) < 128)
+              (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
             {
               SPEC_USIGN (LETYPE (tree)) = 0;
             }
           else
             {
-              werror (W_CMP_SU_CHAR);
+              werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
               tree->left  = addCast (tree->left , RESULT_TYPE_INT, TRUE);
               tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
             }
         }
 
       LRVAL (tree) = RRVAL (tree) = 1;
-      TTYPE (tree) = TETYPE (tree) = newBoolLink ();
+      TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
 
       /* condition transformations */
       {
@@ -4244,6 +4344,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             tree->opval.op = transformedOp;
             tree->decorated = 0;
             tree = newNode ('!', tree, NULL);
+            tree->filename = tree->left->filename;
             tree->lineno = tree->left->lineno;
             return decorateType (tree, resultType);
           }
@@ -4259,6 +4360,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* change the type to a integer */
       {
         int size = getSize (tree->right->ftype);
+
         SNPRINTF(buffer, sizeof(buffer), "%d", size);
         if (!size && !IS_VOID(tree->right->ftype))
           werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
@@ -4268,6 +4370,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       tree->right = tree->left = NULL;
       TETYPE (tree) = getSpec (TTYPE (tree) =
                                tree->opval.val->type);
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -4356,21 +4459,55 @@ decorateType (ast * tree, RESULT_TYPE resultType)
     case '?':
       /* the type is value of the colon operator (on the right) */
       assert (IS_COLON_OP (tree->right));
-      /* if already known then replace the tree : optimizer will do it
-         but faster to do it here */
+
+      /* If already known then replace the tree : optimizer will do it
+         but faster to do it here. If done before decorating tree->right
+         this can save generating unused const strings. */
       if (IS_LITERAL (LTYPE (tree)))
         {
-          if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
+          if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
             return decorateType (tree->right->left, resultTypeProp);
           else
             return decorateType (tree->right->right, resultTypeProp);
         }
-      else
+
+      tree->right = decorateType (tree->right,  resultTypeProp);
+
+      if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
+          ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
         {
-          tree->right = decorateType (tree->right, resultTypeProp);
-          TTYPE (tree) = RTYPE (tree);
-          TETYPE (tree) = getSpec (TTYPE (tree));
+          double valTrue = AST_FLOAT_VALUE (tree->right->left);
+          double valFalse = AST_FLOAT_VALUE (tree->right->right);
+
+          if ((valTrue != 0) && (valFalse == 0))
+            {
+              /* assign cond to result */
+              tree->left->decorated = 0;
+              return decorateType (tree->left, resultTypeProp);
+            }
+          else if ((valTrue == 0) && (valFalse != 0))
+            {
+              /* assign !cond to result */
+              tree->opval.op = '!';
+              tree->decorated = 0;
+              tree->right = NULL;
+              return decorateType (tree, resultTypeProp);
+            }
+          else
+            {
+              /* they have the same boolean value, make them equal */
+              tree->right->left = tree->right->right;
+            }
+        }
+
+      /* if they are equal then replace the tree */
+      if (isAstEqual (tree->right->left, tree->right->right))
+        {
+          return tree->right->left;
         }
+
+      TTYPE (tree) = RTYPE (tree);
+      TETYPE (tree) = getSpec (TTYPE (tree));
       return tree;
 
     case ':':
@@ -4378,7 +4515,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
           (compareType (RTYPE (tree), LTYPE (tree)) == 0))
         {
-          werror (E_TYPE_MISMATCH, "conditional operator", " ");
+          werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
           goto errorTreeReturn;
         }
 
@@ -4399,18 +4536,18 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (!IS_ARITHMETIC (LTYPE (tree)) ||
           !IS_ARITHMETIC (RTYPE (tree)))
         {
-          werror (E_OPS_INTEGRAL);
+          werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
           goto errorTreeReturn;
         }
       RRVAL (tree) = 1;
       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
 
       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
-        werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+        werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
 
       if (LRVAL (tree))
         {
-          werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
           goto errorTreeReturn;
         }
       LLVAL (tree) = 1;
@@ -4426,18 +4563,18 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (!IS_INTEGRAL (LTYPE (tree)) ||
           !IS_INTEGRAL (RTYPE (tree)))
         {
-          werror (E_OPS_INTEGRAL);
+          werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
           goto errorTreeReturn;
         }
       RRVAL (tree) = 1;
       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
 
       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
-        werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
+        werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
 
       if (LRVAL (tree))
         {
-          werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
           goto errorTreeReturn;
         }
       LLVAL (tree) = 1;
@@ -4452,14 +4589,14 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (!(IS_PTR (LTYPE (tree)) ||
             IS_ARITHMETIC (LTYPE (tree))))
         {
-          werror (E_PLUS_INVALID, "-=");
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
           goto errorTreeReturn;
         }
 
       if (!(IS_PTR (RTYPE (tree)) ||
             IS_ARITHMETIC (RTYPE (tree))))
         {
-          werror (E_PLUS_INVALID, "-=");
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
           goto errorTreeReturn;
         }
       RRVAL (tree) = 1;
@@ -4470,11 +4607,11 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                             tree->opval.op));
 
       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
-        werror (E_CODE_WRITE, "-=");
+        werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
 
       if (LRVAL (tree))
         {
-          werror (E_LVALUE_REQUIRED, "-=");
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
           goto errorTreeReturn;
         }
       LLVAL (tree) = 1;
@@ -4490,19 +4627,19 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* if both pointers then problem */
       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
         {
-          werror (E_PTR_PLUS_PTR);
+          werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
           goto errorTreeReturn;
         }
 
       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
         {
-          werror (E_PLUS_INVALID, "+=");
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
           goto errorTreeReturn;
         }
 
       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
         {
-          werror (E_PLUS_INVALID, "+=");
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
           goto errorTreeReturn;
         }
       RRVAL (tree) = 1;
@@ -4513,11 +4650,11 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                             tree->opval.op));
 
       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
-        werror (E_CODE_WRITE, "+=");
+        werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
 
       if (LRVAL (tree))
         {
-          werror (E_LVALUE_REQUIRED, "+=");
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
           goto errorTreeReturn;
         }
 
@@ -4535,14 +4672,14 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* cannot be an aggregate */
       if (IS_AGGREGATE (LTYPE (tree)))
         {
-          werror (E_AGGR_ASSIGN);
+          werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
           goto errorTreeReturn;
         }
 
       /* they should either match or be castable */
       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
         {
-          werror (E_TYPE_MISMATCH, "assignment", " ");
+          werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
           printFromToType(RTYPE(tree),LTYPE(tree));
         }
 
@@ -4550,21 +4687,20 @@ decorateType (ast * tree, RESULT_TYPE resultType)
          then report error */
       if (IS_VOID (LTYPE (tree)))
         {
-          werror (E_CAST_ZERO);
+          werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
           printFromToType(RTYPE(tree), LTYPE(tree));
         }
 
-      TETYPE (tree) = getSpec (TTYPE (tree) =
-                               LTYPE (tree));
+      TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
       RRVAL (tree) = 1;
       LLVAL (tree) = 1;
       if (!tree->initMode ) {
         if (IS_CONSTANT(LTYPE(tree)))
-          werror (E_CODE_WRITE, "=");
+          werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
       }
       if (LRVAL (tree))
         {
-          werror (E_LVALUE_REQUIRED, "=");
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
           goto errorTreeReturn;
         }
 
@@ -4661,7 +4797,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             decorateType (newNode (CAST,
                           newAst_LINK (copyLinkChain (currFunc->type->next)),
                                         tree->right),
-                          RESULT_TYPE_NONE);
+                          IS_GENPTR (currFunc->type->next) ? RESULT_TYPE_GPTR : RESULT_TYPE_NONE);
         }
 
       RRVAL (tree) = 1;
@@ -4671,7 +4807,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
         {
-          werror (W_VOID_FUNC, currFunc->name);
+          werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
           goto errorTreeReturn;
         }
 
@@ -4737,7 +4873,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                           tree->left), RESULT_TYPE_NONE);
       }
     case PARAM:
-      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+      werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
               "node PARAM shouldn't be processed here");
               /* but in processParams() */
       return tree;
@@ -4902,6 +5038,7 @@ createBlock (symbol * decl, ast * body)
   ex->values.sym = decl;
 
   ex->level++;
+  ex->filename = NULL;
   ex->lineno = 0;
   return ex;
 }
@@ -4938,6 +5075,7 @@ createLabel (symbol * label, ast * stmnt)
   label->islbl = 1;
   label->key = labelKey++;
   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
+  rValue->filename = NULL;
   rValue->lineno = 0;
 
   return rValue;
@@ -4983,8 +5121,8 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
     {
       /* also order the cases according to value */
       value *pval = NULL;
-      int cVal = (int) floatFromVal (caseVal->opval.val);
-      while (val && (int) floatFromVal (val) < cVal)
+      int cVal = (int) ulFromVal (caseVal->opval.val);
+      while (val && (int) ulFromVal (val) < cVal)
         {
           pval = val;
           val = val->next;
@@ -4995,7 +5133,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
         {
           pval->next = caseVal->opval.val;
         }
-      else if ((int) floatFromVal (val) == cVal)
+      else if ((int) ulFromVal (val) == cVal)
         {
           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
                     "case");
@@ -5022,9 +5160,10 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
   SNPRINTF(caseLbl, sizeof(caseLbl),
            "_case_%d_%d",
            swStat->values.switchVals.swNum,
-           (int) floatFromVal (caseVal->opval.val));
+           (int) ulFromVal (caseVal->opval.val));
 
   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
+  rexpr->filename = 0;
   rexpr->lineno = 0;
   return rexpr;
 }
@@ -5260,10 +5399,12 @@ createWhile (symbol * trueLabel, symbol * continueLabel,
   /* put the continue label */
   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
   condExpr = createLabel (continueLabel, condExpr);
+  condExpr->filename = NULL;
   condExpr->lineno = 0;
 
   /* put the body label in front of the body */
   whileBody = createLabel (trueLabel, whileBody);
+  whileBody->filename = NULL;
   whileBody->lineno = 0;
   /* put a jump to continue at the end of the body */
   /* and put break label at the end of the body */
@@ -5326,7 +5467,7 @@ isBitAndPow2 (ast * tree)
   if (!IS_AST_LIT_VALUE (tree->right))
     return -1;
 
-  return powof2 ((TYPE_TARGET_ULONG)AST_LIT_VALUE (tree->right));
+  return powof2 (AST_ULONG_VALUE (tree->right));
 }
 
 /*-----------------------------------------------------------------*/
@@ -5335,14 +5476,14 @@ isBitAndPow2 (ast * tree)
 ast *
 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
 {
-  int i, j;
+  unsigned int i, j;
   ast * expr;
 
   expr = isShiftRightLitVal_BitAndLitVal(tree);
   if (expr)
     {
-      if ((AST_LIT_VALUE (tree->right) != 1) ||
-          ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
+      if ((AST_ULONG_VALUE (tree->right) != 1) ||
+          ((i = AST_ULONG_VALUE (tree->left->right)) !=
           (j = (getSize (TTYPE (expr)) * 8 - 1))))
         expr = NULL;
     }
@@ -5375,7 +5516,7 @@ optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
   expr = isShiftRightLitVal_BitAndLitVal(tree);
   if (expr)
     {
-  if (AST_LIT_VALUE (tree->right) != 1)
+  if (AST_ULONG_VALUE (tree->right) != 1)
         expr = NULL;
       count = tree->left->right;
     }
@@ -5413,9 +5554,9 @@ optimizeGetByte (ast * tree, RESULT_TYPE resultType)
   expr = isShiftRightLitVal_BitAndLitVal(tree);
   if (expr)
     {
-      i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+      i = AST_ULONG_VALUE (tree->left->right);
       count = tree->left->right;
-      if (AST_LIT_VALUE (tree->right) != 0xFF)
+      if (AST_ULONG_VALUE (tree->right) != 0xFF)
         expr = NULL;
     }
   if (!expr && resultType == RESULT_TYPE_CHAR)
@@ -5423,7 +5564,7 @@ optimizeGetByte (ast * tree, RESULT_TYPE resultType)
       /* if this is a right shift over a multiple of 8 */
       if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
         {
-          i = (unsigned int) AST_LIT_VALUE (tree->right);
+          i = AST_ULONG_VALUE (tree->right);
           count = tree->right;
             expr = tree->left;
         }
@@ -5452,9 +5593,9 @@ optimizeGetWord (ast * tree, RESULT_TYPE resultType)
   expr = isShiftRightLitVal_BitAndLitVal(tree);
   if (expr)
     {
-      i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+      i = AST_ULONG_VALUE (tree->left->right);
       count = tree->left->right;
-      if (AST_LIT_VALUE (tree->right) != 0xFFFF)
+      if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
         expr = NULL;
     }
   if (!expr && resultType == RESULT_TYPE_INT)
@@ -5462,7 +5603,7 @@ optimizeGetWord (ast * tree, RESULT_TYPE resultType)
       /* if this is a right shift over a multiple of 8 */
       if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
         {
-          i = (unsigned int) AST_LIT_VALUE (tree->right);
+          i = AST_ULONG_VALUE (tree->right);
           count = tree->right;
             expr = tree->left;
         }
@@ -5518,10 +5659,10 @@ optimizeRRCRLC (ast * root)
                        root->right->left))
         goto tryNext0;
 
-      if (AST_LIT_VALUE (root->left->right) != 1)
+      if (AST_ULONG_VALUE (root->left->right) != 1)
         goto tryNext0;
 
-      if (AST_LIT_VALUE (root->right->right) !=
+      if (AST_ULONG_VALUE (root->right->right) !=
           (getSize (TTYPE (root->left->left)) * 8 - 1))
         goto tryNext0;
 
@@ -5553,10 +5694,10 @@ tryNext0:
                        root->right->left))
         goto tryNext1;
 
-      if (AST_LIT_VALUE (root->right->right) != 1)
+      if (AST_ULONG_VALUE (root->right->right) != 1)
         goto tryNext1;
 
-      if (AST_LIT_VALUE (root->left->right) !=
+      if (AST_ULONG_VALUE (root->left->right) !=
           (getSize (TTYPE (root->left->left)) * 8 - 1))
         goto tryNext1;
 
@@ -5589,10 +5730,10 @@ tryNext1:
                        root->right->left))
         goto tryNext2;
 
-      if (AST_LIT_VALUE (root->left->right) != 1)
+      if (AST_ULONG_VALUE (root->left->right) != 1)
         goto tryNext2;
 
-      if (AST_LIT_VALUE (root->right->right) !=
+      if (AST_ULONG_VALUE (root->right->right) !=
           (getSize (TTYPE (root->left->left)) * 8 - 1))
         goto tryNext2;
 
@@ -5624,10 +5765,10 @@ tryNext2:
                        root->right->left))
         return root;
 
-      if (AST_LIT_VALUE (root->right->right) != 1)
+      if (AST_ULONG_VALUE (root->right->right) != 1)
         return root;
 
-      if (AST_LIT_VALUE (root->left->right) !=
+      if (AST_ULONG_VALUE (root->left->right) !=
           (getSize (TTYPE (root->left->left)) * 8 - 1))
         return root;
 
@@ -5678,11 +5819,11 @@ optimizeSWAP (ast * root)
                        root->right->left))
         return root;
 
-      if (AST_LIT_VALUE (root->left->right) !=
+      if (AST_ULONG_VALUE (root->left->right) !=
           (getSize (TTYPE (root->left->left)) * 4))
         return root;
 
-      if (AST_LIT_VALUE (root->right->right) !=
+      if (AST_ULONG_VALUE (root->right->right) !=
           (getSize (TTYPE (root->left->left)) * 4))
         return root;
 
@@ -5732,12 +5873,12 @@ optimizeCompare (ast * root)
         case '>':
         case '<':
         case NE_OP:
-          optExpr = newAst_VALUE (constVal ("0"));
+          optExpr = newAst_VALUE (constCharVal (0));
           break;
         case GE_OP:
         case LE_OP:
         case EQ_OP:
-          optExpr = newAst_VALUE (constVal ("1"));
+          optExpr = newAst_VALUE (constCharVal (1));
           break;
         }
 
@@ -5751,8 +5892,8 @@ optimizeCompare (ast * root)
             root->right->opval.val : NULL);
 
   /* if left is a BITVAR in BITSPACE */
-  /* and right is a LITERAL then opt- */
-  /* imize else do nothing       */
+  /* and right is a LITERAL then     */
+  /* optimize else do nothing        */
   if (vleft && vright &&
       IS_BITVAR (vleft->etype) &&
       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
@@ -5760,7 +5901,7 @@ optimizeCompare (ast * root)
     {
 
       /* if right side > 1 then comparison may never succeed */
-      if ((litValue = (int) floatFromVal (vright)) > 1)
+      if ((litValue = (int) ulFromVal (vright)) > 1)
         {
           werror (W_BAD_COMPARE);
           goto noOptimize;
@@ -5821,6 +5962,7 @@ optimizeCompare (ast * root)
 noOptimize:
   return root;
 }
+
 /*-----------------------------------------------------------------*/
 /* addSymToBlock : adds the symbol to the first block we find      */
 /*-----------------------------------------------------------------*/
@@ -5875,6 +6017,395 @@ DEFSETFUNC (resetParmKey)
   return 1;
 }
 
+/*------------------------------------------------------------------*/
+/* fixupInlineLabel - change a label in an inlined function so that */
+/*                    it is always unique no matter how many times  */
+/*                    the function is inlined.                      */
+/*------------------------------------------------------------------*/
+static void
+fixupInlineLabel (symbol * sym)
+{
+  char name[SDCC_NAME_MAX + 1];
+
+  SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
+  strcpy (sym->name, name);
+}
+
+/*------------------------------------------------------------------*/
+/* copyAstLoc - copy location information (file, line, block, etc.) */
+/*              from one ast node to another                        */
+/*------------------------------------------------------------------*/
+static void
+copyAstLoc (ast * dest, ast * src)
+{
+  dest->filename = src->filename;
+  dest->lineno = src->lineno;
+  dest->level = src->level;
+  dest->block = src->block;
+  dest->seqPoint = src->seqPoint;
+}
+
+/*-----------------------------------------------------------------*/
+/* fixupInline - perform various fixups on an inline function tree */
+/*               to take into account that it is no longer a       */
+/*               stand-alone function.                             */
+/*-----------------------------------------------------------------*/
+static void
+fixupInline (ast * tree, int level)
+{
+  int savedBlockno = currBlockno;
+
+  if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
+    {
+      symbol * decls;
+
+      currBlockno = ++blockNo;
+      level++;
+
+      /* Add any declared variables back into the symbol table */
+      decls = tree->values.sym;
+      while (decls)
+        {
+          decls->level = level;
+          decls->block = currBlockno;
+          addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
+          decls = decls->next;
+        }
+    }
+
+  tree->level = level;
+  tree->block = currBlockno;
+
+  /* Update symbols */
+  if (IS_AST_VALUE (tree) &&
+      tree->opval.val->sym)
+    {
+      symbol * sym = tree->opval.val->sym;
+
+      sym->level = level;
+      sym->block = currBlockno;
+
+      sym->reqv = NULL;
+      SYM_SPIL_LOC (sym) = NULL;
+      sym->key = 0;
+
+      /* If the symbol is a label, we need to renumber it */
+      if (sym->islbl)
+        fixupInlineLabel (sym);
+    }
+
+  /* Update IFX target labels */
+  if (tree->type == EX_OP && tree->opval.op == IFX)
+    {
+      if (tree->trueLabel)
+        fixupInlineLabel (tree->trueLabel);
+      if (tree->falseLabel)
+        fixupInlineLabel (tree->falseLabel);
+    }
+
+  /* Replace RETURN with optional assignment and a GOTO to the end */
+  /* of the inlined function */
+  if (tree->type == EX_OP && tree->opval.op == RETURN)
+    {
+      ast * assignTree = NULL;
+      ast * gotoTree;
+
+      if (inlineState.retsym && tree->right)
+        {
+          assignTree = newNode ('=',
+                                newAst_VALUE (symbolVal (inlineState.retsym)),
+                                tree->right);
+          copyAstLoc (assignTree, tree);
+        }
+
+      gotoTree = newNode (GOTO,
+                          newAst_VALUE (symbolVal (inlineState.retlab)),
+                          NULL);
+      copyAstLoc (gotoTree, tree);
+
+      tree->opval.op = NULLOP;
+      tree->left = assignTree;
+      tree->right = gotoTree;
+    }
+
+  /* Update any children */
+  if (tree->left)
+      fixupInline (tree->left, level);
+  if (tree->right)
+      fixupInline (tree->right, level);
+
+  if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
+    {
+      symbol * label = tree->left->opval.val->sym;
+
+      label->key = labelKey++;
+      /* Add this label back into the symbol table */
+      addSym (LabelTab, label, label->name, label->level, 0, 0);
+    }
+
+  if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
+    {
+      level--;
+      currBlockno = savedBlockno;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineAddDecl - add a variable declaration to an ast block. It  */
+/*                 is also added to the symbol table if addSymTab  */
+/*                 is nonzero.                                     */
+/*-----------------------------------------------------------------*/
+static void
+inlineAddDecl (symbol * sym, ast * block, int addSymTab)
+{
+  sym->reqv = NULL;
+  SYM_SPIL_LOC (sym) = NULL;
+  sym->key = 0;
+  if (block != NULL)
+    {
+      symbol **decl = &(block->values.sym);
+
+      sym->level = block->level;
+      sym->block = block->block;
+
+      while (*decl)
+        {
+          if (strcmp ((*decl)->name, sym->name) == 0)
+            return;
+          decl = &( (*decl)->next );
+        }
+
+      *decl = sym;
+
+      if (addSymTab)
+        addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
+
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineTempVar - create a temporary variable for inlining        */
+/*-----------------------------------------------------------------*/
+static symbol *
+inlineTempVar (sym_link * type, int level)
+{
+  symbol * sym;
+
+  sym = newSymbol (genSymName(level), level );
+  sym->type = copyLinkChain (type);
+  sym->etype = getSpec(sym->type);
+  SPEC_SCLS (sym->etype) = S_AUTO;
+  SPEC_OCLS (sym->etype) = NULL;
+  SPEC_EXTR (sym->etype) = 0;
+  SPEC_STAT (sym->etype) = 0;
+  if IS_SPEC (sym->type)
+    SPEC_VOLATILE (sym->type) = 0;
+  else
+    DCL_PTR_VOLATILE (sym->type) = 0;
+  SPEC_ABSA (sym->etype) = 0;
+
+  return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineFindParmRecurse - recursive function for inlineFindParm   */
+/*-----------------------------------------------------------------*/
+static ast *
+inlineFindParmRecurse (ast * parms, int *index)
+{
+  if (!parms)
+    return NULL;
+
+  if (parms->type == EX_OP && parms->opval.op == PARAM)
+  {
+    ast * p;
+
+    p=inlineFindParmRecurse (parms->left, index);
+    if (p)
+      return p;
+    p=inlineFindParmRecurse (parms->right, index);
+    if (p)
+      return p;
+  }
+  if (!*index)
+    return parms;
+  (*index)--;
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineFindParm - search an ast tree of parameters to find one   */
+/*                  at a particular index (0=first parameter).     */
+/*                  Returns NULL if not found.                     */
+/*-----------------------------------------------------------------*/
+static ast *
+inlineFindParm (ast * parms, int index)
+{
+  return inlineFindParmRecurse (parms, &index);
+}
+
+/*-----------------------------------------------------------------*/
+/* expandInlineFuncs - replace calls to inline functions with the  */
+/*                     function itself                             */
+/*-----------------------------------------------------------------*/
+static void
+expandInlineFuncs (ast * tree, ast * block)
+{
+  if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
+      && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
+    {
+      symbol * func = tree->left->opval.val->sym;
+      symbol * csym;
+
+      /* The symbol is probably not bound yet, so find the real one */
+      csym = findSymWithLevel (SymbolTab, func);
+      if (csym)
+        func = csym;
+
+      /* Is this an inline function that we can inline? */
+      if (IFFUNC_ISINLINE (func->type) && func->funcTree)
+        {
+          symbol * retsym = NULL;
+          symbol * retlab;
+          ast * inlinetree;
+          ast * inlinetree2;
+          ast * temptree;
+          value * args;
+          int argIndex;
+
+          /* Generate a label for the inlined function to branch to */
+          /* in case it contains a return statement */
+          retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
+          retlab->isitmp = 1;
+          retlab->islbl = 1;
+          inlineState.retlab = retlab;
+
+          /* Build the subtree for the inlined function in the form: */
+          /* { //inlinetree block                                    */
+          /*   { //inlinetree2 block                                 */
+          /*     inline_function_code;                               */
+          /*     retlab:                                             */
+          /*   }                                                     */
+          /* }                                                       */
+          temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
+          copyAstLoc (temptree, tree);
+          temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
+          copyAstLoc (temptree, tree);
+          temptree = newNode (BLOCK, NULL, temptree);
+          copyAstLoc (temptree, tree);
+          inlinetree2 = temptree;
+          inlinetree = newNode (BLOCK, NULL, inlinetree2);
+          copyAstLoc (inlinetree, tree);
+
+          /* To pass parameters to the inlined function, we need some  */
+          /* intermediate variables. This avoids scoping problems      */
+          /* when the parameter declaration names are used differently */
+          /* during the function call. For example, a function         */
+          /* declared as func(int x, int y) but called as func(y,x).   */
+          /* { //inlinetree block                                      */
+          /*   type1 temparg1 = argument1;                             */
+          /*   ...                                                     */
+          /*   typen tempargn = argumentn;                             */
+          /*   { //inlinetree2 block                                   */
+          /*     type1 param1 = temparg1;                              */
+          /*     ...                                                   */
+          /*     typen paramn = tempargn;                              */
+          /*     inline_function_code;                                 */
+          /*     retlab:                                               */
+          /*   }                                                       */
+          /* }                                                         */
+          args = FUNC_ARGS (func->type);
+          argIndex = 0;
+          while (args)
+            {
+              symbol * temparg;
+              ast * assigntree;
+              symbol * parm;
+              ast * passedarg = inlineFindParm (tree->right, argIndex);
+
+              if (!passedarg)
+                {
+                  werror(E_TOO_FEW_PARMS);
+                  break;
+                }
+
+              temparg = inlineTempVar (args->sym->type, tree->level+1);
+              inlineAddDecl (temparg, inlinetree, FALSE);
+
+              assigntree = newNode ('=',
+                                    newAst_VALUE (symbolVal (temparg)),
+                                    passedarg);
+              assigntree->initMode=1; // tell that assignment is initializer
+              inlinetree->right = newNode (NULLOP,
+                                           assigntree,
+                                           inlinetree->right);
+
+              parm = copySymbol (args->sym);
+              inlineAddDecl (parm, inlinetree2, FALSE);
+              parm->_isparm = 0;
+
+              assigntree = newNode ('=',
+                                    newAst_VALUE (symbolVal (parm)),
+                                    newAst_VALUE (symbolVal (temparg)));
+              assigntree->initMode=1; // tell that assignment is initializer
+              inlinetree2->right = newNode (NULLOP,
+                                           assigntree,
+                                           inlinetree2->right);
+
+              args = args->next;
+              argIndex++;
+            }
+
+          /* Handle the return type */
+          if (!IS_VOID (func->type->next))
+            {
+              /* Create a temporary symbol to hold the return value and   */
+              /* join it with the inlined function using the comma        */
+              /* operator. The fixupInline function will take care of     */
+              /* changing return statements into assignments to retsym.   */
+              /* (parameter passing and return label omitted for clarity) */
+              /* rettype retsym;                                          */
+              /* ...                                                      */
+              /* {{inline_function_code}}, retsym                         */
+
+              retsym = inlineTempVar (func->type->next, tree->level);
+              inlineAddDecl (retsym, block, TRUE);
+
+              tree->opval.op = ',';
+              tree->left = inlinetree;
+              tree->right = newAst_VALUE (symbolVal (retsym));
+            }
+          else
+            {
+              tree->opval.op = NULLOP;
+              tree->left = NULL;
+              tree->right = inlinetree;
+            }
+          inlineState.retsym = retsym;
+
+          /* Renumber the various internal counters on the inlined   */
+          /* function's tree nodes and symbols. Add the inlined      */
+          /* function's local variables to the appropriate scope(s). */
+          /* Convert inlined return statements to an assignment to   */
+          /* retsym (if needed) and a goto retlab.                   */
+          fixupInline (inlinetree, inlinetree->level);
+          inlineState.count++;
+        }
+    }
+
+  /* Recursively continue to search for functions to inline. */
+  if (IS_AST_OP (tree))
+    {
+      if (tree->opval.op == BLOCK)
+        block = tree;
+
+      if (tree->left)
+        expandInlineFuncs (tree->left, block);
+      if (tree->right)
+        expandInlineFuncs (tree->right, block);
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* createFunction - This is the key node that calls the iCode for  */
 /*                  generating the code for a function. Note code  */
@@ -5921,7 +6452,7 @@ createFunction (symbol * name, ast * body)
       addSymChain (&name);
       allocVariables (name);
     }
-  name->lastLine = lineno;
+  name->lastLine = lexLineno;
   currFunc = name;
 
   /* set the stack pointer */
@@ -5944,6 +6475,12 @@ createFunction (symbol * name, ast * body)
   if (IFFUNC_ISREENT (name->type))
     reentrant++;
 
+  inlineState.count = 0;
+  expandInlineFuncs (body, NULL);
+
+  if (FUNC_ISINLINE (name->type))
+    name->funcTree = copyAst (body);
+
   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
 
   /* do processing for parameters that are passed in registers */
@@ -5974,23 +6511,30 @@ createFunction (symbol * name, ast * body)
   ex = newNode (FUNCTION, ex, body);
   ex->values.args = FUNC_ARGS(name->type);
   ex->decorated=1;
-  if (options.dump_tree) PA(ex);
+  if (options.dump_tree)
+    PA(ex);
   if (fatalError)
-    {
-      werror (E_FUNC_NO_CODE, name->name);
-      goto skipall;
-    }
+    goto skipall;
+
+  /* Do not generate code for inline functions unless extern also. */
+#if 0
+  if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
+    goto skipall;
+#else
+  /* Temporary hack: always generate code for static inline functions. */
+  /* Ideally static inline functions should only be generated if needed. */
+  if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
+    goto skipall;
+#endif
 
   /* create the node & generate intermediate code */
   GcurMemmap = code;
   codeOutBuf = &code->oBuf;
   piCode = iCodeFromAst (ex);
+  name->generated = 1;
 
   if (fatalError)
-    {
-      werror (E_FUNC_NO_CODE, name->name);
-      goto skipall;
-    }
+    goto skipall;
 
   eBBlockFromiCode (piCode);
 
@@ -6016,7 +6560,8 @@ skipall:
 
   /* we are done freeup memory & cleanup */
   noLineno--;
-  if (port->reset_labelKey) labelKey = 1;
+  if (port->reset_labelKey)
+    labelKey = 1;
   name->key = 0;
   FUNC_HASBODY(name->type) = 1;
   addSet (&operKeyReset, name);
@@ -6120,10 +6665,10 @@ void ast_print (ast * tree, FILE *outfile, int indent)
     if (IS_LITERAL (tree->opval.val->etype)) {
       fprintf(outfile,"CONSTANT (%p) value = ", tree);
       if (SPEC_USIGN (tree->opval.val->etype))
-        fprintf(outfile,"%u", (TYPE_TARGET_ULONG) floatFromVal(tree->opval.val));
+        fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
       else
-        fprintf(outfile,"%d", (TYPE_TARGET_LONG) floatFromVal(tree->opval.val));
-      fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) floatFromVal(tree->opval.val),
+        fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
+      fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
         floatFromVal(tree->opval.val));
     } else if (tree->opval.val->sym) {
       /* if the undefined flag is set then give error message */
@@ -6688,9 +7233,9 @@ void ast_print (ast * tree, FILE *outfile, int indent)
       for (val = tree->values.switchVals.swVals; val ; val = val->next) {
         INDENT(indent+2,outfile);
         fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
-          (int) floatFromVal(val),
+          (int) ulFromVal(val),
           tree->values.switchVals.swNum,
-          (int) floatFromVal(val));
+          (int) ulFromVal(val));
       }
       ast_print(tree->right,outfile,indent);
     }