* src/SDCCast.c (resolveSymbols): added reentrancy check for parameters
[fw/sdcc] / src / SDCCast.c
index 108f6d73e7d4fc89eea38853d720f6c9dfad2cfd..97581fee14dd9027cef9b8f717dc3f4eef0d7aae 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
@@ -50,8 +55,8 @@ int labelKey = 1;
 int noLineno = 0;
 int noAlloc = 0;
 symbol *currFunc=NULL;
-static ast *createIval (ast *, sym_link *, initList *, ast *);
-static ast *createIvalCharPtr (ast *, sym_link *, ast *);
+static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
+static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
 static ast *optimizeCompare (ast *);
 ast *optimizeRRCRLC (ast *);
 ast *optimizeSWAP (ast *);
@@ -59,12 +64,12 @@ ast *optimizeGetHbit (ast *, RESULT_TYPE);
 ast *optimizeGetAbit (ast *, RESULT_TYPE);
 ast *optimizeGetByte (ast *, RESULT_TYPE);
 ast *optimizeGetWord (ast *, RESULT_TYPE);
-ast *backPatchLabels (ast *, symbol *, symbol *);
+static ast *backPatchLabels (ast *, symbol *, symbol *);
 void PA(ast *t);
 int inInitMode = 0;
 memmap *GcurMemmap=NULL;  /* points to the memmap that's currently active */
-FILE *codeOutFile;
-int 
+struct dbuf_s *codeOutBuf;
+int
 ptt (ast * tree)
 {
   printTypeChain (tree->ftype, stdout);
@@ -84,8 +89,8 @@ newAst_ (unsigned type)
   ex = Safe_alloc ( sizeof (ast));
 
   ex->type = type;
-  ex->lineno = (noLineno ? oldLineno : mylineno);
-  ex->filename = currFname;
+  ex->lineno = (noLineno ? oldLineno : lexLineno);
+  ex->filename = lexFilename;
   ex->level = NestLevel;
   ex->block = currBlockno;
   ex->initMode = inInitMode;
@@ -254,7 +259,7 @@ exit:
   return dest;
 
 }
-
+#if 0
 /*-----------------------------------------------------------------*/
 /* removeIncDecOps: remove for side effects in *_ASSIGN's          */
 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
@@ -325,9 +330,94 @@ ast *removePostIncDecOps (ast * tree) {
 
  return tree;
 }
+#endif
+/*-----------------------------------------------------------------*/
+/* replaceAstWithTemporary: Replace the AST pointed to by the arg  */
+/*            with a reference to a new temporary variable. Returns*/
+/*            an AST which assigns the original value to the       */
+/*            temporary.                                           */
+/*-----------------------------------------------------------------*/
+static ast *replaceAstWithTemporary(ast **treeptr)
+{
+  symbol *sym = newSymbol (genSymName(NestLevel), NestLevel );
+  ast *tempvar;
+
+  /* Tell gatherImplicitVariables() to automatically give the
+     symbol the correct type */
+  sym->infertype = 1;
+  sym->type = NULL;
+  sym->etype = NULL;
+
+  tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr);
+  *treeptr = newAst_VALUE(symbolVal(sym));
+
+  addSymChain(&sym);
+
+  return tempvar;
+}
+
+/*-----------------------------------------------------------------*/
+/* createRMW: Create a read-modify-write expression, using a       */
+/*            temporary variable if necessary to avoid duplicating */
+/*            any side effects, for use in e.g.                    */
+/*               foo()->count += 5;      becomes                   */
+/*               tmp = foo(); tmp->count = tmp->count + 5;         */
+/*-----------------------------------------------------------------*/
+ast * createRMW (ast *target, unsigned op, ast *operand)
+{
+  ast *readval, *writeval;
+  ast *tempvar1 = NULL;
+  ast *tempvar2 = NULL;
+  ast *result;
+
+  if (!target || !operand) {
+    return NULL;
+  }
+
+  /* we need to create two copies of target: one to read from and
+     one to write to. but we need to do this without duplicating
+     any side effects that may be contained in the tree. */
+
+  if (IS_AST_OP(target)) {
+    /* if this is a dereference, put the referenced item in the temporary */
+    if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) {
+      /* create a new temporary containing the item being dereferenced */
+      if (hasSEFcalls(target->left))
+        tempvar1 = replaceAstWithTemporary(&(target->left));
+    } else if (target->opval.op == '[') {
+      /* Array access is similar, but we have to avoid side effects in
+         both values [WIML: Why not transform a[b] to *(a+b) in parser?] */
+      if (hasSEFcalls(target->left))
+        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");
+
+      /* no other kinds of ASTs are lvalues and can contain side effects */
+    }
+  }
+
+  readval = target;
+  writeval = copyAst(target);
+
+  result = newNode('=', writeval, newNode(op, readval, operand));
+  if (tempvar2)
+    result = newNode(',', tempvar2, result);
+  if (tempvar1)
+    result = newNode(',', tempvar1, result);
+
+  return result;
+
+}
 
 /*-----------------------------------------------------------------*/
-/* hasSEFcalls - returns TRUE if tree has a function call          */
+/* hasSEFcalls - returns TRUE if tree has a function call,         */
+/*               inc/decrement, or other side effect               */
 /*-----------------------------------------------------------------*/
 bool
 hasSEFcalls (ast * tree)
@@ -479,7 +569,7 @@ resolveSymbols (ast * tree)
 
       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;
@@ -488,8 +578,8 @@ 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)
         {
 
@@ -589,23 +679,23 @@ funcOfType (char *name, sym_link * type, sym_link * argType,
 symbol *
 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
 {
-  
+
     symbol *sym;
     int i ;
     /* create the symbol */
     sym = newSymbol (name, 0);
-    
+
     /* setup return value */
     sym->type = newLink (DECLARATOR);
     DCL_TYPE (sym->type) = FUNCTION;
     sym->type->next = typeFromStr(rtype);
     sym->etype = getSpec (sym->type);
-    
+
     /* if arguments required */
     if (nArgs) {
         value *args;
         args = FUNC_ARGS(sym->type) = newValue ();
-        
+
         for ( i = 0 ; i < nArgs ; i++ ) {
             args->type = typeFromStr(atypes[i]);
             args->etype = getSpec (args->type);
@@ -647,7 +737,7 @@ reverseParms (ast * ptree)
           ttree->left = ptree->left;
           ptree->left = ttree;
         }
-    
+
       /* Now reverse */
       ttree = ptree->left;
       ptree->left = ptree->right;
@@ -673,7 +763,7 @@ processParms (ast *func,
 {
   RESULT_TYPE resultType;
   sym_link *functype;
-  
+
   /* if none of them exist */
   if (!defParm && !*actParm)
     return 0;
@@ -692,16 +782,16 @@ processParms (ast *func,
     functype = func->ftype->next;
   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;
         }
@@ -747,7 +837,7 @@ processParms (ast *func,
     }
 
   /* decorate parameter */
-  resultType = defParm ? getResultTypeFromType (defParm->etype) :
+  resultType = defParm ? getResultTypeFromType (defParm->type) :
                          RESULT_TYPE_NONE;
   *actParm = decorateType (*actParm, resultType);
 
@@ -776,7 +866,7 @@ processParms (ast *func,
       if (IS_INTEGRAL (ftype)
           && (getSize (ftype) < (unsigned) INTSIZE))
         {
-          newType = newAst_LINK(INTTYPE);  
+          newType = newAst_LINK(INTTYPE);
         }
 
       if (IS_PTR(ftype) && !IS_GENPTR(ftype))
@@ -790,14 +880,14 @@ processParms (ast *func,
           newType = newAst_LINK (copyLinkChain (ftype));
           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
         }
-      
+
       if (newType)
         {
           /* cast required; change this op to a cast. */
           (*actParm)->decorated = 0;
            *actParm = newNode (CAST, newType, *actParm);
           (*actParm)->lineno = (*actParm)->right->lineno;
-          
+
           decorateType (*actParm, RESULT_TYPE_NONE);
         }
       return 0;
@@ -810,7 +900,7 @@ processParms (ast *func,
     return 0;
 
   resolveSymbols (*actParm);
-  
+
   /* the parameter type must be at least castable */
   if (compareType (defParm->type, (*actParm)->ftype) == 0)
     {
@@ -826,7 +916,7 @@ processParms (ast *func,
 
       resultType = getResultTypeFromType (defParm->etype);
       pTree = resolveSymbols (copyAst (*actParm));
-      
+
       /* now change the current one to a cast */
       (*actParm)->type = EX_OP;
       (*actParm)->opval.op = CAST;
@@ -840,6 +930,18 @@ processParms (ast *func,
   (*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;
 }
@@ -864,7 +966,7 @@ createIvalType (ast * sym, sym_link * type, initList * ilist)
 /* createIvalStruct - generates initial value for structures       */
 /*-----------------------------------------------------------------*/
 static ast *
-createIvalStruct (ast * sym, sym_link * type, initList * ilist)
+createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
 {
   ast *rast = NULL;
   ast *lAst;
@@ -888,12 +990,15 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist)
       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)), RESULT_TYPE_NONE);
+      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
+                                                       iloop, rast, rootValue)),
+                           RESULT_TYPE_NONE);
+
     }
 
   if (iloop) {
     werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
-              W_EXCESS_INITIALIZERS, "struct", 
+              W_EXCESS_INITIALIZERS, "struct",
               sym->opval.val->sym->name);
   }
 
@@ -905,7 +1010,7 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist)
 /* createIvalArray - generates code for array initialization       */
 /*-----------------------------------------------------------------*/
 static ast *
-createIvalArray (ast * sym, sym_link * type, initList * ilist)
+createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
 {
   ast *rast = NULL;
   initList *iloop;
@@ -918,84 +1023,83 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
   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)
-    {
-        werror (E_INIT_STRUCT, "");
-        return NULL;
-    }
+  /* not the special case             */
+  if (ilist->type != INIT_DEEP)
+  {
+      werror (E_INIT_STRUCT, "");
+      return NULL;
+  }
 
-    iloop = ilist->init.deep;
-    lcnt = DCL_ELEM (type);
+  iloop = ilist->init.deep;
+  lcnt = DCL_ELEM (type);
 
-    if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
-    {
-        ast *aSym;
+  if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
+  {
+      ast *aSym;
 
-        aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
-        
-        rast = newNode(ARRAYINIT, aSym, NULL);
-        rast->values.constlist = literalL;
-        
-        // 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);
-        }
-    }
-    else
-    {
-        for (;;)
-        {
-            ast *aSym;
-            
-            aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
-            aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
-            rast = createIval (aSym, type->next, iloop, rast);
-            iloop = (iloop ? iloop->next : NULL);
-            if (!iloop)
-            {
-                break;
-            }
-            
-            /* no of elements given and we    */
-            /* have generated for all of them */
-            if (!--lcnt) 
-            {
-                // 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);
-                
-                break;
-            }
-        }
-    }
+      aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
+
+      rast = newNode(ARRAYINIT, aSym, NULL);
+      rast->values.constlist = literalL;
+
+      // 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.
+          werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+            W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
+      }
+  }
+  else
+  {
+      for (;;)
+      {
+          ast *aSym;
+
+          aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
+          aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
+          rast = createIval (aSym, type->next, iloop, rast, rootValue);
+          iloop = (iloop ? iloop->next : NULL);
+          if (!iloop)
+          {
+              break;
+          }
+
+          /* no of elements given and we    */
+          /* have generated for all of them */
+          if (!--lcnt)
+          {
+              // is this a better way? at least it won't crash
+              char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+              werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
 
-    /* if we have not been given a size  */
-    if (!DCL_ELEM (type))
+              break;
+          }
+      }
+  }
+
+  /* if we have not been given a size  */
+  if (!DCL_ELEM (type))
     {
-        /* but this still updates the typedef instead of the instance ! see bug 770487 */
+      /* check, if it's a flexible array */
+      if (IS_STRUCT (AST_VALUE (rootValue)->type))
+        AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
+      else
         DCL_ELEM (type) = size;
     }
 
-    return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
+  return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 }
 
 
@@ -1003,9 +1107,10 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
 /* createIvalCharPtr - generates initial values for char pointers  */
 /*-----------------------------------------------------------------*/
 static ast *
-createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
+createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
 {
   ast *rast = NULL;
+  unsigned size = 0;
 
   /* if this is a pointer & right is a literal array then */
   /* just assignment will do                              */
@@ -1014,8 +1119,7 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
                         && 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 ((IS_LITERAL (iexpr->etype) ||
        SPEC_SCLS (iexpr->etype) == S_CODE)
       && IS_ARRAY (iexpr->ftype))
@@ -1023,15 +1127,19 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
       /* for each character generate an assignment */
       /* to the array element */
       char *s = SPEC_CVAL (iexpr->etype).v_char;
-      int i = 0;
-      int size = getSize (iexpr->ftype);
-      int symsize = getSize (type);
-      
-      if (size>symsize)
+      unsigned int i = 0;
+      unsigned int symsize = getSize (type);
+
+      size = getSize (iexpr->ftype);
+      if (symsize && size>symsize)
         {
           if (size>(symsize+1))
-            werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
-                      "string", sym->opval.val->sym->name);
+            {
+              char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+
+              werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+                        "string", name);
+            }
           size = symsize;
         }
 
@@ -1049,6 +1157,16 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
       // now WE don't need iexpr's symbol anymore
       freeStringSymbol(AST_SYMBOL(iexpr));
 
+      /* if we have not been given a size  */
+      if (!DCL_ELEM (type))
+        {
+          /* check, if it's a flexible array */
+          if (IS_STRUCT (AST_VALUE (rootVal)->type))
+            AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
+          else
+            DCL_ELEM (type) = size;
+        }
+
       return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
     }
 
@@ -1059,7 +1177,7 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
 /* createIvalPtr - generates initial value for pointers            */
 /*-----------------------------------------------------------------*/
 static ast *
-createIvalPtr (ast * sym, sym_link * type, initList * ilist)
+createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
 {
   ast *rast;
   ast *iexpr;
@@ -1072,7 +1190,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist)
 
   /* if character pointer */
   if (IS_CHAR (type->next))
-    if ((rast = createIvalCharPtr (sym, type, iexpr)))
+    if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
       return rast;
 
   return newNode ('=', sym, iexpr);
@@ -1082,7 +1200,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist)
 /* createIval - generates code for initial value                   */
 /*-----------------------------------------------------------------*/
 static ast *
-createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
+createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
 {
   ast *rast = NULL;
 
@@ -1091,15 +1209,15 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
 
   /* if structure then    */
   if (IS_STRUCT (type))
-    rast = createIvalStruct (sym, type, ilist);
+    rast = createIvalStruct (sym, type, ilist, rootValue);
   else
     /* if this is a pointer */
   if (IS_PTR (type))
-    rast = createIvalPtr (sym, type, ilist);
+    rast = createIvalPtr (sym, type, ilist, rootValue);
   else
     /* if this is an array   */
   if (IS_ARRAY (type))
-    rast = createIvalArray (sym, type, ilist);
+    rast = createIvalArray (sym, type, ilist, rootValue);
   else
     /* if type is SPECIFIER */
   if (IS_SPEC (type))
@@ -1115,12 +1233,13 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
 /* initAggregates - initialises aggregate variables with initv     */
 /*-----------------------------------------------------------------*/
 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
-  return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, 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)
@@ -1160,7 +1279,7 @@ gatherAutoInit (symbol * autoChain)
           SPEC_SCLS (sym->etype) != S_CODE)
         {
           symbol *newSym;
-          
+
           /* insert the symbol into the symbol table */
           /* with level = 0 & name = rname       */
           newSym = copySymbol (sym);
@@ -1172,7 +1291,7 @@ gatherAutoInit (symbol * autoChain)
           } else {
             if (getNelements(sym->type, sym->ival)>1) {
               werrorfl (sym->fileDef, sym->lineDef,
-                        W_EXCESS_INITIALIZERS, "scalar", 
+                        W_EXCESS_INITIALIZERS, "scalar",
                         sym->name);
             }
             work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
@@ -1194,27 +1313,27 @@ gatherAutoInit (symbol * autoChain)
       if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
         {
           initList *ilist=sym->ival;
-          
+
           while (ilist->type == INIT_DEEP) {
             ilist = ilist->init.deep;
           }
 
           /* update lineno for error msg */
-          lineno=sym->lineDef;
-          setAstLineno (ilist->init.node, lineno);
-          
+          lineno = sym->lineDef;
+          setAstLineno (ilist->init.node, 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", 
+                        W_EXCESS_INITIALIZERS, "scalar",
                         sym->name);
             }
             work = newNode ('=', newAst_VALUE (symbolVal (sym)),
                             list2expr (sym->ival));
           }
-          
+
           // just to be sure
           setAstLineno (work, sym->lineDef);
 
@@ -1242,7 +1361,7 @@ void freeStringSymbol(symbol *sym) {
     }
   }
 }
-  
+
 /*-----------------------------------------------------------------*/
 /* stringToSymbol - creates a symbol from a literal string         */
 /*-----------------------------------------------------------------*/
@@ -1314,7 +1433,7 @@ processBlockVars (ast * tree, int *stack, int action)
         {
           *stack += allocVariables (tree->values.sym);
           autoInit = gatherAutoInit (tree->values.sym);
-        
+
           /* if there are auto inits then do them */
           if (autoInit)
             tree->left = newNode (NULLOP, autoInit, tree->left);
@@ -1341,7 +1460,7 @@ bool constExprTree (ast *cexpr) {
 
   cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
 
-  switch (cexpr->type) 
+  switch (cexpr->type)
     {
     case EX_VALUE:
       if (IS_AST_LIT_VALUE(cexpr)) {
@@ -1356,7 +1475,7 @@ bool constExprTree (ast *cexpr) {
         // an array's address will never change
         return TRUE;
       }
-      if (IS_AST_SYM_VALUE(cexpr) && 
+      if (IS_AST_SYM_VALUE(cexpr) &&
           IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
         // a symbol in code space will never change
         // This is only for the 'char *s="hallo"' case and will have to leave
@@ -1380,7 +1499,7 @@ bool constExprTree (ast *cexpr) {
         // cast ignored, maybe we should throw a warning here?
         return constExprTree(cexpr->right);
       }
-      if (cexpr->opval.op=='&') { 
+      if (cexpr->opval.op=='&') {
         return TRUE;
       }
       if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
@@ -1395,7 +1514,7 @@ bool constExprTree (ast *cexpr) {
     }
   return FALSE;
 }
-    
+
 /*-----------------------------------------------------------------*/
 /* constExprValue - returns the value of a constant expression     */
 /*                  or NULL if it is not a constant expression     */
@@ -1428,13 +1547,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)
@@ -1444,14 +1563,17 @@ constExprValue (ast * cexpr, int check)
     }
 
   /* return the value */
-  return cexpr->opval.val;
-
+  if (IS_AST_VALUE (cexpr))
+    {
+      return cexpr->opval.val;
+    }
+  return NULL;
 }
 
 /*-----------------------------------------------------------------*/
 /* isLabelInAst - will return true if a given label is found       */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isLabelInAst (symbol * label, ast * tree)
 {
   if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
@@ -1464,14 +1586,13 @@ isLabelInAst (symbol * label, ast * tree)
 
   return isLabelInAst (label, tree->right) &&
     isLabelInAst (label, tree->left);
-
 }
 
 /*-----------------------------------------------------------------*/
 /* isLoopCountable - return true if the loop count can be determi- */
 /* -ned at compile time .                                          */
 /*-----------------------------------------------------------------*/
-bool 
+static bool
 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
                  symbol ** sym, ast ** init, ast ** end)
 {
@@ -1496,6 +1617,10 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
   else
     return FALSE;
 
+  /* don't reverse loop with volatile counter */
+  if (IS_VOLATILE ((*sym)->type))
+    return FALSE;
+
   /* for now the symbol has to be of
      integral type */
   if (!IS_INTEGRAL ((*sym)->type))
@@ -1573,7 +1698,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;
         }
     }
@@ -1584,7 +1709,7 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
 /*-----------------------------------------------------------------*/
 /* astHasVolatile - returns true if ast contains any volatile      */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 astHasVolatile (ast * tree)
 {
   if (!tree)
@@ -1603,7 +1728,7 @@ astHasVolatile (ast * tree)
 /*-----------------------------------------------------------------*/
 /* astHasPointer - return true if the ast contains any ptr variable */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 astHasPointer (ast * tree)
 {
   if (!tree)
@@ -1628,7 +1753,7 @@ astHasPointer (ast * tree)
 /*-----------------------------------------------------------------*/
 /* astHasSymbol - return true if the ast has the given symbol      */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 astHasSymbol (ast * tree, symbol * sym)
 {
   if (!tree || IS_AST_LINK (tree))
@@ -1649,14 +1774,14 @@ astHasSymbol (ast * tree, symbol * sym)
 /*-----------------------------------------------------------------*/
 /* astHasDeref - return true if the ast has an indirect access     */
 /*-----------------------------------------------------------------*/
-static bool 
+static bool
 astHasDeref (ast * tree)
 {
   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
     return FALSE;
 
   if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
-  
+
   return astHasDeref (tree->left) || astHasDeref (tree->right);
 }
 
@@ -1664,7 +1789,7 @@ 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      */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isConformingBody (ast * pbody, symbol * sym, ast * body)
 {
 
@@ -1683,7 +1808,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
   /* if we reach the end or a leaf then true */
   if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
     return TRUE;
-  
+
   /* if anything else is "volatile" */
   if (IS_VOLATILE (TETYPE (pbody)))
     return FALSE;
@@ -1865,7 +1990,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 /*----------------------------*/
     case CALL:
         /* if local & not passed as paramater then ok */
-        if (sym->level && !astHasSymbol(pbody->right,sym)) 
+        if (sym->level && !astHasSymbol(pbody->right,sym))
             return TRUE;
       return FALSE;
 
@@ -1901,7 +2026,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 /* if the for loop is reversible. If yes will set the value of     */
 /* the loop control var & init value & termination value           */
 /*-----------------------------------------------------------------*/
-bool
+static bool
 isLoopReversible (ast * loop, symbol ** loopCntrl,
                   ast ** init, ast ** end)
 {
@@ -1931,7 +2056,7 @@ isLoopReversible (ast * loop, symbol ** loopCntrl,
 /*-----------------------------------------------------------------*/
 /* replLoopSym - replace the loop sym by loop sym -1               */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 replLoopSym (ast * body, symbol * sym)
 {
   /* reached end */
@@ -2011,7 +2136,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
 /* searchLitOp - search tree (*ops only) for an ast with literal */
 /*-----------------------------------------------------------------*/
 static ast *
-searchLitOp (ast *tree, ast **parent, const unsigned char *ops)
+searchLitOp (ast *tree, ast **parent, const char *ops)
 {
   ast *ret;
 
@@ -2021,7 +2146,7 @@ searchLitOp (ast *tree, ast **parent, const unsigned char *ops)
       if (tree->right &&
           IS_AST_OP(tree->right) &&
           tree->right->right &&
-          (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1]))
+          (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
         {
           if (IS_LITERAL (RTYPE (tree->right)) !=
               IS_LITERAL (LTYPE (tree->right)))
@@ -2038,7 +2163,7 @@ searchLitOp (ast *tree, ast **parent, const unsigned char *ops)
       if (tree->left &&
           IS_AST_OP(tree->left) &&
           tree->left->right &&
-          (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
+          (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
         {
           if (IS_LITERAL (RTYPE (tree->left)) !=
               IS_LITERAL (LTYPE (tree->left)))
@@ -2068,7 +2193,7 @@ getResultTypeFromType (sym_link *type)
   if (IS_BITFIELD (type))
     {
       int blen = SPEC_BLEN (type);
-      
+
       if (blen <= 1)
         return RESULT_TYPE_BIT;
       if (blen <= 8)
@@ -2077,8 +2202,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;
 }
@@ -2091,7 +2215,7 @@ addCast (ast *tree, RESULT_TYPE resultType, bool promote)
 {
   sym_link *newLink;
   bool upCasted = FALSE;
-  
+
   switch (resultType)
     {
       case RESULT_TYPE_NONE:
@@ -2137,11 +2261,11 @@ addCast (ast *tree, RESULT_TYPE resultType, bool promote)
         newLink = newIntLink();
         upCasted = TRUE;
         break;
+      case RESULT_TYPE_IFX:
       case RESULT_TYPE_OTHER:
-        if (!promote)
-          return tree;
-        /* return type is long, float: promote char to int */
-        if (getSize (tree->etype) >= INTSIZE)
+        if (!promote ||
+            /* return type is ifx, long, float: promote char to int */
+            getSize (tree->etype) >= INTSIZE)
           return tree;
         newLink = newIntLink();
         upCasted = TRUE;
@@ -2169,17 +2293,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)
@@ -2216,7 +2345,7 @@ getLeftResultType (ast *tree, RESULT_TYPE resultType)
       case '[':
         if (!IS_ARRAY (LTYPE (tree)))
           return resultType;
-        if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256)
+        if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
           return RESULT_TYPE_CHAR;
         return resultType;
       default:
@@ -2224,10 +2353,77 @@ getLeftResultType (ast *tree, RESULT_TYPE resultType)
     }
 }
 
+/*------------------------------------------------------------------*/
+/* gatherImplicitVariables: assigns correct type information to     */
+/*            symbols and values created by replaceAstWithTemporary */
+/*            and adds the symbols to the declarations list of the  */
+/*            innermost block that contains them                    */
+/*------------------------------------------------------------------*/
+void
+gatherImplicitVariables (ast * tree, ast * block)
+{
+  if (!tree)
+    return;
+
+  if (tree->type == EX_OP && tree->opval.op == BLOCK)
+    {
+      /* keep track of containing scope */
+      block = tree;
+    }
+  if (tree->type == EX_OP && tree->opval.op == '=' &&
+      tree->left->type == EX_VALUE && tree->left->opval.val->sym)
+    {
+      symbol *assignee = tree->left->opval.val->sym;
+
+      /* special case for assignment to compiler-generated temporary variable:
+         compute type of RHS, and set the symbol's type to match */
+      if (assignee->type == NULL && assignee->infertype) {
+        ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
+
+        if (dtr != tree->right)
+          tree->right = dtr;
+
+        assignee->type = copyLinkChain(TTYPE(dtr));
+        assignee->etype = getSpec(assignee->type);
+        SPEC_SCLS (assignee->etype) = S_AUTO;
+        SPEC_OCLS (assignee->etype) = NULL;
+        SPEC_EXTR (assignee->etype) = 0;
+        SPEC_STAT (assignee->etype) = 0;
+        SPEC_VOLATILE (assignee->etype) = 0;
+        SPEC_ABSA (assignee->etype) = 0;
+
+        wassertl(block != NULL, "implicit variable not contained in block");
+        wassert(assignee->next == NULL);
+        if (block != NULL) {
+          symbol **decl = &(block->values.sym);
+
+          while (*decl) {
+            wassert(*decl != assignee);  /* should not already be in list */
+            decl = &( (*decl)->next );
+          }
+
+          *decl = assignee;
+        }
+      }
+    }
+  if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
+      tree->opval.val->type == NULL &&
+      tree->opval.val->sym &&
+      tree->opval.val->sym->infertype)
+    {
+      /* fixup type of value for compiler-inferred temporary var */
+      tree->opval.val->type = tree->opval.val->sym->type;
+      tree->opval.val->etype = tree->opval.val->sym->etype;
+    }
+
+  gatherImplicitVariables(tree->left, block);
+  gatherImplicitVariables(tree->right, block);
+}
+
 /*--------------------------------------------------------------------*/
 /* decorateType - compute type for this tree, also does type checking.*/
 /* This is done bottom up, since type has to flow upwards.            */
-/* resultType flows top-down and forces e.g. char-arithmetik, if the  */
+/* resultType flows top-down and forces e.g. char-arithmetic, if the  */
 /* result is a char and the operand(s) are int's.                     */
 /* It also does constant folding, and parameter checking.             */
 /*--------------------------------------------------------------------*/
@@ -2270,7 +2466,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 /*----------------------------*/
 /*   leaf has been reached    */
 /*----------------------------*/
-  lineno=tree->lineno;
+  lineno = tree->lineno;
   /* if this is of type value */
   /* just get the type        */
   if (tree->type == EX_VALUE)
@@ -2293,31 +2489,29 @@ 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 =
                 tree->opval.val->etype = tree->opval.val->sym->etype =
                 copyLinkChain (INTTYPE);
             }
+          else if (tree->opval.val->sym->implicit)
+            {
+              /* if implicit i.e. struct/union member then no type */
+              TTYPE (tree) = TETYPE (tree) = NULL;
+            }
           else
             {
+              /* copy the type from the value into the ast */
+              COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
 
-              /* if impilicit i.e. struct/union member then no type */
-              if (tree->opval.val->sym->implicit)
-                TTYPE (tree) = TETYPE (tree) = NULL;
-
-              else
-                {
-
-                  /* else copy the type */
-                  COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
-
-                  /* and mark it as referenced */
-                  tree->opval.val->sym->isref = 1;
-                }
+              /* and mark the symbol as referenced */
+              tree->opval.val->sym->isref = 1;
             }
         }
+      else
+        wassert(0); /* unreached: all values are literals or symbols */
 
       return tree;
     }
@@ -2358,7 +2552,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);
@@ -2380,7 +2574,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
        in tree->left->?type. If the op is e.g. '=' we extract the type
        information from there and propagate it to the right branch. */
     resultTypeProp = getLeftResultType (tree, resultTypeProp);
-    
+
     switch (tree->opval.op)
       {
         case '?':
@@ -2388,12 +2582,18 @@ decorateType (ast * tree, RESULT_TYPE resultType)
              expansions might rely on this */
           dtr = tree->right;
           break;
-        case CALL: 
+        case CALL:
           /* decorate right side for CALL (parameter list) in processParms();
              there is resultType available */
           dtr = tree->right;
           break;
-        default:     
+        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;
       }
@@ -2421,36 +2621,37 @@ 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);
             }
         }
 
       RRVAL (tree) = 1;
       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
+      SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2461,7 +2662,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),
@@ -2478,13 +2679,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;
         }
 
@@ -2496,19 +2697,19 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* adjust the storage class */
       switch (DCL_TYPE(tree->left->ftype)) {
       case POINTER:
-        SPEC_SCLS(TETYPE(tree)) = S_DATA; 
+        SPEC_SCLS(TETYPE(tree)) = S_DATA;
         break;
       case FPOINTER:
-        SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
+        SPEC_SCLS(TETYPE(tree)) = S_XDATA;
         break;
       case CPOINTER:
-        SPEC_SCLS(TETYPE(tree)) = S_CODE; 
+        SPEC_SCLS(TETYPE(tree)) = S_CODE;
         break;
       case GPOINTER:
         SPEC_SCLS (TETYPE (tree)) = 0;
         break;
       case PPOINTER:
-        SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
+        SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
         break;
       case IPOINTER:
         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
@@ -2523,7 +2724,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       case FUNCTION:
         break;
       }
-      
+
       /* This breaks with extern declarations, bitfields, and perhaps other */
       /* cases (gcse). Let's leave this optimization disabled for now and   */
       /* ponder if there's a safe way to do this. -- EEP                    */
@@ -2552,7 +2753,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             SPEC_ABSA(sym->etype) = 1;
             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
             allocGlobal (sym);
-            
+
             AST_VALUE (tree) = symbolVal(sym);
             TLVAL (tree) = 1;
             TRVAL (tree) = 0;
@@ -2561,7 +2762,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             tree->right = NULL;
         }
       #endif
-      
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2574,7 +2775,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;
@@ -2594,8 +2795,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);
@@ -2679,7 +2880,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             }
 
           LRVAL (tree) = RRVAL (tree) = 1;
-          
+
           TTYPE (tree) = computeType (LTYPE (tree),
                                       RTYPE (tree),
                                       resultType,
@@ -2697,13 +2898,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;
         }
 
@@ -2715,13 +2916,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))
@@ -2780,7 +2981,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
         ast *wtree = optimizeRRCRLC (tree);
         if (wtree != tree)
           return decorateType (wtree, RESULT_TYPE_NONE);
-        
+
         wtree = optimizeSWAP (tree);
         if (wtree != tree)
           return decorateType (wtree, RESULT_TYPE_NONE);
@@ -2820,8 +3021,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);
@@ -2886,7 +3087,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 */
@@ -2915,7 +3116,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* rearrange the tree */
       if (IS_LITERAL (RTYPE (tree))
           /* avoid infinite loop */
-          && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
+          && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
         {
           ast *parent;
           ast *litTree = searchLitOp (tree, &parent, "/");
@@ -2953,8 +3154,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);
@@ -2990,13 +3191,13 @@ 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))
@@ -3012,16 +3213,16 @@ decorateType (ast * tree, RESULT_TYPE resultType)
               SPEC_SCLS(TETYPE(tree)) = S_DATA;
               break;
             case FPOINTER:
-              SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
+              SPEC_SCLS(TETYPE(tree)) = S_XDATA;
               break;
             case CPOINTER:
-              SPEC_SCLS(TETYPE(tree)) = S_CODE; 
+              SPEC_SCLS(TETYPE(tree)) = S_CODE;
               break;
             case GPOINTER:
               SPEC_SCLS (TETYPE (tree)) = 0;
               break;
             case PPOINTER:
-              SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
+              SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
               break;
             case IPOINTER:
               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
@@ -3045,7 +3246,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;
         }
 
@@ -3089,8 +3290,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),
@@ -3109,7 +3310,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;
             }
 
@@ -3137,21 +3338,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 */
@@ -3159,8 +3360,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;
@@ -3230,15 +3431,15 @@ 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),
                                                   resultType,
                                                   tree->opval.op));
         }
-        
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3252,7 +3453,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;
             }
 
@@ -3263,11 +3464,15 @@ decorateType (ast * tree, RESULT_TYPE resultType)
               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
               tree->left = NULL;
               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-              SPEC_USIGN(TETYPE(tree)) = 0;
               return tree;
             }
+          tree->left  = addCast (tree->left, resultTypeProp, TRUE);
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                     computeType (LTYPE (tree),
+                                                  NULL,
+                                                  resultType,
+                                                  tree->opval.op));
           LRVAL (tree) = 1;
-          TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
           return tree;
         }
 
@@ -3280,7 +3485,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;
         }
 
@@ -3288,7 +3493,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;
         }
 
@@ -3296,7 +3501,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;
         }
 
@@ -3305,8 +3510,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;
@@ -3338,8 +3543,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),
@@ -3355,7 +3560,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* rearrange the tree */
       if (IS_LITERAL (RTYPE (tree))
           /* avoid infinite loop */
-          && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
+          && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
         {
           ast *litTree, *litParent;
           litTree = searchLitOp (tree, &litParent, "+-");
@@ -3383,7 +3588,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                       tree->right = litParent->left;
                       litParent->left = tTree;
                       litTree->opval.op = '+';
-                      
+
                       tree->decorated = 0;
                       decorateType (tree, resultType);
                     }
@@ -3409,7 +3614,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;
         }
 
@@ -3420,7 +3625,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 &&
@@ -3431,14 +3636,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");
         }
       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;
@@ -3453,10 +3658,29 @@ 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 (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")));
+          tree->right->lineno = tree->lineno;
+          tree->decorated = 0;
+          return decorateType (tree, resultType);
+        }
+
       /* if left is a literal then do it */
       if (IS_LITERAL (LTYPE (tree)))
         {
@@ -3498,8 +3722,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);
@@ -3509,8 +3733,8 @@ 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 */
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
@@ -3563,14 +3787,13 @@ 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_UDWORD) 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;
@@ -3590,7 +3813,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;
         }
 
@@ -3598,6 +3821,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 (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
+        {
+          return tree->right;
+        }
+
       /* If code memory is read only, then pointers to code memory */
       /* implicitly point to constants -- make this explicit       */
       {
@@ -3628,9 +3858,9 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                       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 */  {
+                         ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
                       sym_link *rest = LTYPE(tree)->next;
-                      werror(W_LITERAL_GENERIC);
+                      werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
                       TTYPE(tree) = newLink(DECLARATOR);
                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
                       TTYPE(tree)->next = rest;
@@ -3651,19 +3881,20 @@ 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);
 
-        if (IS_GENPTR (LTYPE (tree)) && GPTRSIZE > FPTRSIZE)
+        if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
+                                        || TARGET_IS_PIC16) )
           {
             switch (SPEC_SCLS (sym->etype))
               {
@@ -3682,10 +3913,13 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                 break;
               default:
                 gptype = 0;
+
+                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);
@@ -3801,7 +4035,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;
         }
 
@@ -3809,7 +4043,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 */
@@ -3859,7 +4093,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 ");
@@ -3876,7 +4110,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 ");
@@ -3885,36 +4119,71 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                 goto errorTreeReturn;
               }
         }
-      /* if unsigned value < 0  then always false */
+
+      {
+        CCR_RESULT ccr_result = CCR_OK;
+
+        /* if left is integral and right is literal
+           then check constant range */
+        if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
+          ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
+                                           tree->opval.op, FALSE);
+        if (ccr_result == CCR_OK &&
+            IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
+          ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
+                                           tree->opval.op, TRUE);
+        switch (ccr_result)
+            {
+              case CCR_ALWAYS_TRUE:
+              case CCR_ALWAYS_FALSE:
+                if (!options.lessPedantic)
+                  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);
+              case CCR_OK:
+              default:
+                break;
+            }
+      }
+
       /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
-      if (SPEC_USIGN(LETYPE(tree)) &&
-          !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */
+      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 (tree->opval.op == '<')
+          if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
             {
-              return tree->right;
-            }
-          if (tree->opval.op == '>')
-            {
-              if (resultType == RESULT_TYPE_IFX)
-                {
-                  /* the parent is an ifx: */
-                  /* if (unsigned value) */
-                  return tree->left;
-                }
-              
-              /* (unsigned value) ? 1 : 0 */
-              tree->opval.op = '?';
-              tree->right = newNode (':',
-                                     newAst_VALUE (constVal ("1")),
-                                     tree->right); /* val 0 */
-              tree->right->lineno = tree->lineno;
-              tree->right->left->lineno = tree->lineno;
-              decorateType (tree->right, RESULT_TYPE_NONE);
+              /* the parent is an ifx: */
+              /* if (unsigned value) */
+              return tree->left;
             }
+
+          /* (unsigned value) ? 1 : 0 */
+          tree->opval.op = '?';
+          tree->right = newNode (':',
+                                  newAst_VALUE (constVal ("1")),
+                                  tree->right); /* val 0 */
+          tree->right->lineno = tree->lineno;
+          tree->right->left->lineno = tree->lineno;
+          tree->decorated = 0;
+          return decorateType (tree, resultType);
+        }
+
+      /* 'ifx (op == 0)' -> 'ifx (!(op))' */
+      if (IS_LITERAL(RTYPE(tree))  &&
+          floatFromVal (valFromType (RETYPE (tree))) == 0 &&
+          tree->opval.op == EQ_OP &&
+          (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
+        {
+          tree->opval.op = '!';
+          tree->right = NULL;
+          tree->decorated = 0;
+          return decorateType (tree, resultType);
         }
+
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) &&
@@ -3929,8 +4198,84 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                    tree->opval.val->type);
           return tree;
         }
+
+      /* if one is 'signed char ' and the other one is 'unsigned char' */
+      /* it's necessary to promote to int */
+      if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
+          (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
+        {
+          /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
+             if it's possible to use a 'signed char' */
+
+              /* is left a 'unsigned char'? */
+          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) 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) ulFromVal (valFromType (LETYPE (tree))) < 128)
+            {
+              SPEC_USIGN (LETYPE (tree)) = 0;
+            }
+          else
+            {
+              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) = newCharLink ();
+      TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
+
+      /* condition transformations */
+      {
+        unsigned transformedOp = 0;
+
+        switch (tree->opval.op)
+          {
+            case '<':             /* transform (a < b)  to !(a >= b)  */
+              if (port->lt_nge)
+                transformedOp = GE_OP;
+              break;
+            case '>':             /* transform (a > b)  to !(a <= b)  */
+              if (port->gt_nle)
+                transformedOp = LE_OP;
+              break;
+            case LE_OP:           /* transform (a <= b) to !(a > b)   */
+              if (port->le_ngt)
+                transformedOp = '>';
+              break;
+            case GE_OP:           /* transform (a >= b) to !(a < b)   */
+              if (port->ge_nlt)
+                transformedOp = '<';
+              break;
+            case NE_OP:           /* transform (a != b) to !(a == b)   */
+              if (port->ne_neq)
+                transformedOp = EQ_OP;
+              break;
+            case EQ_OP:           /* transform (a == b) to !(a != b)   */
+              if (port->eq_nne)
+                transformedOp = NE_OP;
+              break;
+            default:
+              break;
+          }
+        if (transformedOp)
+          {
+            tree->opval.op = transformedOp;
+            tree->decorated = 0;
+            tree = newNode ('!', tree, NULL);
+            tree->lineno = tree->left->lineno;
+            return decorateType (tree, resultType);
+          }
+      }
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3941,6 +4286,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);
@@ -3950,6 +4296,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       tree->right = tree->left = NULL;
       TETYPE (tree) = getSpec (TTYPE (tree) =
                                tree->opval.val->type);
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -4038,29 +4385,63 @@ 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);
-          TTYPE (tree) = RTYPE (tree);
-          TETYPE (tree) = getSpec (TTYPE (tree));
-        }
-      return tree;
+
+      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)))
+        {
+          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 ':':
       /* if they don't match we have a problem */
       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;
         }
 
@@ -4081,18 +4462,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;
@@ -4108,18 +4489,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;
@@ -4134,14 +4515,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;
@@ -4152,11 +4533,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;
@@ -4172,19 +4553,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;
@@ -4195,11 +4576,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;
         }
 
@@ -4217,14 +4598,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));
         }
 
@@ -4232,7 +4613,7 @@ 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));
         }
 
@@ -4242,11 +4623,11 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       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;
         }
 
@@ -4265,7 +4646,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /*       function call        */
       /*----------------------------*/
     case CALL:
-      
+
       /* undo any explicit pointer derefernce; PCALL will handle it instead */
       if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
         {
@@ -4285,11 +4666,14 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (!tree->right ||
           !tree->right->decorated)
         {
-          sym_link *functype;      
+          sym_link *functype;
           parmNumber = 1;
 
           if (IS_FUNCPTR (LTYPE (tree)))
-            functype = LTYPE (tree)->next;
+            {
+              functype = LTYPE (tree)->next;
+              processFuncPtrArgs (functype);
+            }
           else
             functype = LTYPE (tree);
 
@@ -4298,8 +4682,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             {
               goto errorTreeReturn;
             }
-        
-          if ((options.stackAuto || IFFUNC_ISREENT (functype)) && 
+
+          if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
              !IFFUNC_ISBUILTIN(functype))
             {
               reverseParms (tree->right);
@@ -4350,7 +4734,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;
         }
 
@@ -4389,9 +4773,12 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /*----------------------------*/
     case FOR:
 
-      decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
-      decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
-      decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
+      AST_FOR (tree, initExpr) = decorateType (
+                  resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
+      AST_FOR (tree, condExpr) = decorateType (
+                  resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
+      AST_FOR (tree, loopExpr) = decorateType (
+                  resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
 
       /* if the for loop is reversible then
          reverse it otherwise do what we normally
@@ -4413,7 +4800,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;
@@ -4464,13 +4851,23 @@ sizeofOp (sym_link * type)
 /*-----------------------------------------------------------------*/
 /* backPatchLabels - change and or not operators to flow control    */
 /*-----------------------------------------------------------------*/
-ast *
+static ast *
 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
 {
 
   if (!tree)
     return NULL;
 
+  /* while-loops insert a label between the IFX and the condition,
+     therefore look behind the label too */
+  if (tree->opval.op == LABEL &&
+      tree->right &&
+      IS_ANDORNOT (tree->right))
+    {
+      tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
+      return tree;
+    }
+
   if (!(IS_ANDORNOT (tree)))
     return tree;
 
@@ -4529,25 +4926,18 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
   /* change not */
   if (IS_NOT (tree))
     {
-      int wasnot = IS_NOT (tree->left);
+      /* call with exchanged labels */
       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
 
-      /* if the left is already a IFX */
+      /* if left isn't already a IFX */
       if (!IS_IFX (tree->left))
-        tree->left = newNode (IFX, tree->left, NULL);
-
-      if (wasnot)
-        {
-          tree->left->trueLabel = trueLabel;
-          tree->left->falseLabel = falseLabel;
-        }
-      else
         {
+          tree->left = newNode (IFX, tree->left, NULL);
           tree->left->trueLabel = falseLabel;
           tree->left->falseLabel = trueLabel;
         }
       return tree->left;
-    }
+     }
 
   if (IS_IFX (tree))
     {
@@ -4573,7 +4963,7 @@ createBlock (symbol * decl, ast * body)
 
   ex = newNode (BLOCK, NULL, body);
   ex->values.sym = decl;
-  
+
   ex->level++;
   ex->lineno = 0;
   return ex;
@@ -4656,8 +5046,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;
@@ -4668,7 +5058,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");
@@ -4692,10 +5082,10 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
     }
 
   /* create the case label   */
-  SNPRINTF(caseLbl, sizeof(caseLbl), 
+  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->lineno = 0;
@@ -4821,11 +5211,13 @@ createDo (symbol * trueLabel, symbol * continueLabel,
   /* if the body does not exist then it is simple */
   if (!doBody)
     {
-      condAst = backPatchLabels (condAst, continueLabel, NULL);
+      condAst = backPatchLabels (condAst, continueLabel, falseLabel);
       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
       doTree->trueLabel = continueLabel;
       doTree->falseLabel = NULL;
+
+      doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
       return doTree;
     }
 
@@ -4997,7 +5389,7 @@ isBitAndPow2 (ast * tree)
   if (!IS_AST_LIT_VALUE (tree->right))
     return -1;
 
-  return powof2 ((TYPE_UDWORD)AST_LIT_VALUE (tree->right));
+  return powof2 (AST_ULONG_VALUE (tree->right));
 }
 
 /*-----------------------------------------------------------------*/
@@ -5006,21 +5398,21 @@ 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;
     }
   if (!expr && (resultType == RESULT_TYPE_BIT))
     {
       expr = tree->left;
-      if (isBitAndPow2 (tree) != getSize (TTYPE (expr)) * 8 - 1)
+      if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
         expr = NULL;
     }
   if (!expr)
@@ -5046,7 +5438,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;
     }
@@ -5084,9 +5476,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)
@@ -5094,14 +5486,14 @@ 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;
         }
     }
   if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
     return tree;
-      
+
   /* make sure the port supports GETBYTE */
   if (port->hasExtBitOp
       && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
@@ -5123,24 +5515,24 @@ 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)
     {
       /* 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;
         }
     }
   if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
     return tree;
-      
+
   /* make sure the port supports GETWORD */
   if (port->hasExtBitOp
       && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
@@ -5165,12 +5557,12 @@ optimizeRRCRLC (ast * root)
      into a RRC operation
      note : by 7 I mean (number of bits required to hold the
      variable -1 ) */
-  /* if the root operations is not a | operation the not */
+  /* if the root operation is not a | operation then not */
   if (!IS_BITOR (root))
     return root;
 
   /* I have to think of a better way to match patterns this sucks */
-  /* that aside let start looking for the first case : I use a the
+  /* that aside let's start looking for the first case : I use a
      negative check a lot to improve the efficiency */
   /* (?expr << 1) | (?expr >> 7) */
   if (IS_LEFT_OP (root->left) &&
@@ -5189,10 +5581,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;
 
@@ -5224,10 +5616,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;
 
@@ -5260,10 +5652,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;
 
@@ -5295,10 +5687,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;
 
@@ -5328,7 +5720,7 @@ optimizeSWAP (ast * root)
      into a SWAP : operation ..
      note : by 4 I mean (number of bits required to hold the
      variable /2 ) */
-  /* if the root operations is not a | operation the not */
+  /* if the root operation is not a | operation then not */
   if (!IS_BITOR (root))
     return root;
 
@@ -5349,11 +5741,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;
 
@@ -5422,8 +5814,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)) &&
@@ -5431,7 +5823,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;
@@ -5492,10 +5884,11 @@ optimizeCompare (ast * root)
 noOptimize:
   return root;
 }
+
 /*-----------------------------------------------------------------*/
 /* addSymToBlock : adds the symbol to the first block we find      */
 /*-----------------------------------------------------------------*/
-void 
+void
 addSymToBlock (symbol * sym, ast * tree)
 {
   /* reached end of tree or a leaf */
@@ -5521,7 +5914,7 @@ addSymToBlock (symbol * sym, ast * tree)
 /*-----------------------------------------------------------------*/
 /* processRegParms - do processing for register parameters         */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 processRegParms (value * args, ast * body)
 {
   while (args)
@@ -5546,6 +5939,430 @@ 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->lineno = src->lineno;
+  dest->filename = src->filename;
+  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)
+{
+  tree->block = currBlockno;
+
+  if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
+    {
+      symbol * decls;
+
+      currBlockno++;
+      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;
+
+  /* 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--;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* 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);
+}
+
+/*-----------------------------------------------------------------*/
+/* inlineFindMaxBlockno - find maximum block number in an ast tree */
+/*-----------------------------------------------------------------*/
+static int
+inlineFindMaxBlockno (ast * tree, int maxBlockno)
+{
+  int tempBlockno;
+
+  if (!tree)
+    return maxBlockno;
+
+  tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
+  if (tempBlockno > maxBlockno)
+    maxBlockno = tempBlockno;
+
+  tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
+  if (tempBlockno > maxBlockno)
+    maxBlockno = tempBlockno;
+
+  if (tree->block > maxBlockno)
+    maxBlockno = tree->block;
+  return maxBlockno;
+}
+
+
+
+
+/*-----------------------------------------------------------------*/
+/* 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;                                         */
+          /*   ...                                                     */
+          /*   typen tempargn;                                         */
+          /*   temparg1 = argument1;                                   */
+          /*   ...                                                     */
+          /*   tempargn = argumentn;                                   */
+          /*   { //inlinetree2 block                                   */
+          /*     type1 param1;                                         */
+          /*     ...                                                   */
+          /*     typen paramn;                                         */
+          /*     param1 = temparg1;                                    */
+          /*     ...                                                   */
+          /*     paramn = tempargn;                                    */
+          /*     inline_function_code;                                 */
+          /*     retlab:                                               */
+          /*   }                                                       */
+          /* }                                                         */
+          args = FUNC_ARGS (func->type);
+          argIndex = 0;
+          while (args)
+            {
+              symbol * temparg;
+              ast * passedarg;
+              ast * assigntree;
+              symbol * parm = copySymbol (args->sym);
+
+              temparg = inlineTempVar (args->sym->type, tree->level+1);
+              inlineAddDecl (temparg, inlinetree, FALSE);
+
+              passedarg = inlineFindParm (tree->right, argIndex);
+              assigntree = newNode ('=',
+                                    newAst_VALUE (symbolVal (temparg)),
+                                    passedarg);
+              inlinetree->right = newNode (NULLOP,
+                                           assigntree,
+                                           inlinetree->right);
+
+              inlineAddDecl (parm, inlinetree2, FALSE);
+              parm->_isparm = 0;
+
+              assigntree = newNode ('=',
+                                    newAst_VALUE (symbolVal (parm)),
+                                    newAst_VALUE (symbolVal (temparg)));
+              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  */
@@ -5560,6 +6377,7 @@ createFunction (symbol * name, ast * body)
   int stack = 0;
   sym_link *fetype;
   iCode *piCode = NULL;
+  int savedBlockno;
 
   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
@@ -5592,7 +6410,7 @@ createFunction (symbol * name, ast * body)
       addSymChain (&name);
       allocVariables (name);
     }
-  name->lastLine = mylineno;
+  name->lastLine = lexLineno;
   currFunc = name;
 
   /* set the stack pointer */
@@ -5615,6 +6433,15 @@ createFunction (symbol * name, ast * body)
   if (IFFUNC_ISREENT (name->type))
     reentrant++;
 
+  inlineState.count = 0;
+  savedBlockno = currBlockno;
+  currBlockno = inlineFindMaxBlockno (body, 0);
+  expandInlineFuncs (body, NULL);
+  currBlockno = savedBlockno;
+
+  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 */
@@ -5624,43 +6451,51 @@ createFunction (symbol * name, ast * body)
   stackPtr = 0;
   xstackPtr = -1;
 
+  gatherImplicitVariables (body, NULL);  /* move implicit variables into blocks */
+
   /* allocate & autoinit the block variables */
   processBlockVars (body, &stack, ALLOCATE);
 
-  /* save the stack information */
-  if (options.useXstack)
-    name->xstack = SPEC_STAK (fetype) = stack;
-  else
-    name->stack = SPEC_STAK (fetype) = stack;
-
   /* name needs to be mangled */
   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
 
   body = resolveSymbols (body); /* resolve the symbols */
   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
-                                        
+
+  /* save the stack information */
+  if (options.useXstack)
+    name->xstack = SPEC_STAK (fetype) = stack;
+  else
+    name->stack = SPEC_STAK (fetype) = stack;
 
   ex = newAst_VALUE (symbolVal (name)); /* create name */
   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;
-  codeOutFile = code->oFile;
+  codeOutBuf = &code->oBuf;
   piCode = iCodeFromAst (ex);
+  name->generated = 1;
 
   if (fatalError)
-    {
-      werror (E_FUNC_NO_CODE, name->name);
-      goto skipall;
-    }
+    goto skipall;
 
   eBBlockFromiCode (piCode);
 
@@ -5668,7 +6503,7 @@ createFunction (symbol * name, ast * body)
   if (staticAutos)
     {
       GcurMemmap = statsg;
-      codeOutFile = statsg->oFile;
+      codeOutBuf = &statsg->oBuf;
       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
       staticAutos = NULL;
     }
@@ -5705,7 +6540,7 @@ skipall:
 }
 
 
-#define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
+#define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
 /*-----------------------------------------------------------------*/
 /* ast_print : prints the ast (for debugging purposes)             */
 /*-----------------------------------------------------------------*/
@@ -5713,734 +6548,732 @@ skipall:
 void ast_print (ast * tree, FILE *outfile, int indent)
 {
 
-        if (!tree) return ;
-
-        /* can print only decorated trees */
-        if (!tree->decorated) return;
-
-        /* if any child is an error | this one is an error do nothing */
-        if (tree->isError ||
-            (tree->left && tree->left->isError) ||
-            (tree->right && tree->right->isError)) {
-                fprintf(outfile,"ERROR_NODE(%p)\n",tree);
-        }
-
-
-        /* print the line          */
-        /* if not block & function */
-        if (tree->type == EX_OP &&
-            (tree->opval.op != FUNCTION &&
-             tree->opval.op != BLOCK &&
-             tree->opval.op != NULLOP)) {
-        }
-
-        if (tree->opval.op == FUNCTION) {
-                int arg=0;
-                value *args=FUNC_ARGS(tree->left->opval.val->type);
-                fprintf(outfile,"FUNCTION (%s=%p) type (",
-                        tree->left->opval.val->name, tree);
-                printTypeChain (tree->left->opval.val->type->next,outfile);
-                fprintf(outfile,") args (");
-                do {
-                  if (arg) {
-                    fprintf (outfile, ", ");
-                  }
-                  printTypeChain (args ? args->type : NULL, outfile);
-                  arg++;
-                  args= args ? args->next : NULL;
-                } while (args);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent);
-                ast_print(tree->right,outfile,indent);
-                return ;
-        }
-        if (tree->opval.op == BLOCK) {
-                symbol *decls = tree->values.sym;
-                INDENT(indent,outfile);
-                fprintf(outfile,"{\n");
-                while (decls) {
-                        INDENT(indent+2,outfile);
-                        fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
-                                decls->name, decls);
-                        printTypeChain(decls->type,outfile);
-                        fprintf(outfile,")\n");
-
-                        decls = decls->next;
-                }
-                ast_print(tree->right,outfile,indent+2);
-                INDENT(indent,outfile);
-                fprintf(outfile,"}\n");
-                return;
-        }
-        if (tree->opval.op == NULLOP) {
-                ast_print(tree->left,outfile,indent);
-                ast_print(tree->right,outfile,indent);
-                return ;
-        }
-        INDENT(indent,outfile);
+  if (!tree) return ;
 
-        /*------------------------------------------------------------------*/
-        /*----------------------------*/
-        /*   leaf has been reached    */
-        /*----------------------------*/
-        /* if this is of type value */
-        /* just get the type        */
-        if (tree->type == EX_VALUE) {
-
-                if (IS_LITERAL (tree->opval.val->etype)) {
-                        fprintf(outfile,"CONSTANT (%p) value = ", tree);
-                        if (SPEC_USIGN (tree->opval.val->etype))
-                                fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
-                        else
-                                fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
-                        fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
-                                                      floatFromVal(tree->opval.val));
-                } else if (tree->opval.val->sym) {
-                        /* if the undefined flag is set then give error message */
-                        if (tree->opval.val->sym->undefined) {
-                                fprintf(outfile,"UNDEFINED SYMBOL ");
-                        } else {
-                                fprintf(outfile,"SYMBOL ");
-                        }
-                        fprintf(outfile,"(%s=%p)",
-                                tree->opval.val->sym->name,tree);
-                }
-                if (tree->ftype) {
-                        fprintf(outfile," type (");
-                        printTypeChain(tree->ftype,outfile);
-                        fprintf(outfile,")\n");
-                } else {
-                        fprintf(outfile,"\n");
-                }
-                return ;
-        }
-
-        /* if type link for the case of cast */
-        if (tree->type == EX_LINK) {
-                fprintf(outfile,"TYPENODE (%p) type = (",tree);
-                printTypeChain(tree->opval.lnk,outfile);
-                fprintf(outfile,")\n");
-                return ;
-        }
-
-
-        /* depending on type of operator do */
-
-        switch (tree->opval.op) {
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*        array node          */
-                /*----------------------------*/
-        case '[':
-                fprintf(outfile,"ARRAY_OP (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*      struct/union          */
-                /*----------------------------*/
-        case '.':
-                fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*    struct/union pointer    */
-                /*----------------------------*/
-        case PTR_OP:
-                fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*  ++/-- operation           */
-                /*----------------------------*/
-        case INC_OP:
-                if (tree->left)
-                  fprintf(outfile,"post-");
-                else
-                  fprintf(outfile,"pre-");
-                fprintf(outfile,"INC_OP (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2); /* postincrement case */
-                ast_print(tree->right,outfile,indent+2); /* preincrement case */
-                return ;
-
-        case DEC_OP:
-                if (tree->left)
-                  fprintf(outfile,"post-");
-                else
-                  fprintf(outfile,"pre-");
-                fprintf(outfile,"DEC_OP (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2); /* postdecrement case */
-                ast_print(tree->right,outfile,indent+2); /* predecrement case */
-                return ;
-
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*  bitwise and               */
-                /*----------------------------*/
-        case '&':
-                if (tree->right) {
-                        fprintf(outfile,"& (%p) type (",tree);
-                        printTypeChain(tree->ftype,outfile);
-                        fprintf(outfile,")\n");
-                        ast_print(tree->left,outfile,indent+2);
-                        ast_print(tree->right,outfile,indent+2);
-                } else {
-                        fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
-                        printTypeChain(tree->ftype,outfile);
-                        fprintf(outfile,")\n");
-                        ast_print(tree->left,outfile,indent+2);
-                        ast_print(tree->right,outfile,indent+2);
-                }
-                return ;
-                /*----------------------------*/
-                /*  bitwise or                */
-                /*----------------------------*/
-        case '|':
-                fprintf(outfile,"OR (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*  bitwise xor               */
-                /*----------------------------*/
-        case '^':
-                fprintf(outfile,"XOR (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*  division                  */
-                /*----------------------------*/
-        case '/':
-                fprintf(outfile,"DIV (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*            modulus         */
-                /*----------------------------*/
-        case '%':
-                fprintf(outfile,"MOD (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*  address dereference       */
-                /*----------------------------*/
-        case '*':                       /* can be unary  : if right is null then unary operation */
-                if (!tree->right) {
-                        fprintf(outfile,"DEREF (%p) type (",tree);
-                        printTypeChain(tree->ftype,outfile);
-                        fprintf(outfile,")\n");
-                        ast_print(tree->left,outfile,indent+2);
-                        return ;
-                }                       
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*      multiplication        */
-                /*----------------------------*/                
-                fprintf(outfile,"MULT (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-
-
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*    unary '+' operator      */
-                /*----------------------------*/
-        case '+':
-                /* if unary plus */
-                if (!tree->right) {
-                        fprintf(outfile,"UPLUS (%p) type (",tree);
-                        printTypeChain(tree->ftype,outfile);
-                        fprintf(outfile,")\n");
-                        ast_print(tree->left,outfile,indent+2);
-                } else {
-                        /*------------------------------------------------------------------*/
-                        /*----------------------------*/
-                        /*      addition              */
-                        /*----------------------------*/
-                        fprintf(outfile,"ADD (%p) type (",tree);
-                        printTypeChain(tree->ftype,outfile);
-                        fprintf(outfile,")\n");
-                        ast_print(tree->left,outfile,indent+2);
-                        ast_print(tree->right,outfile,indent+2);
-                }
-                return;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*      unary '-'             */
-                /*----------------------------*/
-        case '-':                       /* can be unary   */
-                if (!tree->right) {
-                        fprintf(outfile,"UMINUS (%p) type (",tree);
-                        printTypeChain(tree->ftype,outfile);
-                        fprintf(outfile,")\n");
-                        ast_print(tree->left,outfile,indent+2);
-                } else {
-                        /*------------------------------------------------------------------*/
-                        /*----------------------------*/
-                        /*      subtraction           */
-                        /*----------------------------*/
-                        fprintf(outfile,"SUB (%p) type (",tree);
-                        printTypeChain(tree->ftype,outfile);
-                        fprintf(outfile,")\n");
-                        ast_print(tree->left,outfile,indent+2);
-                        ast_print(tree->right,outfile,indent+2);
-                }
-                return;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*    complement              */
-                /*----------------------------*/
-        case '~':
-                fprintf(outfile,"COMPL (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                return ;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*           not              */
-                /*----------------------------*/
-        case '!':
-                fprintf(outfile,"NOT (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                return ;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*           shift            */
-                /*----------------------------*/
-        case RRC:
-                fprintf(outfile,"RRC (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                return ;
-
-        case RLC:
-                fprintf(outfile,"RLC (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                return ;
-        case SWAP:
-                fprintf(outfile,"SWAP (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                return ;
-        case GETHBIT:
-                fprintf(outfile,"GETHBIT (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                return ;
-        case GETABIT:
-                fprintf(outfile,"GETABIT (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case GETBYTE:
-                fprintf(outfile,"GETBYTE (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case GETWORD:
-                fprintf(outfile,"GETWORD (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case LEFT_OP:
-                fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case RIGHT_OP:
-                fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*         casting            */
-                /*----------------------------*/
-        case CAST:                      /* change the type   */
-                fprintf(outfile,"CAST (%p) from type (",tree);
-                printTypeChain(tree->right->ftype,outfile);
-                fprintf(outfile,") to type (");
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-                
-        case AND_OP:
-                fprintf(outfile,"ANDAND (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case OR_OP:
-                fprintf(outfile,"OROR (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-                
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*     comparison operators   */
-                /*----------------------------*/
-        case '>':
-                fprintf(outfile,"GT(>) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case '<':
-                fprintf(outfile,"LT(<) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case LE_OP:
-                fprintf(outfile,"LE(<=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case GE_OP:
-                fprintf(outfile,"GE(>=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case EQ_OP:
-                fprintf(outfile,"EQ(==) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-        case NE_OP:
-                fprintf(outfile,"NE(!=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*             sizeof         */
-                /*----------------------------*/
-        case SIZEOF:            /* evaluate wihout code generation */
-                fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
-                return ;
-
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /* conditional operator  '?'  */
-                /*----------------------------*/
-        case '?':
-                fprintf(outfile,"QUEST(?) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-
-        case ':':
-                fprintf(outfile,"COLON(:) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*    assignment operators    */
-                /*----------------------------*/
-        case MUL_ASSIGN:
-                fprintf(outfile,"MULASS(*=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-        case DIV_ASSIGN:
-                fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-        case AND_ASSIGN:
-                fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-        case OR_ASSIGN:
-                fprintf(outfile,"ORASS(|=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-        case XOR_ASSIGN:
-                fprintf(outfile,"XORASS(^=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-        case RIGHT_ASSIGN:
-                fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-        case LEFT_ASSIGN:
-                fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*    -= operator             */
-                /*----------------------------*/
-        case SUB_ASSIGN:
-                fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*          += operator       */
-                /*----------------------------*/
-        case ADD_ASSIGN:
-                fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*      straight assignemnt   */
-                /*----------------------------*/
-        case '=':
-                fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;     
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*      comma operator        */
-                /*----------------------------*/
-        case ',':
-                fprintf(outfile,"COMMA(,) (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*       function call        */
-                /*----------------------------*/
-        case CALL:
-        case PCALL:
-                fprintf(outfile,"CALL (%p) type (",tree);
-                printTypeChain(tree->ftype,outfile);
-                fprintf(outfile,")\n");
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent+2);
-                return;
-        case PARAM:
-                fprintf(outfile,"PARMS\n");
-                ast_print(tree->left,outfile,indent+2);
-                if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
-                        ast_print(tree->right,outfile,indent+2);
-                }
-                return ;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*     return statement       */
-                /*----------------------------*/
-        case RETURN:
-                fprintf(outfile,"RETURN (%p) type (",tree);
-                if (tree->right) {
-                    printTypeChain(tree->right->ftype,outfile);
-                }
-                fprintf(outfile,")\n");
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*     label statement        */
-                /*----------------------------*/
-        case LABEL :
-                fprintf(outfile,"LABEL (%p)\n",tree);
-                ast_print(tree->left,outfile,indent+2);
-                ast_print(tree->right,outfile,indent);
-                return;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /*     switch statement       */
-                /*----------------------------*/
-        case SWITCH:
-                {
-                        value *val;
-                        fprintf(outfile,"SWITCH (%p) ",tree);
-                        ast_print(tree->left,outfile,0);
-                        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),
-                                        tree->values.switchVals.swNum,
-                                        (int) floatFromVal(val));
-                        }
-                        ast_print(tree->right,outfile,indent);
-                }
-                return ;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /* ifx Statement              */
-                /*----------------------------*/
-        case IFX:
-                fprintf(outfile,"IF (%p) \n",tree);
-                ast_print(tree->left,outfile,indent+2);
-                if (tree->trueLabel) {
-                        INDENT(indent+2,outfile);
-                        fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
-                }
-                if (tree->falseLabel) {
-                        INDENT(indent+2,outfile);
-                        fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
-                }
-                ast_print(tree->right,outfile,indent+2);
-                return ;
-                /*----------------------------*/
-                /* goto Statement              */
-                /*----------------------------*/
-        case GOTO:
-                fprintf(outfile,"GOTO (%p) \n",tree);
-                ast_print(tree->left,outfile,indent+2);
-                fprintf(outfile,"\n");
-                return ;
-                /*------------------------------------------------------------------*/
-                /*----------------------------*/
-                /* for Statement              */
-                /*----------------------------*/
-        case FOR:
-                fprintf(outfile,"FOR (%p) \n",tree);
-                if (AST_FOR( tree, initExpr)) {
-                        INDENT(indent+2,outfile);
-                        fprintf(outfile,"INIT EXPR ");
-                        ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
-                }
-                if (AST_FOR( tree, condExpr)) {
-                        INDENT(indent+2,outfile);
-                        fprintf(outfile,"COND EXPR ");
-                        ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
-                }
-                if (AST_FOR( tree, loopExpr)) {
-                        INDENT(indent+2,outfile);
-                        fprintf(outfile,"LOOP EXPR ");
-                        ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
-                }
-                fprintf(outfile,"FOR LOOP BODY \n");
-                ast_print(tree->left,outfile,indent+2);
-                return ;
-        case CRITICAL:
-                fprintf(outfile,"CRITICAL (%p) \n",tree);
-                ast_print(tree->left,outfile,indent+2);
-        default:
-            return ;
-        }
+  /* can print only decorated trees */
+  if (!tree->decorated) return;
+
+  /* if any child is an error | this one is an error do nothing */
+  if (tree->isError ||
+    (tree->left && tree->left->isError) ||
+    (tree->right && tree->right->isError)) {
+    fprintf(outfile,"ERROR_NODE(%p)\n",tree);
+  }
+
+
+  /* print the line          */
+  /* if not block & function */
+  if (tree->type == EX_OP &&
+    (tree->opval.op != FUNCTION &&
+    tree->opval.op != BLOCK &&
+    tree->opval.op != NULLOP)) {
+  }
+
+  if (tree->opval.op == FUNCTION) {
+    int arg=0;
+    value *args=FUNC_ARGS(tree->left->opval.val->type);
+    fprintf(outfile,"FUNCTION (%s=%p) type (",
+      tree->left->opval.val->name, tree);
+    printTypeChain (tree->left->opval.val->type->next,outfile);
+    fprintf(outfile,") args (");
+    do {
+      if (arg) {
+        fprintf (outfile, ", ");
+      }
+      printTypeChain (args ? args->type : NULL, outfile);
+      arg++;
+      args= args ? args->next : NULL;
+    } while (args);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent);
+    ast_print(tree->right,outfile,indent);
+    return ;
+  }
+  if (tree->opval.op == BLOCK) {
+    symbol *decls = tree->values.sym;
+    INDENT(indent,outfile);
+    fprintf(outfile,"{\n");
+    while (decls) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
+        decls->name, decls);
+      printTypeChain(decls->type,outfile);
+      fprintf(outfile,")\n");
+
+      decls = decls->next;
+    }
+    ast_print(tree->right,outfile,indent+2);
+    INDENT(indent,outfile);
+    fprintf(outfile,"}\n");
+    return;
+  }
+  if (tree->opval.op == NULLOP) {
+    ast_print(tree->left,outfile,indent);
+    ast_print(tree->right,outfile,indent);
+    return ;
+  }
+  INDENT(indent,outfile);
+
+  /*------------------------------------------------------------------*/
+  /*----------------------------*/
+  /*   leaf has been reached    */
+  /*----------------------------*/
+  /* if this is of type value */
+  /* just get the type        */
+  if (tree->type == EX_VALUE) {
+
+    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) ulFromVal(tree->opval.val));
+      else
+        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 */
+      if (tree->opval.val->sym->undefined) {
+        fprintf(outfile,"UNDEFINED SYMBOL ");
+      } else {
+        fprintf(outfile,"SYMBOL ");
+      }
+      fprintf(outfile,"(%s=%p @ %p)",
+        tree->opval.val->sym->name, tree, tree->opval.val->sym);
+    }
+    if (tree->ftype) {
+      fprintf(outfile," type (");
+      printTypeChain(tree->ftype,outfile);
+      fprintf(outfile,")\n");
+    } else {
+      fprintf(outfile,"\n");
+    }
+    return ;
+  }
+
+  /* if type link for the case of cast */
+  if (tree->type == EX_LINK) {
+    fprintf(outfile,"TYPENODE (%p) type = (",tree);
+    printTypeChain(tree->opval.lnk,outfile);
+    fprintf(outfile,")\n");
+    return ;
+  }
+
+
+  /* depending on type of operator do */
+
+  switch (tree->opval.op) {
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*        array node          */
+    /*----------------------------*/
+  case '[':
+    fprintf(outfile,"ARRAY_OP (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*      struct/union          */
+    /*----------------------------*/
+  case '.':
+    fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*    struct/union pointer    */
+    /*----------------------------*/
+  case PTR_OP:
+    fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*  ++/-- operation           */
+    /*----------------------------*/
+  case INC_OP:
+    if (tree->left)
+      fprintf(outfile,"post-");
+    else
+      fprintf(outfile,"pre-");
+    fprintf(outfile,"INC_OP (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2); /* postincrement case */
+    ast_print(tree->right,outfile,indent+2); /* preincrement case */
+    return ;
+
+  case DEC_OP:
+    if (tree->left)
+      fprintf(outfile,"post-");
+    else
+      fprintf(outfile,"pre-");
+    fprintf(outfile,"DEC_OP (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2); /* postdecrement case */
+    ast_print(tree->right,outfile,indent+2); /* predecrement case */
+    return ;
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*  bitwise and               */
+    /*----------------------------*/
+  case '&':
+    if (tree->right) {
+      fprintf(outfile,"& (%p) type (",tree);
+      printTypeChain(tree->ftype,outfile);
+      fprintf(outfile,")\n");
+      ast_print(tree->left,outfile,indent+2);
+      ast_print(tree->right,outfile,indent+2);
+    } else {
+      fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
+      printTypeChain(tree->ftype,outfile);
+      fprintf(outfile,")\n");
+      ast_print(tree->left,outfile,indent+2);
+      ast_print(tree->right,outfile,indent+2);
+    }
+    return ;
+    /*----------------------------*/
+    /*  bitwise or                */
+    /*----------------------------*/
+  case '|':
+    fprintf(outfile,"OR (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*  bitwise xor               */
+    /*----------------------------*/
+  case '^':
+    fprintf(outfile,"XOR (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*  division                  */
+    /*----------------------------*/
+  case '/':
+    fprintf(outfile,"DIV (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*            modulus         */
+    /*----------------------------*/
+  case '%':
+    fprintf(outfile,"MOD (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*  address dereference       */
+    /*----------------------------*/
+  case '*':                       /* can be unary  : if right is null then unary operation */
+    if (!tree->right) {
+      fprintf(outfile,"DEREF (%p) type (",tree);
+      printTypeChain(tree->ftype,outfile);
+      fprintf(outfile,")\n");
+      ast_print(tree->left,outfile,indent+2);
+      return ;
+    }
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*      multiplication        */
+    /*----------------------------*/
+    fprintf(outfile,"MULT (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*    unary '+' operator      */
+    /*----------------------------*/
+  case '+':
+    /* if unary plus */
+    if (!tree->right) {
+      fprintf(outfile,"UPLUS (%p) type (",tree);
+      printTypeChain(tree->ftype,outfile);
+      fprintf(outfile,")\n");
+      ast_print(tree->left,outfile,indent+2);
+    } else {
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*      addition              */
+      /*----------------------------*/
+      fprintf(outfile,"ADD (%p) type (",tree);
+      printTypeChain(tree->ftype,outfile);
+      fprintf(outfile,")\n");
+      ast_print(tree->left,outfile,indent+2);
+      ast_print(tree->right,outfile,indent+2);
+    }
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*      unary '-'             */
+    /*----------------------------*/
+  case '-':                       /* can be unary   */
+    if (!tree->right) {
+      fprintf(outfile,"UMINUS (%p) type (",tree);
+      printTypeChain(tree->ftype,outfile);
+      fprintf(outfile,")\n");
+      ast_print(tree->left,outfile,indent+2);
+    } else {
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*      subtraction           */
+      /*----------------------------*/
+      fprintf(outfile,"SUB (%p) type (",tree);
+      printTypeChain(tree->ftype,outfile);
+      fprintf(outfile,")\n");
+      ast_print(tree->left,outfile,indent+2);
+      ast_print(tree->right,outfile,indent+2);
+    }
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*    complement              */
+    /*----------------------------*/
+  case '~':
+    fprintf(outfile,"COMPL (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*           not              */
+    /*----------------------------*/
+  case '!':
+    fprintf(outfile,"NOT (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*           shift            */
+    /*----------------------------*/
+  case RRC:
+    fprintf(outfile,"RRC (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    return ;
+
+  case RLC:
+    fprintf(outfile,"RLC (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    return ;
+  case SWAP:
+    fprintf(outfile,"SWAP (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    return ;
+  case GETHBIT:
+    fprintf(outfile,"GETHBIT (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    return ;
+  case GETABIT:
+    fprintf(outfile,"GETABIT (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case GETBYTE:
+    fprintf(outfile,"GETBYTE (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case GETWORD:
+    fprintf(outfile,"GETWORD (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case LEFT_OP:
+    fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case RIGHT_OP:
+    fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*         casting            */
+    /*----------------------------*/
+  case CAST:                      /* change the type   */
+    fprintf(outfile,"CAST (%p) from type (",tree);
+    printTypeChain(tree->right->ftype,outfile);
+    fprintf(outfile,") to type (");
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+
+  case AND_OP:
+    fprintf(outfile,"ANDAND (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case OR_OP:
+    fprintf(outfile,"OROR (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*     comparison operators   */
+    /*----------------------------*/
+  case '>':
+    fprintf(outfile,"GT(>) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case '<':
+    fprintf(outfile,"LT(<) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case LE_OP:
+    fprintf(outfile,"LE(<=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case GE_OP:
+    fprintf(outfile,"GE(>=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case EQ_OP:
+    fprintf(outfile,"EQ(==) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+  case NE_OP:
+    fprintf(outfile,"NE(!=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*             sizeof         */
+    /*----------------------------*/
+  case SIZEOF:            /* evaluate wihout code generation */
+    fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
+    return ;
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /* conditional operator  '?'  */
+    /*----------------------------*/
+  case '?':
+    fprintf(outfile,"QUEST(?) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+
+  case ':':
+    fprintf(outfile,"COLON(:) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*    assignment operators    */
+    /*----------------------------*/
+  case MUL_ASSIGN:
+    fprintf(outfile,"MULASS(*=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case DIV_ASSIGN:
+    fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case AND_ASSIGN:
+    fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case OR_ASSIGN:
+    fprintf(outfile,"ORASS(|=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case XOR_ASSIGN:
+    fprintf(outfile,"XORASS(^=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case RIGHT_ASSIGN:
+    fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case LEFT_ASSIGN:
+    fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*    -= operator             */
+    /*----------------------------*/
+  case SUB_ASSIGN:
+    fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*          += operator       */
+    /*----------------------------*/
+  case ADD_ASSIGN:
+    fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*      straight assignemnt   */
+    /*----------------------------*/
+  case '=':
+    fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*      comma operator        */
+    /*----------------------------*/
+  case ',':
+    fprintf(outfile,"COMMA(,) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*       function call        */
+    /*----------------------------*/
+  case CALL:
+  case PCALL:
+    fprintf(outfile,"CALL (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case PARAM:
+    fprintf(outfile,"PARMS\n");
+    ast_print(tree->left,outfile,indent+2);
+    if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
+      ast_print(tree->right,outfile,indent+2);
+    }
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*     return statement       */
+    /*----------------------------*/
+  case RETURN:
+    fprintf(outfile,"RETURN (%p) type (",tree);
+    if (tree->right) {
+      printTypeChain(tree->right->ftype,outfile);
+    }
+    fprintf(outfile,")\n");
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*     label statement        */
+    /*----------------------------*/
+  case LABEL :
+    fprintf(outfile,"LABEL (%p)\n",tree);
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*     switch statement       */
+    /*----------------------------*/
+  case SWITCH:
+    {
+      value *val;
+      fprintf(outfile,"SWITCH (%p) ",tree);
+      ast_print(tree->left,outfile,0);
+      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) ulFromVal(val),
+          tree->values.switchVals.swNum,
+          (int) ulFromVal(val));
+      }
+      ast_print(tree->right,outfile,indent);
+    }
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /* ifx Statement              */
+    /*----------------------------*/
+  case IFX:
+    fprintf(outfile,"IF (%p) \n",tree);
+    ast_print(tree->left,outfile,indent+2);
+    if (tree->trueLabel) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
+    }
+    if (tree->falseLabel) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
+    }
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+    /*----------------------------*/
+    /* goto Statement              */
+    /*----------------------------*/
+  case GOTO:
+    fprintf(outfile,"GOTO (%p) \n",tree);
+    ast_print(tree->left,outfile,indent+2);
+    fprintf(outfile,"\n");
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /* for Statement              */
+    /*----------------------------*/
+  case FOR:
+    fprintf(outfile,"FOR (%p) \n",tree);
+    if (AST_FOR( tree, initExpr)) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"INIT EXPR ");
+      ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
+    }
+    if (AST_FOR( tree, condExpr)) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"COND EXPR ");
+      ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
+    }
+    if (AST_FOR( tree, loopExpr)) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"LOOP EXPR ");
+      ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
+    }
+    fprintf(outfile,"FOR LOOP BODY \n");
+    ast_print(tree->left,outfile,indent+2);
+    return ;
+  case CRITICAL:
+    fprintf(outfile,"CRITICAL (%p) \n",tree);
+    ast_print(tree->left,outfile,indent+2);
+  default:
+    return ;
+  }
 }
 
 void PA(ast *t)
 {
-        ast_print(t,stdout,0);
+  ast_print(t,stdout,0);
 }
 
-
-
 /*-----------------------------------------------------------------*/
 /* astErrors : returns non-zero if errors present in tree          */
 /*-----------------------------------------------------------------*/
 int astErrors(ast *t)
 {
   int errors=0;
-  
+
   if (t)
     {
       if (t->isError)
         errors++;
-  
+
       if (t->type == EX_VALUE
           && t->opval.val->sym
           && t->opval.val->sym->undefined)
@@ -6449,6 +7282,6 @@ int astErrors(ast *t)
       errors += astErrors(t->left);
       errors += astErrors(t->right);
     }
-    
+
   return errors;
 }