* as/hc08/lkaomf51.c (OutputName),
[fw/sdcc] / src / SDCCast.c
index e21105ca710c613f11c4dcd0f8b50945e006bf64..f57bc1489db9bd8de82c98f483d28b920f2a1b94 100644 (file)
@@ -22,6 +22,8 @@
    what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
+#define DEBUG_CF(x) /* puts(x); */
+
 #include "common.h"
 
 int currLineno = 0;
@@ -48,18 +50,21 @@ 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 *);
-ast *optimizeGetHbit (ast *);
-ast *backPatchLabels (ast *, symbol *, symbol *);
+ast *optimizeGetHbit (ast *, RESULT_TYPE);
+ast *optimizeGetAbit (ast *, RESULT_TYPE);
+ast *optimizeGetByte (ast *, RESULT_TYPE);
+ast *optimizeGetWord (ast *, RESULT_TYPE);
+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 
+int
 ptt (ast * tree)
 {
   printTypeChain (tree->ftype, stdout);
@@ -84,6 +89,7 @@ newAst_ (unsigned type)
   ex->level = NestLevel;
   ex->block = currBlockno;
   ex->initMode = inInitMode;
+  ex->seqPoint = seqPointNo;
   return ex;
 }
 
@@ -139,13 +145,13 @@ newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
     {
       /* then depending on the expression value */
       if (floatFromVal (condAst->opval.val))
-       ifxNode = newNode (GOTO,
-                          newAst_VALUE (symbolVal (trueLabel)),
-                          NULL);
+        ifxNode = newNode (GOTO,
+                           newAst_VALUE (symbolVal (trueLabel)),
+                           NULL);
       else
-       ifxNode = newNode (GOTO,
-                          newAst_VALUE (symbolVal (falseLabel)),
-                          NULL);
+        ifxNode = newNode (GOTO,
+                           newAst_VALUE (symbolVal (falseLabel)),
+                           NULL);
     }
   else
     {
@@ -171,11 +177,11 @@ copyAstValues (ast * dest, ast * src)
 
     case SWITCH:
       dest->values.switchVals.swVals =
-       copyValue (src->values.switchVals.swVals);
+        copyValue (src->values.switchVals.swVals);
       dest->values.switchVals.swDefault =
-       src->values.switchVals.swDefault;
+        src->values.switchVals.swDefault;
       dest->values.switchVals.swNum =
-       src->values.switchVals.swNum;
+        src->values.switchVals.swNum;
       break;
 
     case INLINEASM:
@@ -183,8 +189,8 @@ copyAstValues (ast * dest, ast * src)
       break;
 
     case ARRAYINIT:
-       dest->values.constlist = copyLiteralList(src->values.constlist);
-       break;
+        dest->values.constlist = copyLiteralList(src->values.constlist);
+        break;
 
     case FOR:
       AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
@@ -215,6 +221,7 @@ copyAst (ast * src)
   dest->lineno = src->lineno;
   dest->level = src->level;
   dest->funcName = src->funcName;
+  dest->reversed = src->reversed;
 
   if (src->ftype)
     dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
@@ -247,7 +254,7 @@ exit:
   return dest;
 
 }
-
+#if 0
 /*-----------------------------------------------------------------*/
 /* removeIncDecOps: remove for side effects in *_ASSIGN's          */
 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
@@ -318,9 +325,91 @@ 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 {
+      /* 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)
@@ -337,13 +426,13 @@ hasSEFcalls (ast * tree)
     return TRUE;
 
   return (hasSEFcalls (tree->left) |
-         hasSEFcalls (tree->right));
+          hasSEFcalls (tree->right));
 }
 
 /*-----------------------------------------------------------------*/
 /* isAstEqual - compares two asts & returns 1 if they are equal    */
 /*-----------------------------------------------------------------*/
-int 
+static int
 isAstEqual (ast * t1, ast * t2)
 {
   if (!t1 && !t2)
@@ -360,28 +449,28 @@ isAstEqual (ast * t1, ast * t2)
     {
     case EX_OP:
       if (t1->opval.op != t2->opval.op)
-       return 0;
+        return 0;
       return (isAstEqual (t1->left, t2->left) &&
-             isAstEqual (t1->right, t2->right));
+              isAstEqual (t1->right, t2->right));
       break;
 
     case EX_VALUE:
       if (t1->opval.val->sym)
-       {
-         if (!t2->opval.val->sym)
-           return 0;
-         else
-           return isSymbolEqual (t1->opval.val->sym,
-                                 t2->opval.val->sym);
-       }
+        {
+          if (!t2->opval.val->sym)
+            return 0;
+          else
+            return isSymbolEqual (t1->opval.val->sym,
+                                  t2->opval.val->sym);
+        }
       else
-       {
-         if (t2->opval.val->sym)
-           return 0;
-         else
-           return (floatFromVal (t1->opval.val) ==
-                   floatFromVal (t2->opval.val));
-       }
+        {
+          if (t2->opval.val->sym)
+            return 0;
+          else
+            return (floatFromVal (t1->opval.val) ==
+                    floatFromVal (t2->opval.val));
+        }
       break;
 
       /* only compare these two types */
@@ -424,23 +513,25 @@ resolveSymbols (ast * tree)
       symbol *csym;
 
       if (tree->trueLabel)
-       {
-         if ((csym = findSym (LabelTab, tree->trueLabel,
-                              tree->trueLabel->name)))
-           tree->trueLabel = csym;
-         else
-           werror (E_LABEL_UNDEF, tree->trueLabel->name);
-       }
+        {
+          if ((csym = findSym (LabelTab, tree->trueLabel,
+                               tree->trueLabel->name)))
+            tree->trueLabel = csym;
+          else
+            werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+                      tree->trueLabel->name);
+        }
 
       if (tree->falseLabel)
-       {
-         if ((csym = findSym (LabelTab,
-                              tree->falseLabel,
-                              tree->falseLabel->name)))
-           tree->falseLabel = csym;
-         else
-           werror (E_LABEL_UNDEF, tree->falseLabel->name);
-       }
+        {
+          if ((csym = findSym (LabelTab,
+                               tree->falseLabel,
+                               tree->falseLabel->name)))
+            tree->falseLabel = csym;
+          else
+            werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+                      tree->falseLabel->name);
+        }
 
     }
 
@@ -451,12 +542,13 @@ resolveSymbols (ast * tree)
     {
 
       symbol *csym = findSym (LabelTab, tree->opval.val->sym,
-                             tree->opval.val->sym->name);
+                              tree->opval.val->sym->name);
 
       if (!csym)
-       werror (E_LABEL_UNDEF, tree->opval.val->sym->name);
+        werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+                  tree->opval.val->sym->name);
       else
-       tree->opval.val->sym = csym;
+        tree->opval.val->sym = csym;
 
       goto resolveChildren;
     }
@@ -471,40 +563,42 @@ resolveSymbols (ast * tree)
 
       /* if found in the symbol table & they r not the same */
       if (csym && tree->opval.val->sym != csym)
-       {
-         tree->opval.val->sym = csym;
-         tree->opval.val->type = csym->type;
-         tree->opval.val->etype = csym->etype;
-       }
+        {
+          tree->opval.val->sym = csym;
+          tree->opval.val->type = csym->type;
+          tree->opval.val->etype = csym->etype;
+        }
 
       /* if not found in the symbol table */
       /* mark it as undefined assume it is */
       /* an integer in data space         */
       if (!csym && !tree->opval.val->sym->implicit)
-       {
-
-         /* if this is a function name then */
-         /* mark it as returning an int     */
-         if (tree->funcName)
-           {
-             tree->opval.val->sym->type = newLink (DECLARATOR);
-             DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
-             tree->opval.val->sym->type->next =
-               tree->opval.val->sym->etype = newIntLink ();
-             tree->opval.val->etype = tree->opval.val->etype;
-             tree->opval.val->type = tree->opval.val->sym->type;
-             werror (W_IMPLICIT_FUNC, tree->opval.val->sym->name);
-             allocVariables (tree->opval.val->sym);
-           }
-         else
-           {
-             tree->opval.val->sym->undefined = 1;
-             tree->opval.val->type =
-               tree->opval.val->etype = newIntLink ();
-             tree->opval.val->sym->type =
-               tree->opval.val->sym->etype = newIntLink ();
-           }
-       }
+        {
+
+          /* if this is a function name then */
+          /* mark it as returning an int     */
+          if (tree->funcName)
+            {
+              tree->opval.val->sym->type = newLink (DECLARATOR);
+              DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
+              tree->opval.val->sym->type->next =
+                tree->opval.val->sym->etype = newIntLink ();
+              tree->opval.val->etype = tree->opval.val->etype;
+              tree->opval.val->type = tree->opval.val->sym->type;
+              werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
+                        tree->opval.val->sym->name);
+              //tree->opval.val->sym->undefined = 1;
+              allocVariables (tree->opval.val->sym);
+            }
+          else
+            {
+              tree->opval.val->sym->undefined = 1;
+              tree->opval.val->type =
+                tree->opval.val->etype = newIntLink ();
+              tree->opval.val->sym->type =
+                tree->opval.val->sym->etype = newIntLink ();
+            }
+        }
     }
 
 resolveChildren:
@@ -533,7 +627,7 @@ int setAstLineno (ast * tree, int lineno)
 /*-----------------------------------------------------------------*/
 symbol *
 funcOfType (char *name, sym_link * type, sym_link * argType,
-           int nArgs, int rent)
+            int nArgs, int rent)
 {
   symbol *sym;
   /* create the symbol */
@@ -553,18 +647,18 @@ funcOfType (char *name, sym_link * type, sym_link * argType,
       args = FUNC_ARGS(sym->type) = newValue ();
 
       while (nArgs--)
-       {
-         args->type = copyLinkChain (argType);
-         args->etype = getSpec (args->type);
-         SPEC_EXTR(args->etype)=1;
-         if (!nArgs)
-           break;
-         args = args->next = newValue ();
-       }
+        {
+          args->type = copyLinkChain (argType);
+          args->etype = getSpec (args->type);
+          SPEC_EXTR(args->etype)=1;
+          if (!nArgs)
+            break;
+          args = args->next = newValue ();
+        }
     }
 
   /* save it */
-  addSymChain (sym);
+  addSymChain (&sym);
   sym->cdef = 1;
   allocVariables (sym);
   return sym;
@@ -577,34 +671,34 @@ 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);
-           SPEC_EXTR(args->etype)=1;
-           if ((i + 1) == nArgs) break;
-           args = args->next = newValue ();
-       }
+        value *args;
+        args = FUNC_ARGS(sym->type) = newValue ();
+
+        for ( i = 0 ; i < nArgs ; i++ ) {
+            args->type = typeFromStr(atypes[i]);
+            args->etype = getSpec (args->type);
+            SPEC_EXTR(args->etype)=1;
+            if ((i + 1) == nArgs) break;
+            args = args->next = newValue ();
+        }
     }
 
     /* save it */
-    addSymChain (sym);
+    addSymChain (&sym);
     sym->cdef = 1;
     allocVariables (sym);
     return sym;
@@ -622,11 +716,25 @@ reverseParms (ast * ptree)
     return;
 
   /* top down if we find a nonParm tree then quit */
-  if (ptree->type == EX_OP && ptree->opval.op == PARAM)
+  if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
     {
+      /* The various functions expect the parameter tree to be right heavy. */
+      /* Rotate the tree to be left heavy so that after reversal it is */
+      /* right heavy again. */
+      while ((ttree = ptree->right) && ttree->type == EX_OP &&
+             ttree->opval.op == PARAM)
+        {
+          ptree->right = ttree->right;
+          ttree->right = ttree->left;
+          ttree->left = ptree->left;
+          ptree->left = ttree;
+        }
+
+      /* Now reverse */
       ttree = ptree->left;
       ptree->left = ptree->right;
       ptree->right = ttree;
+      ptree->reversed = 1;
       reverseParms (ptree->left);
       reverseParms (ptree->right);
     }
@@ -638,177 +746,186 @@ reverseParms (ast * ptree)
 /* processParms  - makes sure the parameters are okay and do some  */
 /*                 processing with them                            */
 /*-----------------------------------------------------------------*/
-int 
-processParms (ast * func,
-             value *defParm,
-             ast * actParm,
-             int *parmNumber, // unused, although updated
-             bool rightmost)
+static int
+processParms (ast *func,
+              value *defParm,
+              ast **actParm,
+              int *parmNumber, /* unused, although updated */
+              bool rightmost)
 {
+  RESULT_TYPE resultType;
+  sym_link *functype;
+
   /* if none of them exist */
-  if (!defParm && !actParm)
+  if (!defParm && !*actParm)
     return 0;
 
-  if (defParm) {
-    if (getenv("DEBUG_SANITY")) {
-      fprintf (stderr, "processParms: %s ", defParm->name);
+  if (defParm)
+    {
+      if (getenv("DEBUG_SANITY"))
+        {
+          fprintf (stderr, "processParms: %s ", defParm->name);
+        }
+      /* make sure the type is complete and sane */
+      checkTypeSanity(defParm->etype, defParm->name);
     }
-    /* make sure the type is complete and sane */
-    checkTypeSanity(defParm->etype, defParm->name);
-  }
+
+  if (IS_CODEPTR (func->ftype))
+    functype = func->ftype->next;
+  else
+    functype = func->ftype;
 
   /* if the function is being called via a pointer &   */
   /* it has not been defined a reentrant then we cannot */
   /* have parameters                                   */
-  if (func->type != EX_VALUE && !IFFUNC_ISREENT (func->ftype) && !options.stackAuto)
+  /* PIC16 port can... */
+  if (!TARGET_IS_PIC16)
     {
-      werror (W_NONRENT_ARGS);
-      return 1;
+      if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
+        {
+          werror (W_NONRENT_ARGS);
+          fatalError++;
+          return 1;
+        }
     }
 
   /* if defined parameters ended but actual parameters */
   /* exist and this is not defined as a variable arg   */
-  if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype))
+  if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
     {
       werror (E_TOO_MANY_PARMS);
       return 1;
     }
 
   /* if defined parameters present but no actual parameters */
-  if (defParm && !actParm)
+  if (defParm && !*actParm)
     {
       werror (E_TOO_FEW_PARMS);
       return 1;
     }
 
-  if (IS_VOID(actParm->ftype)) {
-    werror (E_VOID_VALUE_USED);
-    return 1;
-  }
+  /* if this is a PARAM node then match left & right */
+  if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
+    {
+      (*actParm)->decorated = 1;
+      return (processParms (func, defParm,
+                            &(*actParm)->left,  parmNumber, FALSE) ||
+              processParms (func, defParm ? defParm->next : NULL,
+                            &(*actParm)->right, parmNumber, rightmost));
+    }
+  else if (defParm) /* not vararg */
+    {
+      /* If we have found a value node by following only right-hand links,
+       * then we know that there are no more values after us.
+       *
+       * Therefore, if there are more defined parameters, the caller didn't
+       * supply enough.
+       */
+      if (rightmost && defParm->next)
+        {
+          werror (E_TOO_FEW_PARMS);
+          return 1;
+        }
+    }
+
+  /* decorate parameter */
+  resultType = defParm ? getResultTypeFromType (defParm->type) :
+                         RESULT_TYPE_NONE;
+  *actParm = decorateType (*actParm, resultType);
+
+  if (IS_VOID((*actParm)->ftype))
+    {
+      werror (E_VOID_VALUE_USED);
+      return 1;
+    }
 
   /* If this is a varargs function... */
-  if (!defParm && actParm && IFFUNC_HASVARARGS(func->ftype))
+  if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
     {
       ast *newType = NULL;
       sym_link *ftype;
 
-      if (IS_CAST_OP (actParm)
-         || (IS_AST_LIT_VALUE (actParm) && actParm->values.literalFromCast))
-       {
-         /* Parameter was explicitly typecast; don't touch it. */
-         return 0;
-       }
+      if (IS_CAST_OP (*actParm)
+          || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
+        {
+          /* Parameter was explicitly typecast; don't touch it. */
+          return 0;
+        }
 
-      ftype = actParm->ftype;
-          
-      /* If it's a small integer, upcast to int. */
+      ftype = (*actParm)->ftype;
+
+      /* If it's a char, upcast to int. */
       if (IS_INTEGRAL (ftype)
-         && (getSize (ftype) < (unsigned) INTSIZE))
-       {
-         if (IS_AST_OP(actParm) &&
-             (actParm->opval.op == LEFT_OP ||
-              actParm->opval.op == '*' ||
-              actParm->opval.op == '+' ||
-              actParm->opval.op == '-') &&
-             actParm->right) {
-           // we should cast an operand instead of the result
-           actParm->decorated = 0;
-           actParm->left = newNode( CAST, newAst_LINK(newIntLink()),
-                                        actParm->left);
-           actParm = decorateType(actParm);
-         } else {
-           newType = newAst_LINK(INTTYPE);
-         }
-       }
+          && (getSize (ftype) < (unsigned) INTSIZE))
+        {
+          newType = newAst_LINK(INTTYPE);
+        }
 
       if (IS_PTR(ftype) && !IS_GENPTR(ftype))
-       {
-         newType = newAst_LINK (copyLinkChain(ftype));
-         DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
-       }
+        {
+          newType = newAst_LINK (copyLinkChain(ftype));
+          DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
+        }
 
       if (IS_AGGREGATE (ftype))
-       {
-         newType = newAst_LINK (copyLinkChain (ftype));
-         DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
-       }
+        {
+          newType = newAst_LINK (copyLinkChain (ftype));
+          DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
+        }
+
       if (newType)
-       {
-         /* cast required; change this op to a cast. */
-         ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm)));
-
-         actParm->type = EX_OP;
-         actParm->opval.op = CAST;
-         actParm->left = newType;
-         actParm->right = parmCopy;
-         decorateType (actParm);
-       }
-      else if (actParm->type == EX_OP && actParm->opval.op == PARAM)
-       {
-         return (processParms (func, NULL, actParm->left, parmNumber, FALSE) ||
-         processParms (func, NULL, actParm->right, parmNumber, rightmost));
-       }
+        {
+          /* 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;
-    }
+    } /* vararg */
 
   /* if defined parameters ended but actual has not & */
   /* reentrant */
-  if (!defParm && actParm &&
-      (options.stackAuto || IFFUNC_ISREENT (func->ftype)))
+  if (!defParm && *actParm &&
+      (options.stackAuto || IFFUNC_ISREENT (functype)))
     return 0;
 
-  resolveSymbols (actParm);
-  /* if this is a PARAM node then match left & right */
-  if (actParm->type == EX_OP && actParm->opval.op == PARAM)
-    {
-      return (processParms (func, defParm, actParm->left, parmNumber, FALSE) ||
-             processParms (func, defParm->next, actParm->right, parmNumber, rightmost));
-    }
-  else
-    {
-      /* If we have found a value node by following only right-hand links,
-       * then we know that there are no more values after us.
-       *
-       * Therefore, if there are more defined parameters, the caller didn't
-       * supply enough.
-       */
-      if (rightmost && defParm->next)
-       {
-         werror (E_TOO_FEW_PARMS);
-         return 1;
-       }
-    }
+  resolveSymbols (*actParm);
 
   /* the parameter type must be at least castable */
-  if (compareType (defParm->type, actParm->ftype) == 0) {
-    werror (E_INCOMPAT_TYPES);
-    printFromToType (actParm->ftype, defParm->type);
-    return 1;
-  }
+  if (compareType (defParm->type, (*actParm)->ftype) == 0)
+    {
+      werror (E_INCOMPAT_TYPES);
+      printFromToType ((*actParm)->ftype, defParm->type);
+      return 1;
+    }
 
   /* if the parameter is castable then add the cast */
-  if (compareType (defParm->type, actParm->ftype) < 0)
+  if (compareType (defParm->type, (*actParm)->ftype) < 0)
     {
-      ast *pTree = decorateType(resolveSymbols (copyAst (actParm)));
+      ast *pTree;
+
+      resultType = getResultTypeFromType (defParm->etype);
+      pTree = resolveSymbols (copyAst (*actParm));
 
       /* now change the current one to a cast */
-      actParm->type = EX_OP;
-      actParm->opval.op = CAST;
-      actParm->left = newAst_LINK (defParm->type);
-      actParm->right = pTree;
-      actParm->etype = defParm->etype;
-      actParm->ftype = defParm->type;
-      actParm->decorated=0; /* force typechecking */
-      decorateType (actParm);
+      (*actParm)->type = EX_OP;
+      (*actParm)->opval.op = CAST;
+      (*actParm)->left = newAst_LINK (defParm->type);
+      (*actParm)->right = pTree;
+      (*actParm)->decorated = 0; /* force typechecking */
+      decorateType (*actParm, resultType);
     }
 
   /* make a copy and change the regparm type to the defined parm */
-  actParm->etype = getSpec (actParm->ftype = copyLinkChain (actParm->ftype));
-  SPEC_REGPARM (actParm->etype) = SPEC_REGPARM (defParm->etype);
-  SPEC_ARGREG  (actParm->etype) = SPEC_ARGREG (defParm->etype);
+  (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
+  SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
+  SPEC_ARGREG  ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
   (*parmNumber)++;
   return 0;
 }
+
 /*-----------------------------------------------------------------*/
 /* createIvalType - generates ival for basic types                 */
 /*-----------------------------------------------------------------*/
@@ -821,15 +938,15 @@ createIvalType (ast * sym, sym_link * type, initList * ilist)
   if (ilist->type == INIT_DEEP)
     ilist = ilist->init.deep;
 
-  iExpr = decorateType (resolveSymbols (list2expr (ilist)));
-  return decorateType (newNode ('=', sym, iExpr));
+  iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
+  return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
 }
 
 /*-----------------------------------------------------------------*/
 /* 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;
@@ -849,16 +966,20 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist)
     {
       /* if we have come to end */
       if (!iloop)
-       break;
+        break;
       sflds->implicit = 1;
       lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
-      lAst = decorateType (resolveSymbols (lAst));
-      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)));
+      lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
+      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
+                                                       iloop, rast, rootValue)),
+                           RESULT_TYPE_NONE);
+
     }
 
   if (iloop) {
-    werror (W_EXCESS_INITIALIZERS, "struct", 
-           sym->opval.val->sym->name, sym->opval.val->sym->lineDef);
+    werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+              W_EXCESS_INITIALIZERS, "struct",
+              sym->opval.val->sym->name);
   }
 
   return rast;
@@ -869,7 +990,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;
@@ -881,82 +1002,89 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
   /* by a string                      */
   if (IS_CHAR (type->next))
     if ((rast = createIvalCharPtr (sym,
-                                  type,
-                       decorateType (resolveSymbols (list2expr (ilist))))))
+                                   type,
+                        decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
+                                   rootValue)))
 
-      return decorateType (resolveSymbols (rast));
+      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;
-
-       aSym = decorateType (resolveSymbols(sym));
-       
-       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;
-           
-           werror (W_EXCESS_INITIALIZERS, "array", name, lineno);
-       }
-    }
-    else
-    {
-       for (;;)
-       {
-           ast *aSym;
-           
-           aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
-           aSym = decorateType (resolveSymbols (aSym));
-           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) 
-           {
-               // there has to be a better way
-               char *name=sym->opval.val->sym->name;
-               int lineno=sym->opval.val->sym->lineDef;
-               werror (W_EXCESS_INITIALIZERS, "array", name, lineno);
-               
-               break;
-           }
-       }
-    }
+  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;
 
-    /* if we have not been given a size  */
-    if (!DCL_ELEM (type))
+          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, 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 : "";
+              int lineno = iloop->lineno;
+              char *filename = iloop->filename;
+              werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
+
+              break;
+          }
+      }
+  }
+
+  /* if we have not been given a size  */
+  if (!DCL_ELEM (type))
     {
-       DCL_ELEM (type) = size;
+      /* 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));
+  return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 }
 
 
@@ -964,15 +1092,16 @@ 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                              */
   if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
-                        SPEC_SCLS (iexpr->etype) == S_CODE)
-                       && IS_ARRAY (iexpr->ftype)))
+                         SPEC_SCLS (iexpr->etype) == S_CODE)
+                        && IS_ARRAY (iexpr->ftype)))
     return newNode ('=', sym, iexpr);
 
   /* left side is an array so we have to assign each */
@@ -984,30 +1113,47 @@ 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;
-
-      while (*s)
-       {
-         rast = newNode (NULLOP,
-                         rast,
-                         newNode ('=',
-                                  newNode ('[', sym,
-                                  newAst_VALUE (valueFromLit ((float) i))),
-                                  newAst_VALUE (valueFromLit (*s))));
-         i++;
-         s++;
-       }
-      rast = newNode (NULLOP,
-                     rast,
-                     newNode ('=',
-                              newNode ('[', sym,
-                                  newAst_VALUE (valueFromLit ((float) i))),
-                              newAst_VALUE (valueFromLit (*s))));
+      unsigned int i = 0;
+      unsigned int symsize = getSize (type);
+
+      size = getSize (iexpr->ftype);
+      if (symsize && size>symsize)
+        {
+          if (size>(symsize+1))
+            {
+              char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+
+              werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+                        "string", name);
+            }
+          size = symsize;
+        }
+
+      for (i=0;i<size;i++)
+        {
+          rast = newNode (NULLOP,
+                          rast,
+                          newNode ('=',
+                                   newNode ('[', sym,
+                                   newAst_VALUE (valueFromLit ((float) i))),
+                                   newAst_VALUE (valueFromLit (*s))));
+          s++;
+        }
 
       // now WE don't need iexpr's symbol anymore
       freeStringSymbol(AST_SYMBOL(iexpr));
 
-      return decorateType (resolveSymbols (rast));
+      /* 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);
     }
 
   return NULL;
@@ -1017,7 +1163,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;
@@ -1026,11 +1172,11 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist)
   if (ilist->type == INIT_DEEP)
     ilist = ilist->init.deep;
 
-  iexpr = decorateType (resolveSymbols (list2expr (ilist)));
+  iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
 
   /* 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);
@@ -1040,7 +1186,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;
 
@@ -1049,31 +1195,32 @@ 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))
     rast = createIvalType (sym, type, ilist);
 
   if (wid)
-    return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)));
+    return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
   else
-    return decorateType (resolveSymbols (rast));
+    return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 }
 
 /*-----------------------------------------------------------------*/
 /* 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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1093,78 +1240,95 @@ gatherAutoInit (symbol * autoChain)
 
       /* resolve the symbols in the ival */
       if (sym->ival)
-       resolveIvalSym (sym->ival);
+        resolveIvalSym (sym->ival, sym->type);
+
+#if 1
+      /* if we are PIC16 port,
+       * and this is a static,
+       * and have initial value,
+       * and not S_CODE, don't emit in gs segment,
+       * but allow glue.c:pic16emitRegularMap to put symbol
+       * in idata section */
+      if(TARGET_IS_PIC16 &&
+        IS_STATIC (sym->etype) && sym->ival
+        && SPEC_SCLS(sym->etype) != S_CODE) {
+        SPEC_SCLS (sym->etype) = S_DATA;
+        continue;
+      }
+#endif
 
       /* if this is a static variable & has an */
       /* initial value the code needs to be lifted */
       /* here to the main portion since they can be */
       /* initialised only once at the start    */
       if (IS_STATIC (sym->etype) && sym->ival &&
-         SPEC_SCLS (sym->etype) != S_CODE)
-       {
-         symbol *newSym;
-         
-         /* insert the symbol into the symbol table */
-         /* with level = 0 & name = rname       */
-         newSym = copySymbol (sym);
-         addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
-
-         /* now lift the code to main */
-         if (IS_AGGREGATE (sym->type)) {
-           work = initAggregates (sym, sym->ival, NULL);
-         } else {
-           if (getNelements(sym->type, sym->ival)>1) {
-             werror (W_EXCESS_INITIALIZERS, "scalar", 
-                     sym->name, sym->lineDef);
-           }
-           work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
-                           list2expr (sym->ival));
-         }
-
-         setAstLineno (work, sym->lineDef);
-
-         sym->ival = NULL;
-         if (staticAutos)
-           staticAutos = newNode (NULLOP, staticAutos, work);
-         else
-           staticAutos = work;
-
-         continue;
-       }
+          SPEC_SCLS (sym->etype) != S_CODE)
+        {
+          symbol *newSym;
+
+          /* insert the symbol into the symbol table */
+          /* with level = 0 & name = rname       */
+          newSym = copySymbol (sym);
+          addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
+
+          /* now lift the code to main */
+          if (IS_AGGREGATE (sym->type)) {
+            work = initAggregates (sym, sym->ival, NULL);
+          } else {
+            if (getNelements(sym->type, sym->ival)>1) {
+              werrorfl (sym->fileDef, sym->lineDef,
+                        W_EXCESS_INITIALIZERS, "scalar",
+                        sym->name);
+            }
+            work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
+                            list2expr (sym->ival));
+          }
+
+          setAstLineno (work, sym->lineDef);
+
+          sym->ival = NULL;
+          if (staticAutos)
+            staticAutos = newNode (NULLOP, staticAutos, work);
+          else
+            staticAutos = work;
+
+          continue;
+        }
 
       /* if there is an initial value */
       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);
-         
-         if (IS_AGGREGATE (sym->type)) {
-           work = initAggregates (sym, sym->ival, NULL);
-         } else {
-           if (getNelements(sym->type, sym->ival)>1) {
-             werror (W_EXCESS_INITIALIZERS, "scalar", 
-                     sym->name, sym->lineDef);
-           }
-           work = newNode ('=', newAst_VALUE (symbolVal (sym)),
-                           list2expr (sym->ival));
-         }
-         
-         // just to be sure
-         setAstLineno (work, sym->lineDef);
-
-         sym->ival = NULL;
-         if (init)
-           init = newNode (NULLOP, init, work);
-         else
-           init = work;
-       }
+        {
+          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);
+
+          if (IS_AGGREGATE (sym->type)) {
+            work = initAggregates (sym, sym->ival, NULL);
+          } else {
+            if (getNelements(sym->type, sym->ival)>1) {
+              werrorfl (sym->fileDef, sym->lineDef,
+                        W_EXCESS_INITIALIZERS, "scalar",
+                        sym->name);
+            }
+            work = newNode ('=', newAst_VALUE (symbolVal (sym)),
+                            list2expr (sym->ival));
+          }
+
+          // just to be sure
+          setAstLineno (work, sym->lineDef);
+
+          sym->ival = NULL;
+          if (init)
+            init = newNode (NULLOP, init, work);
+          else
+            init = work;
+        }
     }
   inInitMode = 0;
   return init;
@@ -1183,7 +1347,7 @@ void freeStringSymbol(symbol *sym) {
     }
   }
 }
-  
+
 /*-----------------------------------------------------------------*/
 /* stringToSymbol - creates a symbol from a literal string         */
 /*-----------------------------------------------------------------*/
@@ -1194,12 +1358,14 @@ stringToSymbol (value * val)
   static int charLbl = 0;
   symbol *sym;
   set *sp;
+  unsigned int size;
 
   // have we heard this before?
   for (sp=statsg->syms; sp; sp=sp->next) {
     sym=sp->item;
-    if (sym->isstrlit && 
-       !strcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char)) {
+    size = getSize (sym->type);
+    if (sym->isstrlit && size == getSize (val->type) &&
+        !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
       // yes, this is old news. Don't publish it again.
       sym->isstrlit++; // but raise the usage count
       return symbolVal(sym);
@@ -1207,7 +1373,7 @@ stringToSymbol (value * val)
   }
 
   SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
-  sym = newSymbol (name, 0);   /* make it @ level 0 */
+  sym = newSymbol (name, 0);    /* make it @ level 0 */
   strncpyz (sym->rname, name, SDCC_NAME_MAX);
 
   /* copy the type from the value passed */
@@ -1225,7 +1391,7 @@ stringToSymbol (value * val)
   if (noAlloc == 0)
     {
       /* allocate it */
-      addSymChain (sym);
+      addSymChain (&sym);
       allocVariables (sym);
     }
   sym->ival = NULL;
@@ -1251,15 +1417,15 @@ processBlockVars (ast * tree, int *stack, int action)
 
       if (action == ALLOCATE)
         {
-         *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);
+          *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);
         }
-      else                     /* action is deallocate */
-       deallocLocal (tree->values.sym);
+      else                      /* action is deallocate */
+        deallocLocal (tree->values.sym);
     }
 
   processBlockVars (tree->left, stack, action);
@@ -1278,55 +1444,55 @@ bool constExprTree (ast *cexpr) {
     return TRUE;
   }
 
-  cexpr = decorateType (resolveSymbols (cexpr));
+  cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
 
-  switch (cexpr->type) 
+  switch (cexpr->type)
     {
     case EX_VALUE:
       if (IS_AST_LIT_VALUE(cexpr)) {
-       // this is a literal
-       return TRUE;
+        // this is a literal
+        return TRUE;
       }
       if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
-       // a function's address will never change
-       return TRUE;
+        // a function's address will never change
+        return TRUE;
       }
       if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
-       // an array's address will never change
-       return TRUE;
+        // an array's address will never change
+        return TRUE;
       }
-      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
+      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
         //printf(" code space symbol");
-       return TRUE;
+        return TRUE;
       }
       return FALSE;
     case EX_LINK:
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-             "unexpected link in expression tree\n");
+              "unexpected link in expression tree\n");
       return FALSE;
     case EX_OP:
       if (cexpr->opval.op==ARRAYINIT) {
-       // this is a list of literals
-       return TRUE;
+        // this is a list of literals
+        return TRUE;
       }
       if (cexpr->opval.op=='=') {
-       return constExprTree(cexpr->right);
+        return constExprTree(cexpr->right);
       }
       if (cexpr->opval.op==CAST) {
-       // cast ignored, maybe we should throw a warning here?
-       return constExprTree(cexpr->right);
+        // cast ignored, maybe we should throw a warning here?
+        return constExprTree(cexpr->right);
       }
-      if (cexpr->opval.op=='&') { 
-       return TRUE;
+      if (cexpr->opval.op=='&') {
+        return TRUE;
       }
       if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
-       return FALSE;
+        return FALSE;
       }
       if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
-       return TRUE;
+        return TRUE;
       }
       return FALSE;
     case EX_OPERAND:
@@ -1334,7 +1500,7 @@ bool constExprTree (ast *cexpr) {
     }
   return FALSE;
 }
-    
+
 /*-----------------------------------------------------------------*/
 /* constExprValue - returns the value of a constant expression     */
 /*                  or NULL if it is not a constant expression     */
@@ -1342,7 +1508,7 @@ bool constExprTree (ast *cexpr) {
 value *
 constExprValue (ast * cexpr, int check)
 {
-  cexpr = decorateType (resolveSymbols (cexpr));
+  cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
 
   /* if this is not a constant then */
   if (!IS_LITERAL (cexpr->ftype))
@@ -1350,47 +1516,50 @@ constExprValue (ast * cexpr, int check)
       /* then check if this is a literal array
          in code segment */
       if (SPEC_SCLS (cexpr->etype) == S_CODE &&
-         SPEC_CVAL (cexpr->etype).v_char &&
-         IS_ARRAY (cexpr->ftype))
-       {
-         value *val = valFromType (cexpr->ftype);
-         SPEC_SCLS (val->etype) = S_LITERAL;
-         val->sym = cexpr->opval.val->sym;
-         val->sym->type = copyLinkChain (cexpr->ftype);
-         val->sym->etype = getSpec (val->sym->type);
-         strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
-         return val;
-       }
+          SPEC_CVAL (cexpr->etype).v_char &&
+          IS_ARRAY (cexpr->ftype))
+        {
+          value *val = valFromType (cexpr->ftype);
+          SPEC_SCLS (val->etype) = S_LITERAL;
+          val->sym = cexpr->opval.val->sym;
+          val->sym->type = copyLinkChain (cexpr->ftype);
+          val->sym->etype = getSpec (val->sym->type);
+          strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
+          return val;
+        }
 
       /* if we are casting a literal value then */
       if (IS_AST_OP (cexpr) &&
-         cexpr->opval.op == CAST &&
-         IS_LITERAL (cexpr->right->ftype))
+          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)
-       werror (E_CONST_EXPECTED, "found expression");
+        werror (E_CONST_EXPECTED, "found expression");
 
       return NULL;
     }
 
   /* 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))
@@ -1410,9 +1579,9 @@ isLabelInAst (symbol * label, ast * tree)
 /* 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)
+                 symbol ** sym, ast ** init, ast ** end)
 {
 
   /* the loop is considered countable if the following
@@ -1425,9 +1594,9 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
 
   /* first check the initExpr */
   if (IS_AST_OP (initExpr) &&
-      initExpr->opval.op == '=' &&     /* is assignment */
+      initExpr->opval.op == '=' &&      /* is assignment */
       IS_AST_SYM_VALUE (initExpr->left))
-    {                          /* left is a symbol */
+    {                           /* left is a symbol */
 
       *sym = AST_SYMBOL (initExpr->left);
       *init = initExpr->right;
@@ -1435,6 +1604,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))
@@ -1445,36 +1618,38 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
     {
 
       switch (condExpr->opval.op)
-       {
-       case '<':
-         if (IS_AST_SYM_VALUE (condExpr->left) &&
-             isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
-             IS_AST_LIT_VALUE (condExpr->right))
-           {
-             *end = condExpr->right;
-             break;
-           }
-         return FALSE;
-
-       case '!':
-         if (IS_AST_OP (condExpr->left) &&
-             condExpr->left->opval.op == '>' &&
-             IS_AST_LIT_VALUE (condExpr->left->right) &&
-             IS_AST_SYM_VALUE (condExpr->left->left) &&
-             isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
-           {
-
-             *end = newNode ('+', condExpr->left->right,
-                             newAst_VALUE (constVal ("1")));
-             break;
-           }
-         return FALSE;
-
-       default:
-         return FALSE;
-       }
+        {
+        case '<':
+          if (IS_AST_SYM_VALUE (condExpr->left) &&
+              isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
+              IS_AST_LIT_VALUE (condExpr->right))
+            {
+              *end = condExpr->right;
+              break;
+            }
+          return FALSE;
+
+        case '!':
+          if (IS_AST_OP (condExpr->left) &&
+              condExpr->left->opval.op == '>' &&
+              IS_AST_LIT_VALUE (condExpr->left->right) &&
+              IS_AST_SYM_VALUE (condExpr->left->left) &&
+              isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
+            {
+
+              *end = newNode ('+', condExpr->left->right,
+                              newAst_VALUE (constVal ("1")));
+              break;
+            }
+          return FALSE;
+
+        default:
+          return FALSE;
+        }
 
     }
+  else
+    return FALSE;
 
   /* check loop expression is of the form <sym>++ */
   if (!IS_AST_OP (loopExpr))
@@ -1485,34 +1660,34 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
     {
 
       if (loopExpr->left)
-       {
-         /* pre */
-         if (IS_AST_SYM_VALUE (loopExpr->left) &&
-             isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
-           return TRUE;
+        {
+          /* pre */
+          if (IS_AST_SYM_VALUE (loopExpr->left) &&
+              isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
+            return TRUE;
 
-       }
+        }
       else
-       {
-         /* post */
-         if (IS_AST_SYM_VALUE (loopExpr->right) &&
-             isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
-           return TRUE;
-       }
+        {
+          /* post */
+          if (IS_AST_SYM_VALUE (loopExpr->right) &&
+              isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
+            return TRUE;
+        }
 
     }
   else
     {
       /* check for += */
       if (loopExpr->opval.op == ADD_ASSIGN)
-       {
-
-         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)
-           return TRUE;
-       }
+        {
+
+          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)
+            return TRUE;
+        }
     }
 
   return FALSE;
@@ -1521,7 +1696,7 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
 /*-----------------------------------------------------------------*/
 /* astHasVolatile - returns true if ast contains any volatile      */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 astHasVolatile (ast * tree)
 {
   if (!tree)
@@ -1540,7 +1715,7 @@ astHasVolatile (ast * tree)
 /*-----------------------------------------------------------------*/
 /* astHasPointer - return true if the ast contains any ptr variable */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 astHasPointer (ast * tree)
 {
   if (!tree)
@@ -1565,7 +1740,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))
@@ -1574,11 +1749,11 @@ astHasSymbol (ast * tree, symbol * sym)
   if (IS_AST_VALUE (tree))
     {
       if (IS_AST_SYM_VALUE (tree))
-       return isSymbolEqual (AST_SYMBOL (tree), sym);
+        return isSymbolEqual (AST_SYMBOL (tree), sym);
       else
-       return FALSE;
+        return FALSE;
     }
-  
+
   return astHasSymbol (tree->left, sym) ||
     astHasSymbol (tree->right, sym);
 }
@@ -1586,14 +1761,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);
 }
 
@@ -1601,7 +1776,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)
 {
 
@@ -1620,7 +1795,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;
@@ -1632,10 +1807,12 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 /*------------------------------------------------------------------*/
     case '[':
       // if the loopvar is used as an index
-      if (astHasSymbol(pbody->right, sym)) {
-       return FALSE;
+      /* array op is commutative -- must check both left & right */
+      if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
+        return FALSE;
       }
-      return isConformingBody (pbody->right, sym, body);
+      return isConformingBody (pbody->right, sym, body)
+              && isConformingBody (pbody->left, sym, body);
 
 /*------------------------------------------------------------------*/
     case PTR_OP:
@@ -1648,20 +1825,20 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 
       /* sure we are not sym is not modified */
       if (pbody->left &&
-         IS_AST_SYM_VALUE (pbody->left) &&
-         isSymbolEqual (AST_SYMBOL (pbody->left), sym))
-       return FALSE;
+          IS_AST_SYM_VALUE (pbody->left) &&
+          isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+        return FALSE;
 
       if (pbody->right &&
-         IS_AST_SYM_VALUE (pbody->right) &&
-         isSymbolEqual (AST_SYMBOL (pbody->right), sym))
-       return FALSE;
+          IS_AST_SYM_VALUE (pbody->right) &&
+          isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+        return FALSE;
 
       return TRUE;
 
 /*------------------------------------------------------------------*/
 
-    case '*':                  /* can be unary  : if right is null then unary operation */
+    case '*':                   /* can be unary  : if right is null then unary operation */
     case '+':
     case '-':
     case '&':
@@ -1672,19 +1849,19 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
       /*  address of                */
 /*----------------------------*/
       if (!pbody->right)
-       {
-         if (IS_AST_SYM_VALUE (pbody->left) &&
-             isSymbolEqual (AST_SYMBOL (pbody->left), sym))
-           return FALSE;
-         else
-           return isConformingBody (pbody->left, sym, body);
-       }
+        {
+          if (IS_AST_SYM_VALUE (pbody->left) &&
+              isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+            return FALSE;
+          else
+            return isConformingBody (pbody->left, sym, body);
+        }
       else
-       {
-         if (astHasSymbol (pbody->left, sym) ||
-             astHasSymbol (pbody->right, sym))
-           return FALSE;
-       }
+        {
+          if (astHasSymbol (pbody->left, sym) ||
+              astHasSymbol (pbody->right, sym))
+            return FALSE;
+        }
 
 
 /*------------------------------------------------------------------*/
@@ -1694,17 +1871,20 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
     case '%':
     case LEFT_OP:
     case RIGHT_OP:
+    case GETABIT:
+    case GETBYTE:
+    case GETWORD:
 
       if (IS_AST_SYM_VALUE (pbody->left) &&
-         isSymbolEqual (AST_SYMBOL (pbody->left), sym))
-       return FALSE;
+          isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+        return FALSE;
 
       if (IS_AST_SYM_VALUE (pbody->right) &&
-         isSymbolEqual (AST_SYMBOL (pbody->right), sym))
-       return FALSE;
+          isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+        return FALSE;
 
       return isConformingBody (pbody->left, sym, body) &&
-       isConformingBody (pbody->right, sym, body);
+        isConformingBody (pbody->right, sym, body);
 
     case '~':
     case '!':
@@ -1713,8 +1893,8 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
     case GETHBIT:
     case SWAP:
       if (IS_AST_SYM_VALUE (pbody->left) &&
-         isSymbolEqual (AST_SYMBOL (pbody->left), sym))
-       return FALSE;
+          isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+        return FALSE;
       return isConformingBody (pbody->left, sym, body);
 
 /*------------------------------------------------------------------*/
@@ -1729,18 +1909,18 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
     case NE_OP:
     case '?':
     case ':':
-    case SIZEOF:               /* evaluate wihout code generation */
-      
+    case SIZEOF:                /* evaluate wihout code generation */
+
       if (IS_AST_SYM_VALUE (pbody->left) &&
-         isSymbolEqual (AST_SYMBOL (pbody->left), sym))
-       return FALSE;
+          isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+        return FALSE;
 
       if (IS_AST_SYM_VALUE (pbody->right) &&
-         isSymbolEqual (AST_SYMBOL (pbody->right), sym))
-       return FALSE;
+          isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+        return FALSE;
 
       return isConformingBody (pbody->left, sym, body) &&
-       isConformingBody (pbody->right, sym, body);
+        isConformingBody (pbody->right, sym, body);
 
 /*------------------------------------------------------------------*/
     case '=':
@@ -1748,29 +1928,29 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
       /* if left has a pointer & right has loop
          control variable then we cannot */
       if (astHasPointer (pbody->left) &&
-         astHasSymbol (pbody->right, sym))
-       return FALSE;
+          astHasSymbol (pbody->right, sym))
+        return FALSE;
       if (astHasVolatile (pbody->left))
-       return FALSE;
+        return FALSE;
 
       if (IS_AST_SYM_VALUE (pbody->left)) {
-       // if the loopvar has an assignment
-       if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
-         return FALSE;
-       // if the loopvar is used in another (maybe conditional) block
-       if (astHasSymbol (pbody->right, sym) &&
-           (pbody->level >= body->level)) {
-         return FALSE;
-       }
+        // if the loopvar has an assignment
+        if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+          return FALSE;
+        // if the loopvar is used in another (maybe conditional) block
+        if (astHasSymbol (pbody->right, sym) &&
+            (pbody->level >= body->level)) {
+          return FALSE;
+        }
       }
 
       if (astHasVolatile (pbody->left))
-       return FALSE;
-      
+        return FALSE;
+
       if (astHasDeref(pbody->right)) return FALSE;
 
       return isConformingBody (pbody->left, sym, body) &&
-       isConformingBody (pbody->right, sym, body);
+        isConformingBody (pbody->right, sym, body);
 
     case MUL_ASSIGN:
     case DIV_ASSIGN:
@@ -1789,16 +1969,16 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 /*----------------------------*/
     case ',':
       return isConformingBody (pbody->left, sym, body) &&
-       isConformingBody (pbody->right, sym, body);
+        isConformingBody (pbody->right, sym, body);
 
 /*------------------------------------------------------------------*/
 /*----------------------------*/
       /*       function call        */
 /*----------------------------*/
     case CALL:
-       /* if local & not passed as paramater then ok */
-       if (sym->level && !astHasSymbol(pbody->right,sym)) 
-           return TRUE;
+        /* if local & not passed as paramater then ok */
+        if (sym->level && !astHasSymbol(pbody->right,sym))
+            return TRUE;
       return FALSE;
 
 /*------------------------------------------------------------------*/
@@ -1810,12 +1990,12 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 
     case GOTO:
       if (isLabelInAst (AST_SYMBOL (pbody->left), body))
-       return TRUE;
+        return TRUE;
       else
-       return FALSE;
+        return FALSE;
     case SWITCH:
       if (astHasSymbol (pbody->left, sym))
-       return FALSE;
+        return FALSE;
 
     default:
       break;
@@ -1833,9 +2013,9 @@ 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)
+                  ast ** init, ast ** end)
 {
   /* if option says don't do it then don't */
   if (optimize.noLoopReverse)
@@ -1848,9 +2028,9 @@ isLoopReversible (ast * loop, symbol ** loopCntrl,
      [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
      forBody */
   if (!isLoopCountable (AST_FOR (loop, initExpr),
-                       AST_FOR (loop, condExpr),
-                       AST_FOR (loop, loopExpr),
-                       loopCntrl, init, end))
+                        AST_FOR (loop, condExpr),
+                        AST_FOR (loop, loopExpr),
+                        loopCntrl, init, end))
     return 0;
 
   /* now do some serious checking on the body of the loop
@@ -1863,7 +2043,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 */
@@ -1874,14 +2054,14 @@ replLoopSym (ast * body, symbol * sym)
     {
 
       if (isSymbolEqual (AST_SYMBOL (body), sym))
-       {
+        {
 
-         body->type = EX_OP;
-         body->opval.op = '-';
-         body->left = newAst_VALUE (symbolVal (sym));
-         body->right = newAst_VALUE (constVal ("1"));
+          body->type = EX_OP;
+          body->opval.op = '-';
+          body->left = newAst_VALUE (symbolVal (sym));
+          body->right = newAst_VALUE (constVal ("1"));
 
-       }
+        }
 
       return;
 
@@ -1910,32 +2090,32 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
 
   /* put it together piece by piece */
   rloop = newNode (NULLOP,
-                  createIf (newAst_VALUE (symbolVal (sym)),
-                            newNode (GOTO,
-                                     newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
-                                     NULL), NULL),
-                  newNode ('=',
-                           newAst_VALUE (symbolVal (sym)),
-                           end));
+                   createIf (newAst_VALUE (symbolVal (sym)),
+                             newNode (GOTO,
+                                      newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
+                                      NULL), NULL),
+                   newNode ('=',
+                            newAst_VALUE (symbolVal (sym)),
+                            end));
 
   replLoopSym (loop->left, sym);
   setAstLineno (rloop, init->lineno);
 
   rloop = newNode (NULLOP,
-                  newNode ('=',
-                           newAst_VALUE (symbolVal (sym)),
-                           newNode ('-', end, init)),
-                  createLabel (AST_FOR (loop, continueLabel),
-                               newNode (NULLOP,
-                                        loop->left,
-                                        newNode (NULLOP,
-                                                 newNode (SUB_ASSIGN,
-                                                          newAst_VALUE (symbolVal (sym)),
-                                                          newAst_VALUE (constVal ("1"))),
-                                                 rloop))));
+                   newNode ('=',
+                            newAst_VALUE (symbolVal (sym)),
+                            newNode ('-', end, init)),
+                   createLabel (AST_FOR (loop, continueLabel),
+                                newNode (NULLOP,
+                                         loop->left,
+                                         newNode (NULLOP,
+                                                  newNode (SUB_ASSIGN,
+                                                           newAst_VALUE (symbolVal (sym)),
+                                                           newAst_VALUE (constVal ("1"))),
+                                                  rloop))));
 
   rloop->lineno=init->lineno;
-  return decorateType (rloop);
+  return decorateType (rloop, RESULT_TYPE_NONE);
 
 }
 
@@ -1954,59 +2134,297 @@ searchLitOp (ast *tree, ast **parent, const char *ops)
           IS_AST_OP(tree->right) &&
           tree->right->right &&
           (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1]))
-       {
-         if (IS_LITERAL (RTYPE (tree->right)) ^
-             IS_LITERAL (LTYPE (tree->right)))
-           {
-             tree->right->decorated = 0;
-             tree->decorated = 0;
-             *parent = tree;
-             return tree->right;
-           }
-         ret = searchLitOp (tree->right, parent, ops);
-         if (ret)
-           return ret;
+        {
+          if (IS_LITERAL (RTYPE (tree->right)) !=
+              IS_LITERAL (LTYPE (tree->right)))
+            {
+              tree->right->decorated = 0;
+              tree->decorated = 0;
+              *parent = tree;
+              return tree->right;
+            }
+          ret = searchLitOp (tree->right, parent, ops);
+          if (ret)
+            return ret;
         }
       if (tree->left &&
           IS_AST_OP(tree->left) &&
           tree->left->right &&
-         (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
-       {
-         if (IS_LITERAL (RTYPE (tree->left)) ^
-             IS_LITERAL (LTYPE (tree->left)))
-           {
-             tree->left->decorated = 0;
-             tree->decorated = 0;
-             *parent = tree;
-             return tree->left;
-           }
-         ret = searchLitOp (tree->left, parent, ops);
-         if (ret)
-           return ret;
-       }
+          (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
+        {
+          if (IS_LITERAL (RTYPE (tree->left)) !=
+              IS_LITERAL (LTYPE (tree->left)))
+            {
+              tree->left->decorated = 0;
+              tree->decorated = 0;
+              *parent = tree;
+              return tree->left;
+            }
+          ret = searchLitOp (tree->left, parent, ops);
+          if (ret)
+            return ret;
+        }
     }
   return NULL;
 }
 
 /*-----------------------------------------------------------------*/
-/* decorateType - compute type for this tree also does type checking */
-/*          this is done bottom up, since type have to flow upwards */
-/*          it also does constant folding, and paramater checking  */
+/* getResultFromType                                               */
 /*-----------------------------------------------------------------*/
-ast *
-decorateType (ast * tree)
+RESULT_TYPE
+getResultTypeFromType (sym_link *type)
 {
-  int parmNumber;
-  sym_link *p;
-
-  if (!tree)
-    return tree;
+  /* type = getSpec (type); */
+  if (IS_BIT (type))
+    return RESULT_TYPE_BIT;
+  if (IS_BITFIELD (type))
+    {
+      int blen = SPEC_BLEN (type);
 
-  /* if already has type then do nothing */
-  if (tree->decorated)
-    return tree;
+      if (blen <= 1)
+        return RESULT_TYPE_BIT;
+      if (blen <= 8)
+        return RESULT_TYPE_CHAR;
+      return RESULT_TYPE_INT;
+    }
+  if (IS_CHAR (type))
+    return RESULT_TYPE_CHAR;
+  if (   IS_INT (type)
+      && !IS_LONG (type))
+    return RESULT_TYPE_INT;
+  return RESULT_TYPE_OTHER;
+}
 
-  tree->decorated = 1;
+/*-----------------------------------------------------------------*/
+/* addCast - adds casts to a type specified by RESULT_TYPE         */
+/*-----------------------------------------------------------------*/
+static ast *
+addCast (ast *tree, RESULT_TYPE resultType, bool promote)
+{
+  sym_link *newLink;
+  bool upCasted = FALSE;
+
+  switch (resultType)
+    {
+      case RESULT_TYPE_NONE:
+        /* if thing smaller than int must be promoted to int */
+        if (!promote ||
+            getSize (tree->etype) >= INTSIZE)
+          /* promotion not necessary or already an int */
+          return tree;
+        /* char and bits: promote to int */
+        newLink = newIntLink();
+        upCasted = TRUE;
+        break;
+      case RESULT_TYPE_BIT:
+        if (!promote ||
+            /* already an int */
+            bitsForType (tree->etype) >= 16 ||
+            /* bit to bit operation: don't promote, the code generators
+               hopefully know everything about promotion rules */
+            bitsForType (tree->etype) == 1)
+          return tree;
+        newLink = newIntLink();
+        upCasted = TRUE;
+        break;
+      case RESULT_TYPE_CHAR:
+        if (IS_CHAR (tree->etype) ||
+            IS_FLOAT(tree->etype) ||
+            IS_FIXED(tree->etype))
+          return tree;
+        newLink = newCharLink();
+        break;
+      case RESULT_TYPE_INT:
+#if 0
+        if (getSize (tree->etype) > INTSIZE)
+          {
+            /* warn ("Loosing significant digits"); */
+            return;
+          }
+#endif
+        /* char: promote to int */
+        if (!promote ||
+            getSize (tree->etype) >= INTSIZE)
+          return tree;
+        newLink = newIntLink();
+        upCasted = TRUE;
+        break;
+      case RESULT_TYPE_OTHER:
+        if (!promote)
+          return tree;
+        /* return type is long, float: promote char to int */
+        if (getSize (tree->etype) >= INTSIZE)
+          return tree;
+        newLink = newIntLink();
+        upCasted = TRUE;
+        break;
+      default:
+        return tree;
+    }
+  tree->decorated = 0;
+  tree = newNode (CAST, newAst_LINK (newLink), tree);
+  tree->lineno = tree->right->lineno;
+  /* keep unsigned type during cast to smaller type,
+     but not when promoting from char to int */
+  if (!upCasted)
+    SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
+  return decorateType (tree, resultType);
+}
+
+/*-----------------------------------------------------------------*/
+/* resultTypePropagate - decides if resultType can be propagated   */
+/*-----------------------------------------------------------------*/
+static RESULT_TYPE
+resultTypePropagate (ast *tree, RESULT_TYPE resultType)
+{
+  switch (tree->opval.op)
+    {
+      case AND_OP:
+      case OR_OP:
+        return resultType;
+      case '=':
+      case '?':
+      case ':':
+      case '|':
+      case '^':
+      case '~':
+      case '*':
+      case '+':
+      case '-':
+      case LABEL:
+        return resultType;
+      case '&':
+        if (!tree->right)
+          /* can be unary */
+          return RESULT_TYPE_NONE;
+        else
+          return resultType;
+      case IFX:
+        return RESULT_TYPE_IFX;
+      default:
+        return RESULT_TYPE_NONE;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* getLeftResultType - gets type from left branch for propagation  */
+/*-----------------------------------------------------------------*/
+static RESULT_TYPE
+getLeftResultType (ast *tree, RESULT_TYPE resultType)
+{
+  switch (tree->opval.op)
+    {
+      case '=':
+      case CAST:
+        if (IS_PTR (LTYPE (tree)))
+          return RESULT_TYPE_NONE;
+        else
+          return getResultTypeFromType (LETYPE (tree));
+      case RETURN:
+        if (IS_PTR (currFunc->type->next))
+          return RESULT_TYPE_NONE;
+        else
+          return getResultTypeFromType (currFunc->type->next);
+      case '[':
+        if (!IS_ARRAY (LTYPE (tree)))
+          return resultType;
+        if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
+          return RESULT_TYPE_CHAR;
+        return resultType;
+      default:
+        return 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-arithmetic, if the  */
+/* result is a char and the operand(s) are int's.                     */
+/* It also does constant folding, and parameter checking.             */
+/*--------------------------------------------------------------------*/
+ast *
+decorateType (ast * tree, RESULT_TYPE resultType)
+{
+  int parmNumber;
+  sym_link *p;
+  RESULT_TYPE resultTypeProp;
+
+  if (!tree)
+    return tree;
+
+  /* if already has type then do nothing */
+  if (tree->decorated)
+    return tree;
+
+  tree->decorated = 1;
 
 #if 0
   /* print the line          */
@@ -2029,7 +2447,7 @@ decorateType (ast * tree)
 
 /*------------------------------------------------------------------*/
 /*----------------------------*/
-  /*   leaf has been reached    */
+/*   leaf has been reached    */
 /*----------------------------*/
   lineno=tree->lineno;
   /* if this is of type value */
@@ -2038,47 +2456,45 @@ decorateType (ast * tree)
     {
 
       if (IS_LITERAL (tree->opval.val->etype))
-       {
+        {
 
-         /* if this is a character array then declare it */
-         if (IS_ARRAY (tree->opval.val->type))
-           tree->opval.val = stringToSymbol (tree->opval.val);
+          /* if this is a character array then declare it */
+          if (IS_ARRAY (tree->opval.val->type))
+            tree->opval.val = stringToSymbol (tree->opval.val);
 
-         /* otherwise just copy the type information */
-         COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
-         return tree;
-       }
+          /* otherwise just copy the type information */
+          COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
+          return tree;
+        }
 
       if (tree->opval.val->sym)
-       {
-         /* 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);
-             /* 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 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;
-               }
-           }
-       }
+        {
+          /* 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);
+              /* 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);
+
+              /* and mark the symbol as referenced */
+              tree->opval.val->sym->isref = 1;
+            }
+        }
+      else
+        wassert(0); /* unreached: all values are literals or symbols */
 
       return tree;
     }
@@ -2093,10 +2509,71 @@ decorateType (ast * tree)
   {
     ast *dtl, *dtr;
 
-    dtl = decorateType (tree->left);
-    /* delay right side for '?' operator since conditional macro expansions might
-       rely on this */
-    dtr = (tree->opval.op == '?' ? tree->right : decorateType (tree->right));
+    #if 0
+    if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
+      {
+        if (tree->left && tree->left->type == EX_OPERAND
+            && (tree->left->opval.op == INC_OP
+                || tree->left->opval.op == DEC_OP)
+            && tree->left->left)
+          {
+            tree->left->right = tree->left->left;
+            tree->left->left = NULL;
+          }
+        if (tree->right && tree->right->type == EX_OPERAND
+            && (tree->right->opval.op == INC_OP
+                || tree->right->opval.op == DEC_OP)
+            && tree->right->left)
+          {
+            tree->right->right = tree->right->left;
+            tree->right->left = NULL;
+          }
+      }
+    #endif
+
+    /* Before decorating the left branch we've to decide in dependence
+       upon tree->opval.op, if resultType can be propagated */
+    resultTypeProp = resultTypePropagate (tree, resultType);
+
+    if (tree->opval.op == '?')
+      dtl = decorateType (tree->left, RESULT_TYPE_IFX);
+    else
+      dtl = decorateType (tree->left, resultTypeProp);
+
+    /* if an array node, we may need to swap branches */
+    if (tree->opval.op == '[')
+      {
+        /* determine which is the array & which the index */
+        if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
+            IS_INTEGRAL (LTYPE (tree)))
+          {
+            ast *tempTree = tree->left;
+            tree->left = tree->right;
+            tree->right = tempTree;
+          }
+      }
+
+    /* After decorating the left branch there's type information available
+       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 '?':
+          /* delay right side for '?' operator since conditional macro
+             expansions might rely on this */
+          dtr = tree->right;
+          break;
+        case CALL:
+          /* decorate right side for CALL (parameter list) in processParms();
+             there is resultType available */
+          dtr = tree->right;
+          break;
+        default:
+          dtr = decorateType (tree->right, resultTypeProp);
+          break;
+      }
 
     /* this is to take care of situations
        when the tree gets rewritten */
@@ -2106,69 +2583,52 @@ decorateType (ast * tree)
       tree->right = dtr;
     if ((dtl && dtl->isError) || (dtr && dtr->isError))
       return tree;
-
-    if (IS_AST_OP(tree) &&
-       (tree->opval.op == CAST || tree->opval.op == '=') &&
-       (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) &&
-       (getSize(RTYPE(tree)) < (unsigned) INTSIZE)) {
-      // this is a cast/assign to a bigger type
-      if (IS_AST_OP(tree->right) &&
-         IS_INTEGRAL(tree->right->ftype) &&
-         (tree->right->opval.op == LEFT_OP ||
-          tree->right->opval.op == '*' ||
-          tree->right->opval.op == '+' ||
-          tree->right->opval.op == '-') &&
-         tree->right->right) {
-       // we should cast an operand instead of the result
-       tree->right->decorated = 0;
-       tree->right->left = newNode( CAST, newAst_LINK(newIntLink()),
-                                    tree->right->left);
-       tree->right = decorateType(tree->right);
-      }
-    }
   }
 
   /* depending on type of operator do */
 
   switch (tree->opval.op)
     {
-       /*------------------------------------------------------------------*/
-       /*----------------------------*/
-       /*        array node          */
-       /*----------------------------*/
+        /*------------------------------------------------------------------*/
+        /*----------------------------*/
+        /*        array node          */
+        /*----------------------------*/
     case '[':
 
-      /* determine which is the array & which the index */
-      if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) && IS_INTEGRAL (LTYPE (tree)))
-       {
-
-         ast *tempTree = tree->left;
-         tree->left = tree->right;
-         tree->right = tempTree;
-       }
-
       /* first check if this is a array or a pointer */
       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
-       {
-         werror (E_NEED_ARRAY_PTR, "[]");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_NEED_ARRAY_PTR, "[]");
+          goto errorTreeReturn;
+        }
 
       /* check if the type of the idx */
       if (!IS_INTEGRAL (RTYPE (tree)))
-       {
-         werror (E_IDX_NOT_INT);
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_IDX_NOT_INT);
+          goto errorTreeReturn;
+        }
 
       /* if the left is an rvalue then error */
       if (LRVAL (tree))
-       {
-         werror (E_LVALUE_REQUIRED, "array access");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_LVALUE_REQUIRED, "array access");
+          goto errorTreeReturn;
+        }
+
+      if (IS_LITERAL (RTYPE (tree)))
+        {
+          int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree)));
+          int arraySize = DCL_ELEM (LTYPE (tree));
+          if (arraySize && arrayIndex >= arraySize)
+            {
+              werror (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;
 
       /*------------------------------------------------------------------*/
@@ -2178,13 +2638,13 @@ decorateType (ast * tree)
     case '.':
       /* if this is not a structure */
       if (!IS_STRUCT (LTYPE (tree)))
-       {
-         werror (E_STRUCT_UNION, ".");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_STRUCT_UNION, ".");
+          goto errorTreeReturn;
+        }
       TTYPE (tree) = structElemType (LTYPE (tree),
-                                    (tree->right->type == EX_VALUE ?
-                              tree->right->opval.val : NULL));
+                                     (tree->right->type == EX_VALUE ?
+                               tree->right->opval.val : NULL));
       TETYPE (tree) = getSpec (TTYPE (tree));
       return tree;
 
@@ -2195,53 +2655,53 @@ decorateType (ast * tree)
     case PTR_OP:
       /* if not pointer to a structure */
       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
-       {
-         werror (E_PTR_REQD);
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_PTR_REQD);
+          goto errorTreeReturn;
+        }
 
       if (!IS_STRUCT (LTYPE (tree)->next))
-       {
-         werror (E_STRUCT_UNION, "->");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_STRUCT_UNION, "->");
+          goto errorTreeReturn;
+        }
 
       TTYPE (tree) = structElemType (LTYPE (tree)->next,
-                                    (tree->right->type == EX_VALUE ?
-                              tree->right->opval.val : NULL));
+                                     (tree->right->type == EX_VALUE ?
+                               tree->right->opval.val : NULL));
       TETYPE (tree) = getSpec (TTYPE (tree));
 
       /* adjust the storage class */
       switch (DCL_TYPE(tree->left->ftype)) {
       case POINTER:
-               SPEC_SCLS(TETYPE(tree)) = S_DATA; 
-       break;
+        SPEC_SCLS(TETYPE(tree)) = S_DATA;
+        break;
       case FPOINTER:
-               SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
-       break;
+        SPEC_SCLS(TETYPE(tree)) = S_XDATA;
+        break;
       case CPOINTER:
-               SPEC_SCLS(TETYPE(tree)) = S_CODE; 
-       break;
+        SPEC_SCLS(TETYPE(tree)) = S_CODE;
+        break;
       case GPOINTER:
-       SPEC_SCLS (TETYPE (tree)) = 0;
-       break;
+        SPEC_SCLS (TETYPE (tree)) = 0;
+        break;
       case PPOINTER:
-               SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
-       break;
+        SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
+        break;
       case IPOINTER:
-               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
-       break;
+        SPEC_SCLS(TETYPE(tree)) = S_IDATA;
+        break;
       case EEPPOINTER:
-               SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
-       break;
+        SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
+        break;
       case UPOINTER:
-       SPEC_SCLS (TETYPE (tree)) = 0;
-       break;
+        SPEC_SCLS (TETYPE (tree)) = 0;
+        break;
       case ARRAY:
       case FUNCTION:
-       break;
+        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                    */
@@ -2256,7 +2716,7 @@ decorateType (ast * tree)
             */
             symbol *sym;
             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
-                                               AST_SYMBOL(tree->right));
+                                                AST_SYMBOL(tree->right));
 
             sym = newSymbol(genSymName (0), 0);
             sym->type = TTYPE (tree);
@@ -2270,7 +2730,7 @@ decorateType (ast * tree)
             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;
@@ -2279,7 +2739,7 @@ decorateType (ast * tree)
             tree->right = NULL;
         }
       #endif
-      
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2289,92 +2749,123 @@ decorateType (ast * tree)
     case INC_OP:
     case DEC_OP:
       {
-       sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
-       COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
+        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 ? "++" : "--");
+          werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
 
-       if (tree->right)
-         RLVAL (tree) = 1;
-       else
-         LLVAL (tree) = 1;
-       return tree;
+        if (tree->right)
+          RLVAL (tree) = 1;
+        else
+          LLVAL (tree) = 1;
+        return tree;
       }
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /*  bitwise and               */
       /*----------------------------*/
-    case '&':                  /* can be unary   */
+    case '&':                   /* can be unary   */
       /* if right is NULL then unary operation  */
-      if (tree->right)         /* not an unary operation */
-       {
-
-         if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
-           {
-             werror (E_BITWISE_OP);
-             werror (W_CONTINUE, "left & right types are ");
-             printTypeChain (LTYPE (tree), stderr);
-             fprintf (stderr, ",");
-             printTypeChain (RTYPE (tree), stderr);
-             fprintf (stderr, "\n");
-             goto errorTreeReturn;
-           }
-
-         /* if they are both literal */
-         if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
-           {
-             tree->type = EX_VALUE;
-             tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
-                                         valFromType (RETYPE (tree)), '&');
-
-             tree->right = tree->left = NULL;
-             TETYPE (tree) = tree->opval.val->etype;
-             TTYPE (tree) = tree->opval.val->type;
-             return tree;
-           }
-
-         /* see if this is a GETHBIT operation if yes
-            then return that */
-         {
-           ast *otree = optimizeGetHbit (tree);
-
-           if (otree != tree)
-             return decorateType (otree);
-         }
-
-         TTYPE (tree) =
-           computeType (LTYPE (tree), RTYPE (tree));
-         TETYPE (tree) = getSpec (TTYPE (tree));
+      if (tree->right)          /* not an unary operation */
+        {
+
+          if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
+            {
+              werror (E_BITWISE_OP);
+              werror (W_CONTINUE, "left & right types are ");
+              printTypeChain (LTYPE (tree), stderr);
+              fprintf (stderr, ",");
+              printTypeChain (RTYPE (tree), stderr);
+              fprintf (stderr, "\n");
+              goto errorTreeReturn;
+            }
+
+          /* if they are both literal */
+          if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
+            {
+              tree->type = EX_VALUE;
+              tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
+                                          valFromType (RETYPE (tree)), '&');
+
+              tree->right = tree->left = NULL;
+              TETYPE (tree) = tree->opval.val->etype;
+              TTYPE (tree) = tree->opval.val->type;
+              return tree;
+            }
+
+          /* see if this is a GETHBIT operation if yes
+             then return that */
+          {
+            ast *otree = optimizeGetHbit (tree, resultType);
+
+            if (otree != tree)
+              return decorateType (otree, RESULT_TYPE_NONE);
+          }
+
+          /* see if this is a GETABIT operation if yes
+             then return that */
+          {
+            ast *otree = optimizeGetAbit (tree, resultType);
+
+            if (otree != tree)
+              return decorateType (otree, RESULT_TYPE_NONE);
+          }
+
+          /* see if this is a GETBYTE operation if yes
+             then return that */
+          {
+            ast *otree = optimizeGetByte (tree, resultType);
+
+            if (otree != tree)
+              return decorateType (otree, RESULT_TYPE_NONE);
+          }
+
+          /* see if this is a GETWORD operation if yes
+             then return that */
+          {
+            ast *otree = optimizeGetWord (tree, resultType);
+
+            if (otree != tree)
+              return decorateType (otree, RESULT_TYPE_NONE);
+          }
 
           /* if left is a literal exchange left & right */
           if (IS_LITERAL (LTYPE (tree)))
-           {
-             ast *tTree = tree->left;
-             tree->left = tree->right;
-             tree->right = tTree;
-           }
-
-         /* if right is a literal and */
-         /* we can find a 2nd literal in a and-tree then */
-         /* rearrange the tree */
-         if (IS_LITERAL (RTYPE (tree)))
-           {
-             ast *parent;
-             ast *litTree = searchLitOp (tree, &parent, "&");
-             if (litTree)
-               {
-                 ast *tTree = litTree->left;
-                 litTree->left = tree->right;
-                 tree->right = tTree;
-                 /* both operands in tTree are literal now */
-                 decorateType (parent);
-               }
-           }
-
-         LRVAL (tree) = RRVAL (tree) = 1;
-         return tree;
-       }
+            {
+              ast *tTree = tree->left;
+              tree->left = tree->right;
+              tree->right = tTree;
+            }
+
+          /* if right is a literal and */
+          /* we can find a 2nd literal in an and-tree then */
+          /* rearrange the tree */
+          if (IS_LITERAL (RTYPE (tree)))
+            {
+              ast *parent;
+              ast *litTree = searchLitOp (tree, &parent, "&");
+              if (litTree)
+                {
+                  DEBUG_CF("&")
+                  ast *tTree = litTree->left;
+                  litTree->left = tree->right;
+                  tree->right = tTree;
+                  /* both operands in litTree are literal now */
+                  decorateType (parent, resultType);
+                }
+            }
+
+          LRVAL (tree) = RRVAL (tree) = 1;
+
+          TTYPE (tree) = computeType (LTYPE (tree),
+                                      RTYPE (tree),
+                                      resultType,
+                                      tree->opval.op);
+          TETYPE (tree) = getSpec (TTYPE (tree));
+
+          return tree;
+        }
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
@@ -2383,56 +2874,56 @@ decorateType (ast * tree)
       p = newLink (DECLARATOR);
       /* if bit field then error */
       if (IS_BITVAR (tree->left->etype))
-       {
-         werror (E_ILLEGAL_ADDR, "address of bit variable");
-         goto errorTreeReturn;
-       }
+        {
+          werror (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");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_ILLEGAL_ADDR, "address of register variable");
+          goto errorTreeReturn;
+        }
 
       if (IS_FUNC (LTYPE (tree)))
-       {
-         // this ought to be ignored
-         return (tree->left);
-       }
+        {
+          // this ought to be ignored
+          return (tree->left);
+        }
 
       if (IS_LITERAL(LTYPE(tree)))
-       {
-         werror (E_ILLEGAL_ADDR, "address of literal");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_ILLEGAL_ADDR, "address of literal");
+          goto errorTreeReturn;
+        }
 
      if (LRVAL (tree))
-       {
-         werror (E_LVALUE_REQUIRED, "address of");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_LVALUE_REQUIRED, "address of");
+          goto errorTreeReturn;
+        }
       if (!LETYPE (tree))
         DCL_TYPE (p) = POINTER;
       else if (SPEC_SCLS (tree->left->etype) == S_CODE)
-       DCL_TYPE (p) = CPOINTER;
+        DCL_TYPE (p) = CPOINTER;
       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
-       DCL_TYPE (p) = FPOINTER;
+        DCL_TYPE (p) = FPOINTER;
       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
-       DCL_TYPE (p) = PPOINTER;
+        DCL_TYPE (p) = PPOINTER;
       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
-       DCL_TYPE (p) = IPOINTER;
+        DCL_TYPE (p) = IPOINTER;
       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
-       DCL_TYPE (p) = EEPPOINTER;
+        DCL_TYPE (p) = EEPPOINTER;
       else if (SPEC_OCLS(tree->left->etype))
-         DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
+          DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
       else
-         DCL_TYPE (p) = POINTER;
+          DCL_TYPE (p) = POINTER;
 
       if (IS_AST_SYM_VALUE (tree->left))
-       {
-         AST_SYMBOL (tree->left)->addrtaken = 1;
-         AST_SYMBOL (tree->left)->allocreq = 1;
-       }
+        {
+          AST_SYMBOL (tree->left)->addrtaken = 1;
+          AST_SYMBOL (tree->left)->allocreq = 1;
+        }
 
       p->next = LTYPE (tree);
       TTYPE (tree) = p;
@@ -2445,13 +2936,13 @@ decorateType (ast * tree)
           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
         {
           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
-                                     AST_SYMBOL(tree->left->right));
-         AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
+                                      AST_SYMBOL(tree->left->right));
+          AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
                                     valueFromLit(element->offset));
-         tree->left = NULL;
-         tree->right = NULL;
-         tree->type = EX_VALUE;
-         tree->values.literalFromCast = 1;
+          tree->left = NULL;
+          tree->right = NULL;
+          tree->type = EX_VALUE;
+          tree->values.literalFromCast = 1;
         }
       #endif
 
@@ -2462,102 +2953,109 @@ decorateType (ast * tree)
       /*  bitwise or                */
       /*----------------------------*/
     case '|':
-      /* if the rewrite succeeds then don't go any furthur */
+      /* if the rewrite succeeds then don't go any further */
       {
-       ast *wtree = optimizeRRCRLC (tree);
-       if (wtree != tree)
-         return decorateType (wtree);
-       
-       wtree = optimizeSWAP (tree);
-       if (wtree != tree)
-         return decorateType (wtree);
-        
-       // fall through
+        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);
       }
 
       /* if left is a literal exchange left & right */
       if (IS_LITERAL (LTYPE (tree)))
-       {
-         ast *tTree = tree->left;
-         tree->left = tree->right;
-         tree->right = tTree;
-       }
+        {
+          ast *tTree = tree->left;
+          tree->left = tree->right;
+          tree->right = tTree;
+        }
 
       /* if right is a literal and */
-      /* we can find a 2nd literal in a or-tree then */
+      /* we can find a 2nd literal in an or-tree then */
       /* rearrange the tree */
       if (IS_LITERAL (RTYPE (tree)))
-       {
-         ast *parent;
-         ast *litTree = searchLitOp (tree, &parent, "|");
-         if (litTree)
-           {
-             ast *tTree = litTree->left;
-             litTree->left = tree->right;
-             tree->right = tTree;
-             /* both operands in tTree are literal now */
-             decorateType (parent);
-           }
+        {
+          ast *parent;
+          ast *litTree = searchLitOp (tree, &parent, "|");
+          if (litTree)
+            {
+              DEBUG_CF("|")
+              ast *tTree = litTree->left;
+              litTree->left = tree->right;
+              tree->right = tTree;
+              /* both operands in tTree are literal now */
+              decorateType (parent, resultType);
+            }
         }
+      /* fall through */
+
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /*  bitwise xor               */
       /*----------------------------*/
     case '^':
       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
-       {
-         werror (E_BITWISE_OP);
-         werror (W_CONTINUE, "left & right types are ");
-         printTypeChain (LTYPE (tree), stderr);
-         fprintf (stderr, ",");
-         printTypeChain (RTYPE (tree), stderr);
-         fprintf (stderr, "\n");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_BITWISE_OP);
+          werror (W_CONTINUE, "left & right types are ");
+          printTypeChain (LTYPE (tree), stderr);
+          fprintf (stderr, ",");
+          printTypeChain (RTYPE (tree), stderr);
+          fprintf (stderr, "\n");
+          goto errorTreeReturn;
+        }
 
-      /* if they are both literal then */
-      /* rewrite the tree */
+      /* if they are both literal then rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
-                                       valFromType (RETYPE (tree)),
-                                       tree->opval.op);
-         tree->right = tree->left = NULL;
-         TETYPE (tree) = tree->opval.val->etype;
-         TTYPE (tree) = tree->opval.val->type;
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
+                                        valFromType (RETYPE (tree)),
+                                        tree->opval.op);
+          tree->right = tree->left = NULL;
+          TETYPE (tree) = tree->opval.val->etype;
+          TTYPE (tree) = tree->opval.val->type;
+          return tree;
+        }
 
       /* if left is a literal exchange left & right */
       if (IS_LITERAL (LTYPE (tree)))
-       {
-         ast *tTree = tree->left;
-         tree->left = tree->right;
-         tree->right = tTree;
-       }
+        {
+          ast *tTree = tree->left;
+          tree->left = tree->right;
+          tree->right = tTree;
+        }
 
       /* if right is a literal and */
       /* we can find a 2nd literal in a xor-tree then */
       /* rearrange the tree */
-      if (IS_LITERAL (RTYPE (tree)))
-       {
-         ast *parent;
-         ast *litTree = searchLitOp (tree, &parent, "^");
-         if (litTree)
-           {
-             ast *tTree = litTree->left;
-             litTree->left = tree->right;
-             tree->right = tTree;
-             /* both operands in litTree are literal now */
-             decorateType (parent);
-           }
+      if (IS_LITERAL (RTYPE (tree)) &&
+          tree->opval.op == '^') /* the same source is used by 'bitwise or' */
+        {
+          ast *parent;
+          ast *litTree = searchLitOp (tree, &parent, "^");
+          if (litTree)
+            {
+              DEBUG_CF("^")
+              ast *tTree = litTree->left;
+              litTree->left = tree->right;
+              tree->right = tTree;
+              /* both operands in litTree are literal now */
+              decorateType (parent, resultType);
+            }
         }
 
       LRVAL (tree) = RRVAL (tree) = 1;
-      TETYPE (tree) = getSpec (TTYPE (tree) =
-                              computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+
+      TTYPE (tree) = computeType (LTYPE (tree),
+                                  RTYPE (tree),
+                                  resultType,
+                                  tree->opval.op);
+      TETYPE (tree) = getSpec (TTYPE (tree));
+
+      return tree;
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
@@ -2565,58 +3063,64 @@ decorateType (ast * tree)
       /*----------------------------*/
     case '/':
       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
-       {
-         werror (E_INVALID_OP, "divide");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_INVALID_OP, "divide");
+          goto errorTreeReturn;
+        }
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valDiv (valFromType (LETYPE (tree)),
-                                   valFromType (RETYPE (tree)));
-         tree->right = tree->left = NULL;
-         TETYPE (tree) = getSpec (TTYPE (tree) =
-                                  tree->opval.val->type);
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->opval.val = valDiv (valFromType (LETYPE (tree)),
+                                    valFromType (RETYPE (tree)));
+          tree->right = tree->left = NULL;
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                   tree->opval.val->type);
+          return tree;
+        }
 
       LRVAL (tree) = RRVAL (tree) = 1;
+
       TETYPE (tree) = getSpec (TTYPE (tree) =
-                              computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+                               computeType (LTYPE (tree),
+                                            RTYPE (tree),
+                                            resultType,
+                                            tree->opval.op));
 
       /* if right is a literal and */
       /* left is also a division by a literal then */
       /* rearrange the tree */
       if (IS_LITERAL (RTYPE (tree))
           /* avoid infinite loop */
-          && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
-       {
-         ast *parent;
-         ast *litTree = searchLitOp (tree, &parent, "/");
-         if (litTree)
-           {
-             if (IS_LITERAL (RTYPE (litTree)))
-               {
-                 /* foo_div */
-                 litTree->right = newNode ('*', litTree->right, tree->right);
-                 litTree->right->lineno = tree->lineno;
-
-                 tree->right->opval.val = constVal ("1");
-                 decorateType (parent);
-               }
-             else
-               {
-                 /* litTree->left is literal: no gcse possible.
-                    We can't call decorateType(parent), because
-                    this would cause an infinit loop. */
-                 parent->decorated = 1;
-                 decorateType (litTree);
-               }
-           }
-       }
+          && (TYPE_TARGET_ULONG) floatFromVal (tree->right->opval.val) != 1)
+        {
+          ast *parent;
+          ast *litTree = searchLitOp (tree, &parent, "/");
+          if (litTree)
+            {
+              if (IS_LITERAL (RTYPE (litTree)))
+                {
+                  /* foo_div */
+                  DEBUG_CF("div r")
+                  litTree->right = newNode ('*',
+                                            litTree->right,
+                                            copyAst (tree->right));
+                  litTree->right->lineno = tree->lineno;
+
+                  tree->right->opval.val = constVal ("1");
+                  decorateType (parent, resultType);
+                }
+              else
+                {
+                  /* litTree->left is literal: no gcse possible.
+                     We can't call decorateType(parent, RESULT_TYPE_NONE), because
+                     this would cause an infinit loop. */
+                  parent->decorated = 1;
+                  decorateType (litTree, resultType);
+                }
+            }
+        }
 
       return tree;
 
@@ -2626,149 +3130,150 @@ decorateType (ast * tree)
       /*----------------------------*/
     case '%':
       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
-       {
-         werror (E_BITWISE_OP);
-         werror (W_CONTINUE, "left & right types are ");
-         printTypeChain (LTYPE (tree), stderr);
-         fprintf (stderr, ",");
-         printTypeChain (RTYPE (tree), stderr);
-         fprintf (stderr, "\n");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_BITWISE_OP);
+          werror (W_CONTINUE, "left & right types are ");
+          printTypeChain (LTYPE (tree), stderr);
+          fprintf (stderr, ",");
+          printTypeChain (RTYPE (tree), stderr);
+          fprintf (stderr, "\n");
+          goto errorTreeReturn;
+        }
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valMod (valFromType (LETYPE (tree)),
-                                   valFromType (RETYPE (tree)));
-         tree->right = tree->left = NULL;
-         TETYPE (tree) = getSpec (TTYPE (tree) =
-                                  tree->opval.val->type);
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->opval.val = valMod (valFromType (LETYPE (tree)),
+                                    valFromType (RETYPE (tree)));
+          tree->right = tree->left = NULL;
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                   tree->opval.val->type);
+          return tree;
+        }
       LRVAL (tree) = RRVAL (tree) = 1;
       TETYPE (tree) = getSpec (TTYPE (tree) =
-                              computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+                               computeType (LTYPE (tree),
+                                            RTYPE (tree),
+                                            resultType,
+                                            tree->opval.op));
       return tree;
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /*  address dereference       */
       /*----------------------------*/
-    case '*':                  /* can be unary  : if right is null then unary operation */
+    case '*':                   /* can be unary  : if right is null then unary operation */
       if (!tree->right)
-       {
-         if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
-           {
-             werror (E_PTR_REQD);
-             goto errorTreeReturn;
-           }
-
-         if (LRVAL (tree))
-           {
-             werror (E_LVALUE_REQUIRED, "pointer deref");
-             goto errorTreeReturn;
-           }
-         if (IS_ADDRESS_OF_OP(tree->left))
+        {
+          if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
+            {
+              werror (E_PTR_REQD);
+              goto errorTreeReturn;
+            }
+
+          if (LRVAL (tree))
+            {
+              werror (E_LVALUE_REQUIRED, "pointer deref");
+              goto errorTreeReturn;
+            }
+          if (IS_ADDRESS_OF_OP(tree->left))
             {
               /* replace *&obj with obj */
               return tree->left->left;
             }
           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
-         TETYPE (tree) = getSpec (TTYPE (tree));
-         /* adjust the storage class */
-         switch (DCL_TYPE(tree->left->ftype)) {
-           case POINTER:
-             SPEC_SCLS(TETYPE(tree)) = S_DATA;
-             break;
-           case FPOINTER:
-             SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
-             break;
-           case CPOINTER:
-             SPEC_SCLS(TETYPE(tree)) = S_CODE; 
-             break;
-           case GPOINTER:
-             SPEC_SCLS (TETYPE (tree)) = 0;
-             break;
-           case PPOINTER:
-             SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
-             break;
-           case IPOINTER:
-             SPEC_SCLS(TETYPE(tree)) = S_IDATA;
-             break;
-           case EEPPOINTER:
-             SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
-             break;
-           case UPOINTER:
-             SPEC_SCLS (TETYPE (tree)) = 0;
+          TETYPE (tree) = getSpec (TTYPE (tree));
+          /* adjust the storage class */
+          switch (DCL_TYPE(tree->left->ftype)) {
+            case POINTER:
+              SPEC_SCLS(TETYPE(tree)) = S_DATA;
+              break;
+            case FPOINTER:
+              SPEC_SCLS(TETYPE(tree)) = S_XDATA;
+              break;
+            case CPOINTER:
+              SPEC_SCLS(TETYPE(tree)) = S_CODE;
+              break;
+            case GPOINTER:
+              SPEC_SCLS (TETYPE (tree)) = 0;
+              break;
+            case PPOINTER:
+              SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
+              break;
+            case IPOINTER:
+              SPEC_SCLS(TETYPE(tree)) = S_IDATA;
+              break;
+            case EEPPOINTER:
+              SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
+              break;
+            case UPOINTER:
+              SPEC_SCLS (TETYPE (tree)) = 0;
+              break;
+            case ARRAY:
+            case FUNCTION:
               break;
-           case ARRAY:
-           case FUNCTION:
-             break;
-         }
-         return tree;
-       }
+          }
+          return tree;
+        }
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /*      multiplication        */
       /*----------------------------*/
       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
-       {
-         werror (E_INVALID_OP, "multiplication");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_INVALID_OP, "multiplication");
+          goto errorTreeReturn;
+        }
 
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valMult (valFromType (LETYPE (tree)),
-                                    valFromType (RETYPE (tree)));
-         tree->right = tree->left = NULL;
-         TETYPE (tree) = getSpec (TTYPE (tree) =
-                                  tree->opval.val->type);
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->opval.val = valMult (valFromType (LETYPE (tree)),
+                                     valFromType (RETYPE (tree)));
+          tree->right = tree->left = NULL;
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                   tree->opval.val->type);
+          return tree;
+        }
 
       /* if left is a literal exchange left & right */
       if (IS_LITERAL (LTYPE (tree)))
-       {
-         ast *tTree = tree->left;
-         tree->left = tree->right;
-         tree->right = tTree;
-       }
+        {
+          ast *tTree = tree->left;
+          tree->left = tree->right;
+          tree->right = tTree;
+        }
 
       /* if right is a literal and */
       /* we can find a 2nd literal in a mul-tree then */
       /* rearrange the tree */
       if (IS_LITERAL (RTYPE (tree)))
-       {
-         ast *parent;
-         ast *litTree = searchLitOp (tree, &parent, "*");
-         if (litTree)
-           {
-             ast *tTree = litTree->left;
-             litTree->left = tree->right;
-             tree->right = tTree;
-             /* both operands in litTree are literal now */
-             decorateType (parent);
-           }
+        {
+          ast *parent;
+          ast *litTree = searchLitOp (tree, &parent, "*");
+          if (litTree)
+            {
+              DEBUG_CF("mul")
+              ast *tTree = litTree->left;
+              litTree->left = tree->right;
+              tree->right = tTree;
+              /* both operands in litTree are literal now */
+              decorateType (parent, resultType);
+            }
         }
 
       LRVAL (tree) = RRVAL (tree) = 1;
+      tree->left  = addCast (tree->left,  resultType, FALSE);
+      tree->right = addCast (tree->right, resultType, FALSE);
       TETYPE (tree) = getSpec (TTYPE (tree) =
-                              computeType (LTYPE (tree),
-                                           RTYPE (tree)));
-
-      /* promote result to int if left & right are char
-        this will facilitate hardware multiplies 8bit x 8bit = 16bit */
-      if (IS_CHAR(LETYPE(tree)) && IS_CHAR(RETYPE(tree))) {
-       SPEC_NOUN(TETYPE(tree)) = V_INT;
-      }
+                                   computeType (LTYPE (tree),
+                                                RTYPE (tree),
+                                                resultType,
+                                                tree->opval.op));
 
       return tree;
 
@@ -2779,26 +3284,26 @@ decorateType (ast * tree)
     case '+':
       /* if unary plus */
       if (!tree->right)
-       {
-         if (!IS_INTEGRAL (LTYPE (tree)))
-           {
-             werror (E_UNARY_OP, '+');
-             goto errorTreeReturn;
-           }
-
-         /* if left is a literal then do it */
-         if (IS_LITERAL (LTYPE (tree)))
-           {
-             tree->type = EX_VALUE;
-             tree->opval.val = valFromType (LETYPE (tree));
-             tree->left = NULL;
-             TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-             return tree;
-           }
-         LRVAL (tree) = 1;
-         COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
-         return tree;
-       }
+        {
+          if (!IS_ARITHMETIC (LTYPE (tree)))
+            {
+              werror (E_UNARY_OP, '+');
+              goto errorTreeReturn;
+            }
+
+          /* if left is a literal then do it */
+          if (IS_LITERAL (LTYPE (tree)))
+            {
+              tree->type = EX_VALUE;
+              tree->opval.val = valFromType (LETYPE (tree));
+              tree->left = NULL;
+              TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+              return tree;
+            }
+          LRVAL (tree) = 1;
+          COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
+          return tree;
+        }
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
@@ -2808,129 +3313,145 @@ decorateType (ast * tree)
       /* this is not a unary operation */
       /* if both pointers then problem */
       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
-         (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
-       {
-         werror (E_PTR_PLUS_PTR);
-         goto errorTreeReturn;
-       }
+          (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
+        {
+          werror (E_PTR_PLUS_PTR);
+          goto errorTreeReturn;
+        }
 
       if (!IS_ARITHMETIC (LTYPE (tree)) &&
-         !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
-       {
-         werror (E_PLUS_INVALID, "+");
-         goto errorTreeReturn;
-       }
+          !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
+        {
+          werror (E_PLUS_INVALID, "+");
+          goto errorTreeReturn;
+        }
 
       if (!IS_ARITHMETIC (RTYPE (tree)) &&
-         !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
-       {
-         werror (E_PLUS_INVALID, "+");
-         goto errorTreeReturn;
-       }
+          !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
+        {
+          werror (E_PLUS_INVALID, "+");
+          goto errorTreeReturn;
+        }
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valPlus (valFromType (LETYPE (tree)),
-                                    valFromType (RETYPE (tree)));
-         tree->right = tree->left = NULL;
-         TETYPE (tree) = getSpec (TTYPE (tree) =
-                                  tree->opval.val->type);
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->left  = addCast (tree->left,  resultType, TRUE);
+          tree->right = addCast (tree->right, resultType, TRUE);
+          tree->opval.val = valPlus (valFromType (LETYPE (tree)),
+                                     valFromType (RETYPE (tree)));
+          tree->right = tree->left = NULL;
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                   tree->opval.val->type);
+          return tree;
+        }
 
       /* if the right is a pointer or left is a literal
          xchange left & right */
       if (IS_ARRAY (RTYPE (tree)) ||
-         IS_PTR (RTYPE (tree)) ||
-         IS_LITERAL (LTYPE (tree)))
-       {
-         ast *tTree = tree->left;
-         tree->left = tree->right;
-         tree->right = tTree;
-       }
+          IS_PTR (RTYPE (tree)) ||
+          IS_LITERAL (LTYPE (tree)))
+        {
+          ast *tTree = tree->left;
+          tree->left = tree->right;
+          tree->right = tTree;
+        }
 
       /* if right is a literal and */
       /* left is also an addition/subtraction with a literal then */
       /* rearrange the tree */
       if (IS_LITERAL (RTYPE (tree)))
-       {
-         ast *litTree, *parent;
-         litTree = searchLitOp (tree, &parent, "+-");
-         if (litTree)
-           {
-             if (litTree->opval.op == '+')
-               {
-                 /* foo_aa */
-                 ast *tTree = litTree->left;
-                 litTree->left = tree->right;
-                 tree->right = tree->left;
-                 tree->left = tTree;
-               }
-             else if (litTree->opval.op == '-')
-               {
-                 if (IS_LITERAL (RTYPE (litTree)))
-                   {
-                     /* foo_asr */
-                     ast *tTree = litTree->left;
-                     litTree->left = tree->right;
-                     tree->right = tTree;
-                   }
-                 else
-                   {
-                     /* foo_asl */
-                     ast *tTree = litTree->right;
-                     litTree->right = tree->right;
-                     tree->right = tTree;
-                     litTree->opval.op = '+';
-                     tree->opval.op = '-';
-                   }
-               }
-             decorateType (parent);
-           }
-       }
+        {
+          ast *litTree, *parent;
+          litTree = searchLitOp (tree, &parent, "+-");
+          if (litTree)
+            {
+              if (litTree->opval.op == '+')
+                {
+                  /* foo_aa */
+                  DEBUG_CF("+ 1 AA")
+                  ast *tTree = litTree->left;
+                  litTree->left = tree->right;
+                  tree->right = tree->left;
+                  tree->left = tTree;
+                }
+              else if (litTree->opval.op == '-')
+                {
+                  if (IS_LITERAL (RTYPE (litTree)))
+                    {
+                      DEBUG_CF("+ 2 ASR")
+                      /* foo_asr */
+                      ast *tTree = litTree->left;
+                      litTree->left = tree->right;
+                      tree->right = tTree;
+                    }
+                  else
+                    {
+                      DEBUG_CF("+ 3 ASL")
+                      /* foo_asl */
+                      ast *tTree = litTree->right;
+                      litTree->right = tree->right;
+                      tree->right = tTree;
+                      litTree->opval.op = '+';
+                      tree->opval.op = '-';
+                    }
+                }
+              decorateType (parent, resultType);
+            }
+        }
 
       LRVAL (tree) = RRVAL (tree) = 1;
       /* if the left is a pointer */
       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                LTYPE (tree));
+        TETYPE (tree) = getSpec (TTYPE (tree) =
+                                 LTYPE (tree));
       else
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                computeType (LTYPE (tree),
-                                             RTYPE (tree)));
+        {
+          tree->left  = addCast (tree->left,  resultType, TRUE);
+          tree->right = addCast (tree->right, resultType, TRUE);
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                     computeType (LTYPE (tree),
+                                                  RTYPE (tree),
+                                                  resultType,
+                                                  tree->opval.op));
+        }
+
       return tree;
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /*      unary '-'             */
       /*----------------------------*/
-    case '-':                  /* can be unary   */
+    case '-':                   /* can be unary   */
       /* if right is null then unary */
       if (!tree->right)
-       {
-
-         if (!IS_ARITHMETIC (LTYPE (tree)))
-           {
-             werror (E_UNARY_OP, tree->opval.op);
-             goto errorTreeReturn;
-           }
-
-         /* if left is a literal then do it */
-         if (IS_LITERAL (LTYPE (tree)))
-           {
-             tree->type = EX_VALUE;
-             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;
-           }
-         LRVAL (tree) = 1;
-         TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
-         return tree;
-       }
+        {
+
+          if (!IS_ARITHMETIC (LTYPE (tree)))
+            {
+              werror (E_UNARY_OP, tree->opval.op);
+              goto errorTreeReturn;
+            }
+
+          /* if left is a literal then do it */
+          if (IS_LITERAL (LTYPE (tree)))
+            {
+              tree->type = EX_VALUE;
+              tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
+              tree->left = NULL;
+              TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+              return tree;
+            }
+          tree->left  = addCast (tree->left, resultType, TRUE);
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                     computeType (LTYPE (tree),
+                                                  NULL,
+                                                  resultType,
+                                                  tree->opval.op));
+          LRVAL (tree) = 1;
+          return tree;
+        }
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
@@ -2938,67 +3459,76 @@ decorateType (ast * tree)
       /*----------------------------*/
 
       if (!(IS_PTR (LTYPE (tree)) ||
-           IS_ARRAY (LTYPE (tree)) ||
-           IS_ARITHMETIC (LTYPE (tree))))
-       {
-         werror (E_PLUS_INVALID, "-");
-         goto errorTreeReturn;
-       }
+            IS_ARRAY (LTYPE (tree)) ||
+            IS_ARITHMETIC (LTYPE (tree))))
+        {
+          werror (E_PLUS_INVALID, "-");
+          goto errorTreeReturn;
+        }
 
       if (!(IS_PTR (RTYPE (tree)) ||
-           IS_ARRAY (RTYPE (tree)) ||
-           IS_ARITHMETIC (RTYPE (tree))))
-       {
-         werror (E_PLUS_INVALID, "-");
-         goto errorTreeReturn;
-       }
+            IS_ARRAY (RTYPE (tree)) ||
+            IS_ARITHMETIC (RTYPE (tree))))
+        {
+          werror (E_PLUS_INVALID, "-");
+          goto errorTreeReturn;
+        }
 
       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
-         !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
-           IS_INTEGRAL (RTYPE (tree))))
-       {
-         werror (E_PLUS_INVALID, "-");
-         goto errorTreeReturn;
-       }
+          !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
+            IS_INTEGRAL (RTYPE (tree))))
+        {
+          werror (E_PLUS_INVALID, "-");
+          goto errorTreeReturn;
+        }
 
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valMinus (valFromType (LETYPE (tree)),
-                                     valFromType (RETYPE (tree)));
-         tree->right = tree->left = NULL;
-         TETYPE (tree) = getSpec (TTYPE (tree) =
-                                  tree->opval.val->type);
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->left  = addCast (tree->left,  resultType, TRUE);
+          tree->right = addCast (tree->right, resultType, TRUE);
+          tree->opval.val = valMinus (valFromType (LETYPE (tree)),
+                                      valFromType (RETYPE (tree)));
+          tree->right = tree->left = NULL;
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                   tree->opval.val->type);
+          return tree;
+        }
 
       /* if the left & right are equal then zero */
       if (isAstEqual (tree->left, tree->right))
-       {
-         tree->type = EX_VALUE;
-         tree->left = tree->right = NULL;
-         tree->opval.val = constVal ("0");
-         TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->left = tree->right = NULL;
+          tree->opval.val = constVal ("0");
+          TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+          return tree;
+        }
 
       /* if both of them are pointers or arrays then */
       /* the result is going to be an integer        */
       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
-         (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
-       TETYPE (tree) = TTYPE (tree) = newIntLink ();
+          (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
+        TETYPE (tree) = TTYPE (tree) = newIntLink ();
       else
-       /* if only the left is a pointer */
-       /* then result is a pointer      */
+        /* if only the left is a pointer */
+        /* then result is a pointer      */
       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                LTYPE (tree));
+        TETYPE (tree) = getSpec (TTYPE (tree) =
+                                 LTYPE (tree));
       else
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                computeType (LTYPE (tree),
-                                             RTYPE (tree)));
+        {
+          tree->left  = addCast (tree->left,  resultType, TRUE);
+          tree->right = addCast (tree->right, resultType, TRUE);
+
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                     computeType (LTYPE (tree),
+                                                  RTYPE (tree),
+                                                  resultType,
+                                                  tree->opval.op));
+        }
 
       LRVAL (tree) = RRVAL (tree) = 1;
 
@@ -3007,41 +3537,50 @@ decorateType (ast * tree)
       /* rearrange the tree */
       if (IS_LITERAL (RTYPE (tree))
           /* avoid infinite loop */
-          && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
-       {
-         ast *litTree, *litParent;
-         litTree = searchLitOp (tree, &litParent, "+-");
-         if (litTree)
-           {
-             if (litTree->opval.op == '+')
-               {
-                 /* foo_sa */
-                 litTree->right = newNode ('-', litTree->right, tree->right);
-                 litTree->right->lineno = tree->lineno;
-
-                 tree->right->opval.val = constVal ("0");
-               }
-             else if (litTree->opval.op == '-')
-               {
-                 if (IS_LITERAL (RTYPE (litTree)))
-                   {
-                     /* foo_ssr */
-                     litTree->right = newNode ('+', tree->right, litTree->right);
-                     litTree->right->lineno = tree->lineno;
-
-                     tree->right->opval.val = constVal ("0");
-                   }
-                 else
-                   {
-                     /* foo_ssl */
-                     ast *tTree = litTree->right;
-                     litTree->right = tree->right;
-                     tree->right = tTree;
-                   }
-               }
-             decorateType (litParent);
-           }
-       }
+          && (TYPE_TARGET_ULONG) floatFromVal (tree->right->opval.val) != 0)
+        {
+          ast *litTree, *litParent;
+          litTree = searchLitOp (tree, &litParent, "+-");
+          if (litTree)
+            {
+              if (litTree->opval.op == '+')
+                {
+                  /* foo_sa */
+                  DEBUG_CF("- 1 SA")
+                  ast *tTree = litTree->left;
+                  litTree->left = litTree->right;
+                  litTree->right = tree->right;
+                  tree->right = tTree;
+                  tree->opval.op = '+';
+                  litTree->opval.op = '-';
+                }
+              else if (litTree->opval.op == '-')
+                {
+                  if (IS_LITERAL (RTYPE (litTree)))
+                    {
+                      /* foo_ssr */
+                      DEBUG_CF("- 2 SSR")
+                      ast *tTree = litTree->left;
+                      litTree->left = tree->right;
+                      tree->right = litParent->left;
+                      litParent->left = tTree;
+                      litTree->opval.op = '+';
+
+                      tree->decorated = 0;
+                      decorateType (tree, resultType);
+                    }
+                  else
+                    {
+                      /* foo_ssl */
+                      DEBUG_CF("- 3 SSL")
+                      ast *tTree = litTree->right;
+                      litTree->right = tree->right;
+                      tree->right = tTree;
+                    }
+                }
+              decorateType (litParent, resultType);
+            }
+        }
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3051,20 +3590,37 @@ decorateType (ast * tree)
     case '~':
       /* can be only integral type */
       if (!IS_INTEGRAL (LTYPE (tree)))
-       {
-         werror (E_UNARY_OP, tree->opval.op);
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_UNARY_OP, tree->opval.op);
+          goto errorTreeReturn;
+        }
 
       /* if left is a literal then do it */
       if (IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valComplement (valFromType (LETYPE (tree)));
-         tree->left = NULL;
-         TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->opval.val = valComplement (valFromType (LETYPE (tree)));
+          tree->left = NULL;
+          TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+          return addCast (tree, resultType, TRUE);
+        }
+
+      if (resultType == RESULT_TYPE_BIT &&
+          IS_UNSIGNED (tree->left->etype) &&
+          getSize (tree->left->etype) < INTSIZE)
+        {
+          /* promotion rules are responsible for this strange result:
+             bit -> int -> ~int -> bit
+             uchar -> int -> ~int -> bit
+          */
+          werror(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);
       LRVAL (tree) = 1;
       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
       return tree;
@@ -3076,24 +3632,38 @@ decorateType (ast * tree)
     case '!':
       /* can be pointer */
       if (!IS_ARITHMETIC (LTYPE (tree)) &&
-         !IS_PTR (LTYPE (tree)) &&
-         !IS_ARRAY (LTYPE (tree)))
-       {
-         werror (E_UNARY_OP, tree->opval.op);
-         goto errorTreeReturn;
-       }
+          !IS_PTR (LTYPE (tree)) &&
+          !IS_ARRAY (LTYPE (tree)))
+        {
+          werror (E_UNARY_OP, tree->opval.op);
+          goto errorTreeReturn;
+        }
+
+      /* if left is another '!' */
+      if (tree->left->opval.op == '!')
+        {
+          /* 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)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valNot (valFromType (LETYPE (tree)));
-         tree->left = NULL;
-         TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->opval.val = valNot (valFromType (LETYPE (tree)));
+          tree->left = NULL;
+          TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+          return tree;
+        }
       LRVAL (tree) = 1;
-      TTYPE (tree) = TETYPE (tree) = newCharLink ();
+      TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3108,128 +3678,229 @@ decorateType (ast * tree)
       return tree;
 
     case GETHBIT:
-      TTYPE (tree) = TETYPE (tree) = newCharLink ();
+    case GETABIT:
+      TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
+      return tree;
+
+    case GETBYTE:
+      TTYPE (tree) = TETYPE (tree) = newCharLink();
+      return tree;
+
+    case GETWORD:
+      TTYPE (tree) = TETYPE (tree) = newIntLink();
       return tree;
 
     case LEFT_OP:
     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 ");
-         printTypeChain (LTYPE (tree), stderr);
-         fprintf (stderr, ",");
-         printTypeChain (RTYPE (tree), stderr);
-         fprintf (stderr, "\n");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_SHIFT_OP_INVALID);
+          werror (W_CONTINUE, "left & right types are ");
+          printTypeChain (LTYPE (tree), stderr);
+          fprintf (stderr, ",");
+          printTypeChain (RTYPE (tree), stderr);
+          fprintf (stderr, "\n");
+          goto errorTreeReturn;
+        }
+
+      /* make smaller type only if it's a LEFT_OP */
+      if (tree->opval.op == LEFT_OP)
+        tree->left = addCast (tree->left, resultType, TRUE);
 
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valShift (valFromType (LETYPE (tree)),
-                                     valFromType (RETYPE (tree)),
-                                     (tree->opval.op == LEFT_OP ? 1 : 0));
-         tree->right = tree->left = NULL;
-         TETYPE (tree) = getSpec (TTYPE (tree) =
-                                  tree->opval.val->type);
-         return tree;
-       }
+        {
+          tree->type = EX_VALUE;
+          tree->opval.val = valShift (valFromType (LETYPE (tree)),
+                                      valFromType (RETYPE (tree)),
+                                      (tree->opval.op == LEFT_OP ? 1 : 0));
+          tree->right = tree->left = NULL;
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                   tree->opval.val->type);
+          return tree;
+        }
+
+      /* see if this is a GETBYTE operation if yes
+         then return that */
+      {
+        ast *otree = optimizeGetByte (tree, resultType);
+
+        if (otree != tree)
+          return decorateType (otree, RESULT_TYPE_NONE);
+      }
+
+      /* see if this is a GETWORD operation if yes
+         then return that */
+      {
+        ast *otree = optimizeGetWord (tree, resultType);
+
+        if (otree != tree)
+          return decorateType (otree, RESULT_TYPE_NONE);
+      }
+
+      LRVAL (tree) = RRVAL (tree) = 1;
+      if (tree->opval.op == LEFT_OP)
+        {
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                       computeType (LTYPE (tree),
+                                                    NULL,
+                                                    resultType,
+                                                    tree->opval.op));
+        }
+      else /* RIGHT_OP */
+        {
+          /* no promotion necessary */
+          TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
+          if (IS_LITERAL (TTYPE (tree)))
+            SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
+        }
 
       /* 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)) &&
-         ((unsigned) floatFromVal (valFromType (RETYPE (tree)))) >=
-         (getSize (LTYPE (tree)) * 8))
-       {
-         if (tree->opval.op==LEFT_OP ||
-             (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) {
-           lineno=tree->lineno;
-           werror (W_SHIFT_CHANGED,
-                   (tree->opval.op == LEFT_OP ? "left" : "right"));
-           tree->type = EX_VALUE;
-           tree->left = tree->right = NULL;
-           tree->opval.val = constVal ("0");
-           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-           return tree;
-         }
-       }
-      LRVAL (tree) = RRVAL (tree) = 1;
-      TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
-      if (IS_LITERAL (TTYPE (tree)))
-        SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
+          ((TYPE_TARGET_ULONG) floatFromVal (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,
+                      (tree->opval.op == LEFT_OP ? "left" : "right"));
+              tree->type = EX_VALUE;
+              tree->left = tree->right = NULL;
+              tree->opval.val = constVal ("0");
+              TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+              return tree;
+            }
+        }
+
       return tree;
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /*         casting            */
       /*----------------------------*/
-    case CAST:                 /* change the type   */
+    case CAST:                  /* change the type   */
       /* cannot cast to an aggregate type */
       if (IS_AGGREGATE (LTYPE (tree)))
-       {
-         werror (E_CAST_ILLEGAL);
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_CAST_ILLEGAL);
+          goto errorTreeReturn;
+        }
 
       /* make sure the type is complete and sane */
+      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       */
+      {
+        sym_link *t = LTYPE(tree);
+        while (t && t->next)
+          {
+            if (IS_CODEPTR(t) && port->mem.code_ro)
+              {
+                if (IS_SPEC(t->next))
+                  SPEC_CONST (t->next) = 1;
+                else
+                  DCL_PTR_CONST (t->next) = 1;
+              }
+            t = t->next;
+          }
+      }
+
 #if 0
       /* if the right is a literal replace the tree */
       if (IS_LITERAL (RETYPE (tree))) {
-             if (!IS_PTR (LTYPE (tree))) {
-                     tree->type = EX_VALUE;
-                     tree->opval.val =
-                             valCastLiteral (LTYPE (tree),
-                                             floatFromVal (valFromType (RETYPE (tree))));
-                     tree->left = NULL;
-                     tree->right = NULL;
-                     TTYPE (tree) = tree->opval.val->type;
-                     tree->values.literalFromCast = 1;
-             } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
-                        ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
-                     sym_link *rest = LTYPE(tree)->next;
-                     werror(W_LITERAL_GENERIC);
-                     TTYPE(tree) = newLink(DECLARATOR);
-                     DCL_TYPE(TTYPE(tree)) = FPOINTER;
-                     TTYPE(tree)->next = rest;
-                     tree->left->opval.lnk = TTYPE(tree);
-                     LRVAL (tree) = 1;
-             } else {
-                     TTYPE (tree) = LTYPE (tree);
-                     LRVAL (tree) = 1;
-             }
+              if (!IS_PTR (LTYPE (tree))) {
+                      tree->type = EX_VALUE;
+                      tree->opval.val =
+                              valCastLiteral (LTYPE (tree),
+                                              floatFromVal (valFromType (RETYPE (tree))));
+                      tree->left = NULL;
+                      tree->right = NULL;
+                      TTYPE (tree) = tree->opval.val->type;
+                      tree->values.literalFromCast = 1;
+              } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
+                         ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
+                      sym_link *rest = LTYPE(tree)->next;
+                      werror(W_LITERAL_GENERIC);
+                      TTYPE(tree) = newLink(DECLARATOR);
+                      DCL_TYPE(TTYPE(tree)) = FPOINTER;
+                      TTYPE(tree)->next = rest;
+                      tree->left->opval.lnk = TTYPE(tree);
+                      LRVAL (tree) = 1;
+              } else {
+                      TTYPE (tree) = LTYPE (tree);
+                      LRVAL (tree) = 1;
+              }
       } else {
-             TTYPE (tree) = LTYPE (tree);
-             LRVAL (tree) = 1;
+              TTYPE (tree) = LTYPE (tree);
+              LRVAL (tree) = 1;
       }
 #else
 #if 0 // this is already checked, now this could be explicit
       /* if pointer to struct then check names */
       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
-         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,
-                SPEC_STRUCT(LETYPE(tree))->tag);
-       }
+          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,
+                 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)
+                                        || TARGET_IS_PIC16) )
+          {
+            switch (SPEC_SCLS (sym->etype))
+              {
+              case S_CODE:
+                gptype = GPTYPE_CODE;
+                break;
+              case S_XDATA:
+                gptype = GPTYPE_FAR;
+                break;
+              case S_DATA:
+              case S_IDATA:
+                gptype = GPTYPE_NEAR;
+                break;
+              case S_PDATA:
+                gptype = GPTYPE_XSTACK;
+                break;
+              default:
+                gptype = 0;
+
+                if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
+                    gptype = GPTYPE_NEAR;
+              }
+            addr |= gptype << (8*(GPTRSIZE - 1));
+          }
+
         tree->type = EX_VALUE;
-       tree->opval.val =
-         valCastLiteral (LTYPE (tree),
-                         SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
-       TTYPE (tree) = tree->opval.val->type;
+        tree->opval.val =
+          valCastLiteral (LTYPE (tree), addr);
+        TTYPE (tree) = tree->opval.val->type;
         TETYPE (tree) = getSpec (TTYPE (tree));
-       tree->left = NULL;
-       tree->right = NULL;
-       tree->values.literalFromCast = 1;
+        tree->left = NULL;
+        tree->right = NULL;
+        tree->values.literalFromCast = 1;
         return tree;
       }
 
@@ -3245,27 +3916,28 @@ decorateType (ast * tree)
 
         symbol *element = getStructElement (
           SPEC_STRUCT (LETYPE(tree->right->left)),
-         AST_SYMBOL(tree->right->left->right)
+          AST_SYMBOL(tree->right->left->right)
         );
 
         if (element) {
           tree->type = EX_VALUE;
-         tree->opval.val = valCastLiteral (
-           LTYPE (tree),
-           element->offset
-            + floatFromVal (valFromType (RETYPE (tree->right->left->left)))
+          tree->opval.val = valCastLiteral (
+            LTYPE (tree),
+            element->offset
+            + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
           );
 
-         TTYPE (tree) = tree->opval.val->type;
+          TTYPE (tree) = tree->opval.val->type;
           TETYPE (tree) = getSpec (TTYPE (tree));
-         tree->left = NULL;
-         tree->right = NULL;
+          tree->left = NULL;
+          tree->right = NULL;
           return tree;
         }
       }
 
       /* if the right is a literal replace the tree */
       if (IS_LITERAL (RETYPE (tree))) {
+        #if 0
         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
           /* rewrite      (type *)litaddr
              as           &temp
@@ -3289,7 +3961,7 @@ decorateType (ast * tree)
           sym->cdef = 1;
           sym->isref = 1;
           SPEC_STAT (sym->etype) = 1;
-          SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RETYPE (tree)));
+          SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
           SPEC_ABSA(sym->etype) = 1;
           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
           allocGlobal (sym);
@@ -3298,21 +3970,22 @@ decorateType (ast * tree)
           newTree->left->lineno = tree->lineno;
           LTYPE (newTree) = sym->type;
           LETYPE (newTree) = sym->etype;
-         LLVAL (newTree) = 1;
+          LLVAL (newTree) = 1;
           LRVAL (newTree) = 0;
           TLVAL (newTree) = 1;
           return newTree;
         }
+        #endif
         if (!IS_PTR (LTYPE (tree))) {
-         tree->type = EX_VALUE;
-         tree->opval.val =
-         valCastLiteral (LTYPE (tree),
-                         floatFromVal (valFromType (RETYPE (tree))));
-         TTYPE (tree) = tree->opval.val->type;
-         tree->left = NULL;
-         tree->right = NULL;
-         tree->values.literalFromCast = 1;
-         TETYPE (tree) = getSpec (TTYPE (tree));
+          tree->type = EX_VALUE;
+          tree->opval.val =
+          valCastLiteral (LTYPE (tree),
+                          floatFromVal (valFromType (RTYPE (tree))));
+          TTYPE (tree) = tree->opval.val->type;
+          tree->left = NULL;
+          tree->right = NULL;
+          tree->values.literalFromCast = 1;
+          TETYPE (tree) = getSpec (TTYPE (tree));
           return tree;
         }
       }
@@ -3330,38 +4003,38 @@ decorateType (ast * tree)
       /*----------------------------*/
     case AND_OP:
     case OR_OP:
-      /* each must me arithmetic type or be a pointer */
+      /* each must be arithmetic type or be a pointer */
       if (!IS_PTR (LTYPE (tree)) &&
-         !IS_ARRAY (LTYPE (tree)) &&
-         !IS_INTEGRAL (LTYPE (tree)))
-       {
-         werror (E_COMPARE_OP);
-         goto errorTreeReturn;
-       }
+          !IS_ARRAY (LTYPE (tree)) &&
+          !IS_INTEGRAL (LTYPE (tree)))
+        {
+          werror (E_COMPARE_OP);
+          goto errorTreeReturn;
+        }
 
       if (!IS_PTR (RTYPE (tree)) &&
-         !IS_ARRAY (RTYPE (tree)) &&
-         !IS_INTEGRAL (RTYPE (tree)))
-       {
-         werror (E_COMPARE_OP);
-         goto errorTreeReturn;
-       }
+          !IS_ARRAY (RTYPE (tree)) &&
+          !IS_INTEGRAL (RTYPE (tree)))
+        {
+          werror (E_COMPARE_OP);
+          goto errorTreeReturn;
+        }
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) &&
-         IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valLogicAndOr (valFromType (LETYPE (tree)),
-                                          valFromType (RETYPE (tree)),
-                                          tree->opval.op);
-         tree->right = tree->left = NULL;
-         TETYPE (tree) = getSpec (TTYPE (tree) =
-                                  tree->opval.val->type);
-         return tree;
-       }
+          IS_LITERAL (LTYPE (tree)))
+        {
+          tree->type = EX_VALUE;
+          tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
+                                           valFromType (RTYPE (tree)),
+                                           tree->opval.op);
+          tree->right = tree->left = NULL;
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                   tree->opval.val->type);
+          return tree;
+        }
       LRVAL (tree) = RRVAL (tree) = 1;
-      TTYPE (tree) = TETYPE (tree) = newCharLink ();
+      TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3375,92 +4048,226 @@ decorateType (ast * tree)
     case EQ_OP:
     case NE_OP:
       {
-       ast *lt = optimizeCompare (tree);
+        ast *lt = optimizeCompare (tree);
 
-       if (tree != lt)
-         return lt;
+        if (tree != lt)
+          return lt;
       }
 
       /* if they are pointers they must be castable */
       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
-       {
-         if (tree->opval.op==EQ_OP &&
-             !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
-           // we cannot cast a gptr to a !gptr: switch the leaves
-           struct ast *s=tree->left;
-           tree->left=tree->right;
-           tree->right=s;
-         }
-         if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
-           {
-             werror (E_COMPARE_OP);
-             fprintf (stderr, "comparring type ");
-             printTypeChain (LTYPE (tree), stderr);
-             fprintf (stderr, "to type ");
-             printTypeChain (RTYPE (tree), stderr);
-             fprintf (stderr, "\n");
-             goto errorTreeReturn;
-           }
-       }
+        {
+          if (tree->opval.op==EQ_OP &&
+              !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
+            // we cannot cast a gptr to a !gptr: switch the leaves
+            struct ast *s=tree->left;
+            tree->left=tree->right;
+            tree->right=s;
+          }
+          if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
+            {
+              werror (E_COMPARE_OP);
+              fprintf (stderr, "comparing type ");
+              printTypeChain (LTYPE (tree), stderr);
+              fprintf (stderr, "to type ");
+              printTypeChain (RTYPE (tree), stderr);
+              fprintf (stderr, "\n");
+              goto errorTreeReturn;
+            }
+        }
       /* else they should be promotable to one another */
       else
-       {
-         if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
-               (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
-
-           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
-             {
-               werror (E_COMPARE_OP);
-               fprintf (stderr, "comparing type ");
-               printTypeChain (LTYPE (tree), stderr);
-               fprintf (stderr, "to type ");
-               printTypeChain (RTYPE (tree), stderr);
-               fprintf (stderr, "\n");
-               goto errorTreeReturn;
-             }
-       }
-      /* if unsigned value < 0  then always false */
-      /* if (unsigned value) > 0 then (unsigned value) */
-      if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree))  && 
-         ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0) {
-
-         if (tree->opval.op == '<') {
-             return tree->right;
-         }
-         if (tree->opval.op == '>') {
-             return tree->left;
-         }
+        {
+          if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
+                (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
+
+            if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
+              {
+                werror (E_COMPARE_OP);
+                fprintf (stderr, "comparing type ");
+                printTypeChain (LTYPE (tree), stderr);
+                fprintf (stderr, "to type ");
+                printTypeChain (RTYPE (tree), stderr);
+                fprintf (stderr, "\n");
+                goto errorTreeReturn;
+              }
+        }
+
+      {
+        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)
+                  werror (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 (tree->opval.op == '>' &&
+          SPEC_USIGN(LETYPE(tree)) &&
+          IS_LITERAL(RTYPE(tree))  &&
+          ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
+        {
+          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;
+          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)
+        {
+          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)) &&
-         IS_LITERAL (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val = valCompare (valFromType (LETYPE (tree)),
-                                       valFromType (RETYPE (tree)),
-                                       tree->opval.op);
-         tree->right = tree->left = NULL;
-         TETYPE (tree) = getSpec (TTYPE (tree) =
-                                  tree->opval.val->type);
-         return tree;
-       }
+          IS_LITERAL (LTYPE (tree)))
+        {
+          tree->type = EX_VALUE;
+          tree->opval.val = valCompare (valFromType (LETYPE (tree)),
+                                        valFromType (RETYPE (tree)),
+                                        tree->opval.op);
+          tree->right = tree->left = NULL;
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                   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) floatFromVal (valFromType (RETYPE (tree))) < 128)
+            {
+              /* now we've got 2 'signed char'! */
+              SPEC_USIGN (RETYPE (tree)) = 0;
+            }
+                   /* same test for the left operand: */
+          else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
+              (int) floatFromVal (valFromType (LETYPE (tree))) < 128)
+            {
+              SPEC_USIGN (LETYPE (tree)) = 0;
+            }
+          else
+            {
+              werror (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) = newBoolLink ();
+
+      /* 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;
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /*             sizeof         */
       /*----------------------------*/
-    case SIZEOF:               /* evaluate wihout code generation */
+    case SIZEOF:                /* evaluate wihout code generation */
       /* 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);
+      }
       tree->type = EX_VALUE;
-      SNPRINTF(buffer, sizeof(buffer), "%d", (getSize (tree->right->ftype)));
       tree->opval.val = constVal (buffer);
       tree->right = tree->left = NULL;
       TETYPE (tree) = getSpec (TTYPE (tree) =
-                              tree->opval.val->type);
+                               tree->opval.val->type);
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3468,108 +4275,115 @@ decorateType (ast * tree)
       /*             typeof         */
       /*----------------------------*/
     case TYPEOF:
-       /* return typeof enum value */
-       tree->type = EX_VALUE;
-       {
-           int typeofv = 0;
-           if (IS_SPEC(tree->right->ftype)) {
-               switch (SPEC_NOUN(tree->right->ftype)) {
-               case V_INT:
-                   if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
-                   else typeofv = TYPEOF_INT;
-                   break;
-               case V_FLOAT:
-                   typeofv = TYPEOF_FLOAT;
-                   break;
-               case V_CHAR:
-                   typeofv = TYPEOF_CHAR;
-                   break;
-               case V_VOID:
-                   typeofv = TYPEOF_VOID;
-                   break;
-               case V_STRUCT:
-                   typeofv = TYPEOF_STRUCT;
-                   break;
-               case V_BITFIELD:
-                   typeofv = TYPEOF_BITFIELD;
-                   break;
-               case V_BIT:
-                   typeofv = TYPEOF_BIT;
-                   break;
-               case V_SBIT:
-                   typeofv = TYPEOF_SBIT;
-                   break;
-               default:
-                   break;
-               }
-           } else {
-               switch (DCL_TYPE(tree->right->ftype)) {
-               case POINTER:
-                   typeofv = TYPEOF_POINTER;
-                   break;
-               case FPOINTER:
-                   typeofv = TYPEOF_FPOINTER;
-                   break;
-               case CPOINTER:
-                   typeofv = TYPEOF_CPOINTER;
-                   break;
-               case GPOINTER:
-                   typeofv = TYPEOF_GPOINTER;
-                   break;
-               case PPOINTER:
-                   typeofv = TYPEOF_PPOINTER;
-                   break;
-               case IPOINTER:
-                   typeofv = TYPEOF_IPOINTER;
-                   break;
-               case ARRAY:
-                   typeofv = TYPEOF_ARRAY;
-                   break;
-               case FUNCTION:
-                   typeofv = TYPEOF_FUNCTION;
-                   break;
-               default:
-                   break;
-               }
-           }
-           SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
-           tree->opval.val = constVal (buffer);
-           tree->right = tree->left = NULL;
-           TETYPE (tree) = getSpec (TTYPE (tree) =
-                                    tree->opval.val->type);
-       }
-       return tree;
+        /* return typeof enum value */
+        tree->type = EX_VALUE;
+        {
+            int typeofv = 0;
+            if (IS_SPEC(tree->right->ftype)) {
+                switch (SPEC_NOUN(tree->right->ftype)) {
+                case V_INT:
+                    if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
+                    else typeofv = TYPEOF_INT;
+                    break;
+                case V_FLOAT:
+                    typeofv = TYPEOF_FLOAT;
+                    break;
+                case V_FIXED16X16:
+                    typeofv = TYPEOF_FIXED16X16;
+                    break;
+                case V_CHAR:
+                    typeofv = TYPEOF_CHAR;
+                    break;
+                case V_VOID:
+                    typeofv = TYPEOF_VOID;
+                    break;
+                case V_STRUCT:
+                    typeofv = TYPEOF_STRUCT;
+                    break;
+                case V_BITFIELD:
+                    typeofv = TYPEOF_BITFIELD;
+                    break;
+                case V_BIT:
+                    typeofv = TYPEOF_BIT;
+                    break;
+                case V_SBIT:
+                    typeofv = TYPEOF_SBIT;
+                    break;
+                default:
+                    break;
+                }
+            } else {
+                switch (DCL_TYPE(tree->right->ftype)) {
+                case POINTER:
+                    typeofv = TYPEOF_POINTER;
+                    break;
+                case FPOINTER:
+                    typeofv = TYPEOF_FPOINTER;
+                    break;
+                case CPOINTER:
+                    typeofv = TYPEOF_CPOINTER;
+                    break;
+                case GPOINTER:
+                    typeofv = TYPEOF_GPOINTER;
+                    break;
+                case PPOINTER:
+                    typeofv = TYPEOF_PPOINTER;
+                    break;
+                case IPOINTER:
+                    typeofv = TYPEOF_IPOINTER;
+                    break;
+                case ARRAY:
+                    typeofv = TYPEOF_ARRAY;
+                    break;
+                case FUNCTION:
+                    typeofv = TYPEOF_FUNCTION;
+                    break;
+                default:
+                    break;
+                }
+            }
+            SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
+            tree->opval.val = constVal (buffer);
+            tree->right = tree->left = NULL;
+            TETYPE (tree) = getSpec (TTYPE (tree) =
+                                     tree->opval.val->type);
+        }
+        return tree;
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /* conditional operator  '?'  */
       /*----------------------------*/
     case '?':
       /* the type is value of the colon operator (on the right) */
-      assert(IS_COLON_OP(tree->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 (IS_LITERAL (LTYPE(tree))) {    
-         if ( ((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) {
-             return decorateType(tree->right->left) ;
-         } else {
-             return decorateType(tree->right->right) ;
-         }
-      } else {
-         tree->right = decorateType(tree->right);
-         TTYPE (tree) = RTYPE(tree);
-         TETYPE (tree) = getSpec (TTYPE (tree));
-      }
+         but faster to do it here */
+      if (IS_LITERAL (LTYPE (tree)))
+        {
+          if (((int) floatFromVal (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;
 
     case ':':
       /* if they don't match we have a problem */
-      if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
-       {
-         werror (E_TYPE_MISMATCH, "conditional operator", " ");
-         goto errorTreeReturn;
-       }
+      if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
+          (compareType (RTYPE (tree), LTYPE (tree)) == 0))
+        {
+          werror (E_TYPE_MISMATCH, "conditional operator", " ");
+          goto errorTreeReturn;
+        }
 
-      TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree));
+      TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
+                                  resultType, tree->opval.op);
       TETYPE (tree) = getSpec (TTYPE (tree));
       return tree;
 
@@ -3583,22 +4397,22 @@ decorateType (ast * tree)
     case DIV_ASSIGN:
       /* for these it must be both must be integral */
       if (!IS_ARITHMETIC (LTYPE (tree)) ||
-         !IS_ARITHMETIC (RTYPE (tree)))
-       {
-         werror (E_OPS_INTEGRAL);
-         goto errorTreeReturn;
-       }
+          !IS_ARITHMETIC (RTYPE (tree)))
+        {
+          werror (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 ? "*=" : "/=");
+        werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
 
       if (LRVAL (tree))
-       {
-         werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+          goto errorTreeReturn;
+        }
       LLVAL (tree) = 1;
 
       return tree;
@@ -3610,22 +4424,22 @@ decorateType (ast * tree)
     case LEFT_ASSIGN:
       /* for these it must be both must be integral */
       if (!IS_INTEGRAL (LTYPE (tree)) ||
-         !IS_INTEGRAL (RTYPE (tree)))
-       {
-         werror (E_OPS_INTEGRAL);
-         goto errorTreeReturn;
-       }
+          !IS_INTEGRAL (RTYPE (tree)))
+        {
+          werror (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 <<=");
+        werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
 
       if (LRVAL (tree))
-       {
-         werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
+          goto errorTreeReturn;
+        }
       LLVAL (tree) = 1;
 
       return tree;
@@ -3636,31 +4450,33 @@ decorateType (ast * tree)
       /*----------------------------*/
     case SUB_ASSIGN:
       if (!(IS_PTR (LTYPE (tree)) ||
-           IS_ARITHMETIC (LTYPE (tree))))
-       {
-         werror (E_PLUS_INVALID, "-=");
-         goto errorTreeReturn;
-       }
+            IS_ARITHMETIC (LTYPE (tree))))
+        {
+          werror (E_PLUS_INVALID, "-=");
+          goto errorTreeReturn;
+        }
 
       if (!(IS_PTR (RTYPE (tree)) ||
-           IS_ARITHMETIC (RTYPE (tree))))
-       {
-         werror (E_PLUS_INVALID, "-=");
-         goto errorTreeReturn;
-       }
+            IS_ARITHMETIC (RTYPE (tree))))
+        {
+          werror (E_PLUS_INVALID, "-=");
+          goto errorTreeReturn;
+        }
       RRVAL (tree) = 1;
       TETYPE (tree) = getSpec (TTYPE (tree) =
-                              computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+                               computeType (LTYPE (tree),
+                                            RTYPE (tree),
+                                            RESULT_TYPE_NOPROM,
+                                            tree->opval.op));
 
       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
-       werror (E_CODE_WRITE, "-=");
+        werror (E_CODE_WRITE, "-=");
 
       if (LRVAL (tree))
-       {
-         werror (E_LVALUE_REQUIRED, "-=");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_LVALUE_REQUIRED, "-=");
+          goto errorTreeReturn;
+        }
       LLVAL (tree) = 1;
 
       return tree;
@@ -3673,37 +4489,39 @@ decorateType (ast * tree)
       /* this is not a unary operation */
       /* if both pointers then problem */
       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
-       {
-         werror (E_PTR_PLUS_PTR);
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_PTR_PLUS_PTR);
+          goto errorTreeReturn;
+        }
 
       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
-       {
-         werror (E_PLUS_INVALID, "+=");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_PLUS_INVALID, "+=");
+          goto errorTreeReturn;
+        }
 
       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
-       {
-         werror (E_PLUS_INVALID, "+=");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_PLUS_INVALID, "+=");
+          goto errorTreeReturn;
+        }
       RRVAL (tree) = 1;
       TETYPE (tree) = getSpec (TTYPE (tree) =
-                              computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+                               computeType (LTYPE (tree),
+                                            RTYPE (tree),
+                                            RESULT_TYPE_NOPROM,
+                                            tree->opval.op));
 
       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
-       werror (E_CODE_WRITE, "+=");
+        werror (E_CODE_WRITE, "+=");
 
       if (LRVAL (tree))
-       {
-         werror (E_LVALUE_REQUIRED, "+=");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_LVALUE_REQUIRED, "+=");
+          goto errorTreeReturn;
+        }
 
-      tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right));
+      tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
       tree->opval.op = '=';
 
       return tree;
@@ -3716,39 +4534,39 @@ decorateType (ast * tree)
     case '=':
       /* cannot be an aggregate */
       if (IS_AGGREGATE (LTYPE (tree)))
-       {
-         werror (E_AGGR_ASSIGN);
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_AGGR_ASSIGN);
+          goto errorTreeReturn;
+        }
 
       /* they should either match or be castable */
       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
-       {
-         werror (E_TYPE_MISMATCH, "assignment", " ");
-         printFromToType(RTYPE(tree),LTYPE(tree));
-       }
+        {
+          werror (E_TYPE_MISMATCH, "assignment", " ");
+          printFromToType(RTYPE(tree),LTYPE(tree));
+        }
 
       /* if the left side of the tree is of type void
          then report error */
       if (IS_VOID (LTYPE (tree)))
-       {
-         werror (E_CAST_ZERO);
-         printFromToType(RTYPE(tree), LTYPE(tree));
-       }
+        {
+          werror (E_CAST_ZERO);
+          printFromToType(RTYPE(tree), LTYPE(tree));
+        }
 
       TETYPE (tree) = getSpec (TTYPE (tree) =
-                              LTYPE (tree));
+                               LTYPE (tree));
       RRVAL (tree) = 1;
       LLVAL (tree) = 1;
       if (!tree->initMode ) {
         if (IS_CONSTANT(LTYPE(tree)))
-         werror (E_CODE_WRITE, "=");
+          werror (E_CODE_WRITE, "=");
       }
       if (LRVAL (tree))
-       {
-         werror (E_LVALUE_REQUIRED, "=");
-         goto errorTreeReturn;
-       }
+        {
+          werror (E_LVALUE_REQUIRED, "=");
+          goto errorTreeReturn;
+        }
 
       return tree;
 
@@ -3765,26 +4583,52 @@ decorateType (ast * tree)
       /*       function call        */
       /*----------------------------*/
     case CALL:
-      parmNumber = 1;
 
-      if (processParms (tree->left,
-                       FUNC_ARGS(tree->left->ftype),
-                       tree->right, &parmNumber, TRUE)) {
-       goto errorTreeReturn;
-      }
+      /* undo any explicit pointer derefernce; PCALL will handle it instead */
+      if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
+        {
+          if (tree->left->opval.op == '*' && !tree->left->right)
+            tree->left = tree->left->left;
+        }
 
-      if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) && 
-         !IFFUNC_ISBUILTIN(LTYPE(tree)))
-       {
-         reverseParms (tree->right);
-       }
+      /* require a function or pointer to function */
+      if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
+          goto errorTreeReturn;
+        }
 
-      if (IS_CODEPTR(LTYPE(tree))) {
-       TTYPE(tree) = LTYPE(tree)->next->next;
-      } else {
-       TTYPE(tree) = LTYPE(tree)->next;
-      }
-      TETYPE (tree) = getSpec (TTYPE (tree));
+      /* if there are parms, make sure that
+         parms are decorate / process / reverse only once */
+      if (!tree->right ||
+          !tree->right->decorated)
+        {
+          sym_link *functype;
+          parmNumber = 1;
+
+          if (IS_FUNCPTR (LTYPE (tree)))
+            {
+              functype = LTYPE (tree)->next;
+              processFuncPtrArgs (functype);
+            }
+          else
+            functype = LTYPE (tree);
+
+          if (processParms (tree->left, FUNC_ARGS(functype),
+                            &tree->right, &parmNumber, TRUE))
+            {
+              goto errorTreeReturn;
+            }
+
+          if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
+             !IFFUNC_ISBUILTIN(functype))
+            {
+              reverseParms (tree->right);
+            }
+
+           TTYPE (tree) = functype->next;
+           TETYPE (tree) = getSpec (TTYPE (tree));
+        }
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3793,31 +4637,32 @@ decorateType (ast * tree)
       /*----------------------------*/
     case RETURN:
       if (!tree->right)
-       goto voidcheck;
+        goto voidcheck;
 
       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
-       {
-         werror (W_RETURN_MISMATCH);
-         printFromToType (RTYPE(tree), currFunc->type->next);
-         goto errorTreeReturn;
-       }
+        {
+          werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
+          printFromToType (RTYPE(tree), currFunc->type->next);
+          goto errorTreeReturn;
+        }
 
       if (IS_VOID (currFunc->type->next)
-         && tree->right &&
-         !IS_VOID (RTYPE (tree)))
-       {
-         werror (E_FUNC_VOID);
-         goto errorTreeReturn;
-       }
-
-      /* if there is going to be a casing required then add it */
+          && tree->right &&
+          !IS_VOID (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
+          goto errorTreeReturn;
+        }
+
+      /* if there is going to be a casting required then add it */
       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
-       {
-         tree->right =
-           decorateType (newNode (CAST,
-                          newAst_LINK (copyLinkChain (currFunc->type->next)),
-                                  tree->right));
-       }
+        {
+          tree->right =
+            decorateType (newNode (CAST,
+                          newAst_LINK (copyLinkChain (currFunc->type->next)),
+                                        tree->right),
+                          RESULT_TYPE_NONE);
+        }
 
       RRVAL (tree) = 1;
       return tree;
@@ -3825,10 +4670,10 @@ decorateType (ast * tree)
     voidcheck:
 
       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
-       {
-         werror (W_VOID_FUNC, currFunc->name);
-         goto errorTreeReturn;
-       }
+        {
+          werror (W_VOID_FUNC, currFunc->name);
+          goto errorTreeReturn;
+        }
 
       TTYPE (tree) = TETYPE (tree) = NULL;
       return tree;
@@ -3840,10 +4685,10 @@ decorateType (ast * tree)
     case SWITCH:
       /* the switch value must be an integer */
       if (!IS_INTEGRAL (LTYPE (tree)))
-       {
-         werror (E_SWITCH_NON_INTEGER);
-         goto errorTreeReturn;
-       }
+        {
+          werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
+          goto errorTreeReturn;
+        }
       LRVAL (tree) = 1;
       TTYPE (tree) = TETYPE (tree) = NULL;
       return tree;
@@ -3854,8 +4699,8 @@ decorateType (ast * tree)
       /*----------------------------*/
     case IFX:
       tree->left = backPatchLabels (tree->left,
-                                   tree->trueLabel,
-                                   tree->falseLabel);
+                                    tree->trueLabel,
+                                    tree->falseLabel);
       TTYPE (tree) = TETYPE (tree) = NULL;
       return tree;
 
@@ -3865,29 +4710,37 @@ decorateType (ast * tree)
       /*----------------------------*/
     case FOR:
 
-      decorateType (resolveSymbols (AST_FOR (tree, initExpr)));
-      decorateType (resolveSymbols (AST_FOR (tree, condExpr)));
-      decorateType (resolveSymbols (AST_FOR (tree, loopExpr)));
+      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
          do */
       {
-       symbol *sym;
-       ast *init, *end;
-
-       if (isLoopReversible (tree, &sym, &init, &end))
-         return reverseLoop (tree, sym, init, end);
-       else
-         return decorateType (createFor (AST_FOR (tree, trueLabel),
-                                         AST_FOR (tree, continueLabel),
-                                         AST_FOR (tree, falseLabel),
-                                         AST_FOR (tree, condLabel),
-                                         AST_FOR (tree, initExpr),
-                                         AST_FOR (tree, condExpr),
-                                         AST_FOR (tree, loopExpr),
-                                         tree->left));
+        symbol *sym;
+        ast *init, *end;
+
+        if (isLoopReversible (tree, &sym, &init, &end))
+          return reverseLoop (tree, sym, init, end);
+        else
+          return decorateType (createFor (AST_FOR (tree, trueLabel),
+                                          AST_FOR (tree, continueLabel),
+                                          AST_FOR (tree, falseLabel),
+                                          AST_FOR (tree, condLabel),
+                                          AST_FOR (tree, initExpr),
+                                          AST_FOR (tree, condExpr),
+                                          AST_FOR (tree, loopExpr),
+                                          tree->left), RESULT_TYPE_NONE);
       }
+    case PARAM:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "node PARAM shouldn't be processed here");
+              /* but in processParams() */
+      return tree;
     default:
       TTYPE (tree) = TETYPE (tree) = NULL;
       return tree;
@@ -3909,12 +4762,15 @@ value *
 sizeofOp (sym_link * type)
 {
   char buff[10];
+  int size;
 
   /* make sure the type is complete and sane */
   checkTypeSanity(type, "(sizeof)");
 
   /* get the size and convert it to character  */
-  SNPRINTF (buff, sizeof(buff), "%d", getSize (type));
+  SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
+  if (!size && !IS_VOID(type))
+    werror (E_SIZEOF_INCOMPLETE_TYPE);
 
   /* now convert into value  */
   return constVal (buff);
@@ -3932,13 +4788,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;
 
@@ -3955,12 +4821,12 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
 
       /* if left is already a IFX then just change the if true label in that */
       if (!IS_IFX (tree->left))
-       tree->left = newIfxNode (tree->left, localLabel, falseLabel);
+        tree->left = newIfxNode (tree->left, localLabel, falseLabel);
 
       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
       /* right is a IFX then just join */
       if (IS_IFX (tree->right))
-       return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
+        return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
 
       tree->right = createLabel (localLabel, tree->right);
       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
@@ -3981,12 +4847,12 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
 
       /* if left is already a IFX then just change the if true label in that */
       if (!IS_IFX (tree->left))
-       tree->left = newIfxNode (tree->left, trueLabel, localLabel);
+        tree->left = newIfxNode (tree->left, trueLabel, localLabel);
 
       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
       /* right is a IFX then just join */
       if (IS_IFX (tree->right))
-       return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
+        return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
 
       tree->right = createLabel (localLabel, tree->right);
       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
@@ -3997,25 +4863,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->trueLabel = falseLabel;
-         tree->left->falseLabel = trueLabel;
-       }
+        {
+          tree->left = newNode (IFX, tree->left, NULL);
+          tree->left->trueLabel = falseLabel;
+          tree->left->falseLabel = trueLabel;
+        }
       return tree->left;
-    }
+     }
 
   if (IS_IFX (tree))
     {
@@ -4041,8 +4900,7 @@ createBlock (symbol * decl, ast * body)
 
   ex = newNode (BLOCK, NULL, body);
   ex->values.sym = decl;
-  
-  ex->right = ex->right;
+
   ex->level++;
   ex->lineno = 0;
   return ex;
@@ -4076,6 +4934,7 @@ createLabel (symbol * label, ast * stmnt)
   else
     addSym (LabelTab, label, name, label->level, 0, 0);
 
+  label->isitmp = 1;
   label->islbl = 1;
   label->key = labelKey++;
   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
@@ -4098,22 +4957,22 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
   /* then case is out of context            */
   if (!swStat)
     {
-      werror (E_CASE_CONTEXT);
+      werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
       return NULL;
     }
 
-  caseVal = decorateType (resolveSymbols (caseVal));
+  caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
   /* if not a constant then error  */
   if (!IS_LITERAL (caseVal->ftype))
     {
-      werror (E_CASE_CONSTANT);
+      werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
       return NULL;
     }
 
   /* if not a integer than error */
   if (!IS_INTEGRAL (caseVal->ftype))
     {
-      werror (E_CASE_NON_INTEGER);
+      werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
       return NULL;
     }
 
@@ -4126,38 +4985,44 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
       value *pval = NULL;
       int cVal = (int) floatFromVal (caseVal->opval.val);
       while (val && (int) floatFromVal (val) < cVal)
-       {
-         pval = val;
-         val = val->next;
-       }
+        {
+          pval = val;
+          val = val->next;
+        }
 
       /* if we reached the end then */
       if (!val)
-       {
-         pval->next = caseVal->opval.val;
-       }
+        {
+          pval->next = caseVal->opval.val;
+        }
+      else if ((int) floatFromVal (val) == cVal)
+        {
+          werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
+                    "case");
+          return NULL;
+        }
       else
-       {
-         /* we found a value greater than */
-         /* the current value we must add this */
-         /* before the value */
-         caseVal->opval.val->next = val;
-
-         /* if this was the first in chain */
-         if (swStat->values.switchVals.swVals == val)
-           swStat->values.switchVals.swVals =
-             caseVal->opval.val;
-         else
-           pval->next = caseVal->opval.val;
-       }
+        {
+          /* we found a value greater than */
+          /* the current value we must add this */
+          /* before the value */
+          caseVal->opval.val->next = val;
+
+          /* if this was the first in chain */
+          if (swStat->values.switchVals.swVals == val)
+            swStat->values.switchVals.swVals =
+              caseVal->opval.val;
+          else
+            pval->next = caseVal->opval.val;
+        }
 
     }
 
   /* create the case label   */
-  SNPRINTF(caseLbl, sizeof(caseLbl), 
-          "_case_%d_%d",
-          swStat->values.switchVals.swNum,
-          (int) floatFromVal (caseVal->opval.val));
+  SNPRINTF(caseLbl, sizeof(caseLbl),
+           "_case_%d_%d",
+           swStat->values.switchVals.swNum,
+           (int) floatFromVal (caseVal->opval.val));
 
   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
   rexpr->lineno = 0;
@@ -4168,7 +5033,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
 /* createDefault - creates the parse tree for the default statement */
 /*-----------------------------------------------------------------*/
 ast *
-createDefault (ast * swStat, ast * stmnt)
+createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
 {
   char defLbl[SDCC_NAME_MAX + 1];
 
@@ -4176,7 +5041,14 @@ createDefault (ast * swStat, ast * stmnt)
   /* then case is out of context            */
   if (!swStat)
     {
-      werror (E_CASE_CONTEXT);
+      werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
+      return NULL;
+    }
+
+  if (swStat->values.switchVals.swDefault)
+    {
+      werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
+                "default");
       return NULL;
     }
 
@@ -4185,7 +5057,7 @@ createDefault (ast * swStat, ast * stmnt)
 
   /* create the label  */
   SNPRINTF (defLbl, sizeof(defLbl),
-           "_default_%d", swStat->values.switchVals.swNum);
+            "_default_%d", swStat->values.switchVals.swNum);
   return createLabel (newSymbol (defLbl, 0), stmnt);
 }
 
@@ -4230,20 +5102,20 @@ createIf (ast * condAst, ast * ifBody, ast * elseBody)
   if (elseBody)
     {
       ifBody = newNode (NULLOP, ifBody,
-                       newNode (GOTO,
-                                newAst_VALUE (symbolVal (ifEnd)),
-                                NULL));
+                        newNode (GOTO,
+                                 newAst_VALUE (symbolVal (ifEnd)),
+                                 NULL));
       /* put the elseLabel on the else body */
       elseBody = createLabel (ifFalse, elseBody);
       /* out the end at the end of the body */
       elseBody = newNode (NULLOP,
-                         elseBody,
-                         createLabel (ifEnd, NULL));
+                          elseBody,
+                          createLabel (ifEnd, NULL));
     }
   else
     {
       ifBody = newNode (NULLOP, ifBody,
-                       createLabel (ifFalse, NULL));
+                        createLabel (ifFalse, NULL));
     }
   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
   if (IS_IFX (condAst))
@@ -4252,7 +5124,7 @@ createIf (ast * condAst, ast * ifBody, ast * elseBody)
     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
 
   return newNode (NULLOP, ifTree,
-                 newNode (NULLOP, ifBody, elseBody));
+                  newNode (NULLOP, ifBody, elseBody));
 
 }
 
@@ -4268,7 +5140,7 @@ createIf (ast * condAst, ast * ifBody, ast * elseBody)
 /*-----------------------------------------------------------------*/
 ast *
 createDo (symbol * trueLabel, symbol * continueLabel,
-         symbol * falseLabel, ast * condAst, ast * doBody)
+          symbol * falseLabel, ast * condAst, ast * doBody)
 {
   ast *doTree;
 
@@ -4278,7 +5150,7 @@ createDo (symbol * trueLabel, symbol * continueLabel,
     {
       condAst = backPatchLabels (condAst, continueLabel, NULL);
       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
-               : newNode (IFX, createLabel (continueLabel, condAst), NULL));
+                : newNode (IFX, createLabel (continueLabel, condAst), NULL));
       doTree->trueLabel = continueLabel;
       doTree->falseLabel = NULL;
       return doTree;
@@ -4291,7 +5163,7 @@ createDo (symbol * trueLabel, symbol * continueLabel,
   doBody = createLabel (trueLabel, doBody);
   /* attach the continue label to end of body */
   doBody = newNode (NULLOP, doBody,
-                   createLabel (continueLabel, NULL));
+                    createLabel (continueLabel, NULL));
 
   /* now put the break label at the end */
   if (IS_IFX (condAst))
@@ -4321,9 +5193,9 @@ createDo (symbol * trueLabel, symbol * continueLabel,
 /*-----------------------------------------------------------------*/
 ast *
 createFor (symbol * trueLabel, symbol * continueLabel,
-          symbol * falseLabel, symbol * condLabel,
-          ast * initExpr, ast * condExpr, ast * loopExpr,
-          ast * forBody)
+           symbol * falseLabel, symbol * condLabel,
+           ast * initExpr, ast * condExpr, ast * loopExpr,
+           ast * forBody)
 {
   ast *forTree;
 
@@ -4331,8 +5203,8 @@ createFor (symbol * trueLabel, symbol * continueLabel,
   /* the same way as a while */
   if (!loopExpr)
     return newNode (NULLOP, initExpr,
-                   createWhile (trueLabel, continueLabel,
-                                falseLabel, condExpr, forBody));
+                    createWhile (trueLabel, continueLabel,
+                                 falseLabel, condExpr, forBody));
   /* vanilla for statement */
   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
 
@@ -4349,18 +5221,18 @@ createFor (symbol * trueLabel, symbol * continueLabel,
   /* attach continue to forLoop expression & attach */
   /* goto the forcond @ and of loopExpression       */
   loopExpr = createLabel (continueLabel,
-                         newNode (NULLOP,
-                                  loopExpr,
-                                  newNode (GOTO,
-                                      newAst_VALUE (symbolVal (condLabel)),
-                                           NULL)));
+                          newNode (NULLOP,
+                                   loopExpr,
+                                   newNode (GOTO,
+                                       newAst_VALUE (symbolVal (condLabel)),
+                                            NULL)));
   /* now start putting them together */
   forTree = newNode (NULLOP, initExpr, condExpr);
   forTree = newNode (NULLOP, forTree, forBody);
   forTree = newNode (NULLOP, forTree, loopExpr);
   /* finally add the break label */
   forTree = newNode (NULLOP, forTree,
-                    createLabel (falseLabel, NULL));
+                     createLabel (falseLabel, NULL));
   return forTree;
 }
 
@@ -4379,7 +5251,7 @@ createFor (symbol * trueLabel, symbol * continueLabel,
 /*-----------------------------------------------------------------*/
 ast *
 createWhile (symbol * trueLabel, symbol * continueLabel,
-            symbol * falseLabel, ast * condExpr, ast * whileBody)
+             symbol * falseLabel, ast * condExpr, ast * whileBody)
 {
   ast *whileTree;
 
@@ -4394,10 +5266,10 @@ createWhile (symbol * trueLabel, symbol * continueLabel,
   /* put a jump to continue at the end of the body */
   /* and put break label at the end of the body */
   whileBody = newNode (NULLOP,
-                      whileBody,
-                      newNode (GOTO,
-                               newAst_VALUE (symbolVal (continueLabel)),
-                               createLabel (falseLabel, NULL)));
+                       whileBody,
+                       newNode (GOTO,
+                                newAst_VALUE (symbolVal (continueLabel)),
+                                createLabel (falseLabel, NULL)));
 
   /* put it all together */
   if (IS_IFX (condExpr))
@@ -4414,41 +5286,194 @@ createWhile (symbol * trueLabel, symbol * continueLabel,
 }
 
 /*-----------------------------------------------------------------*/
-/* optimizeGetHbit - get highest order bit of the expression       */
+/* isShiftRightLitVal _BitAndLitVal - helper function              */
 /*-----------------------------------------------------------------*/
-ast *
-optimizeGetHbit (ast * tree)
+static ast *
+isShiftRightLitVal_BitAndLitVal (ast * tree)
 {
-  int i, j;
   /* if this is not a bit and */
   if (!IS_BITAND (tree))
-    return tree;
+    return NULL;
+
+  /* will look for tree of the form
+     ( expr >> litval2) & litval1 */
+  if (!IS_AST_LIT_VALUE (tree->right))
+    return NULL;
+
+  if (!IS_RIGHT_OP (tree->left))
+    return NULL;
+
+  if (!IS_AST_LIT_VALUE (tree->left->right))
+    return NULL;
+
+  return tree->left->left;
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitAndPowOf2 - helper function                                */
+/*-----------------------------------------------------------------*/
+static int
+isBitAndPow2 (ast * tree)
+{
+  /* if this is not a bit and */
+  if (!IS_BITAND (tree))
+    return -1;
 
   /* will look for tree of the form
-     ( expr >> ((sizeof expr) -1) ) & 1 */
+     ( expr & (1 << litval) */
   if (!IS_AST_LIT_VALUE (tree->right))
+    return -1;
+
+  return powof2 ((TYPE_TARGET_ULONG)AST_LIT_VALUE (tree->right));
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetHbit - get highest order bit of the expression       */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
+{
+  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)) !=
+          (j = (getSize (TTYPE (expr)) * 8 - 1))))
+        expr = NULL;
+    }
+  if (!expr && (resultType == RESULT_TYPE_BIT))
+    {
+      expr = tree->left;
+      if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
+        expr = NULL;
+    }
+  if (!expr)
     return tree;
 
-  if (AST_LIT_VALUE (tree->right) != 1)
+  /* make sure the port supports GETHBIT */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
     return tree;
 
-  if (!IS_RIGHT_OP (tree->left))
+  return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetAbit - get a single bit of the expression            */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
+{
+  ast * expr;
+  ast * count = NULL;
+
+  expr = isShiftRightLitVal_BitAndLitVal(tree);
+  if (expr)
+    {
+  if (AST_LIT_VALUE (tree->right) != 1)
+        expr = NULL;
+      count = tree->left->right;
+    }
+  if (!expr && (resultType == RESULT_TYPE_BIT))
+    {
+      int p2 = isBitAndPow2 (tree);
+      if (p2 >= 0)
+        {
+          expr = tree->left;
+          count = newAst_VALUE (valueFromLit (p2));
+        }
+    }
+  if (!expr)
     return tree;
 
-  if (!IS_AST_LIT_VALUE (tree->left->right))
+  /* make sure the port supports GETABIT */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
     return tree;
 
-  if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
-      (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
+  return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetByte - get a byte of the expression                  */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetByte (ast * tree, RESULT_TYPE resultType)
+{
+  unsigned int i = 0;
+  ast * expr;
+  ast * count = NULL;
+
+  expr = isShiftRightLitVal_BitAndLitVal(tree);
+  if (expr)
+    {
+      i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+      count = tree->left->right;
+      if (AST_LIT_VALUE (tree->right) != 0xFF)
+        expr = NULL;
+    }
+  if (!expr && resultType == RESULT_TYPE_CHAR)
+    {
+      /* 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);
+          count = tree->right;
+            expr = tree->left;
+        }
+    }
+  if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
     return tree;
-      
-  /* make sure the port supports GETHBIT */
+
+  /* make sure the port supports GETBYTE */
   if (port->hasExtBitOp
-      && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
+      && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
+    return tree;
+
+  return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetWord - get two bytes of the expression               */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetWord (ast * tree, RESULT_TYPE resultType)
+{
+  unsigned int i = 0;
+  ast * expr;
+  ast * count = NULL;
+
+  expr = isShiftRightLitVal_BitAndLitVal(tree);
+  if (expr)
+    {
+      i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+      count = tree->left->right;
+      if (AST_LIT_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);
+          count = tree->right;
+            expr = tree->left;
+        }
+    }
+  if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
     return tree;
 
-  return decorateType (newNode (GETHBIT, tree->left->left, NULL));
+  /* make sure the port supports GETWORD */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
+    return tree;
 
+  return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -4467,12 +5492,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) &&
@@ -4480,23 +5505,23 @@ optimizeRRCRLC (ast * root)
     {
 
       if (!SPEC_USIGN (TETYPE (root->left->left)))
-       return root;
+        return root;
 
       if (!IS_AST_LIT_VALUE (root->left->right) ||
-         !IS_AST_LIT_VALUE (root->right->right))
-       goto tryNext0;
+          !IS_AST_LIT_VALUE (root->right->right))
+        goto tryNext0;
 
       /* make sure it is the same expression */
       if (!isAstEqual (root->left->left,
-                      root->right->left))
-       goto tryNext0;
+                       root->right->left))
+        goto tryNext0;
 
       if (AST_LIT_VALUE (root->left->right) != 1)
-       goto tryNext0;
+        goto tryNext0;
 
       if (AST_LIT_VALUE (root->right->right) !=
-         (getSize (TTYPE (root->left->left)) * 8 - 1))
-       goto tryNext0;
+          (getSize (TTYPE (root->left->left)) * 8 - 1))
+        goto tryNext0;
 
       /* make sure the port supports RLC */
       if (port->hasExtBitOp
@@ -4515,23 +5540,23 @@ tryNext0:
     {
 
       if (!SPEC_USIGN (TETYPE (root->left->left)))
-       return root;
+        return root;
 
       if (!IS_AST_LIT_VALUE (root->left->right) ||
-         !IS_AST_LIT_VALUE (root->right->right))
-       goto tryNext1;
+          !IS_AST_LIT_VALUE (root->right->right))
+        goto tryNext1;
 
       /* make sure it is the same symbol */
       if (!isAstEqual (root->left->left,
-                      root->right->left))
-       goto tryNext1;
+                       root->right->left))
+        goto tryNext1;
 
       if (AST_LIT_VALUE (root->right->right) != 1)
-       goto tryNext1;
+        goto tryNext1;
 
       if (AST_LIT_VALUE (root->left->right) !=
-         (getSize (TTYPE (root->left->left)) * 8 - 1))
-       goto tryNext1;
+          (getSize (TTYPE (root->left->left)) * 8 - 1))
+        goto tryNext1;
 
       /* make sure the port supports RLC */
       if (port->hasExtBitOp
@@ -4551,23 +5576,23 @@ tryNext1:
     {
 
       if (!SPEC_USIGN (TETYPE (root->left->left)))
-       return root;
+        return root;
 
       if (!IS_AST_LIT_VALUE (root->left->right) ||
-         !IS_AST_LIT_VALUE (root->right->right))
-       goto tryNext2;
+          !IS_AST_LIT_VALUE (root->right->right))
+        goto tryNext2;
 
       /* make sure it is the same symbol */
       if (!isAstEqual (root->left->left,
-                      root->right->left))
-       goto tryNext2;
+                       root->right->left))
+        goto tryNext2;
 
       if (AST_LIT_VALUE (root->left->right) != 1)
-       goto tryNext2;
+        goto tryNext2;
 
       if (AST_LIT_VALUE (root->right->right) !=
-         (getSize (TTYPE (root->left->left)) * 8 - 1))
-       goto tryNext2;
+          (getSize (TTYPE (root->left->left)) * 8 - 1))
+        goto tryNext2;
 
       /* make sure the port supports RRC */
       if (port->hasExtBitOp
@@ -4586,23 +5611,23 @@ tryNext2:
     {
 
       if (!SPEC_USIGN (TETYPE (root->left->left)))
-       return root;
+        return root;
 
       if (!IS_AST_LIT_VALUE (root->left->right) ||
-         !IS_AST_LIT_VALUE (root->right->right))
-       return root;
+          !IS_AST_LIT_VALUE (root->right->right))
+        return root;
 
       /* make sure it is the same symbol */
       if (!isAstEqual (root->left->left,
-                      root->right->left))
-       return root;
+                       root->right->left))
+        return root;
 
       if (AST_LIT_VALUE (root->right->right) != 1)
-       return root;
+        return root;
 
       if (AST_LIT_VALUE (root->left->right) !=
-         (getSize (TTYPE (root->left->left)) * 8 - 1))
-       return root;
+          (getSize (TTYPE (root->left->left)) * 8 - 1))
+        return root;
 
       /* make sure the port supports RRC */
       if (port->hasExtBitOp
@@ -4630,7 +5655,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;
 
@@ -4640,24 +5665,24 @@ optimizeSWAP (ast * root)
     {
 
       if (!SPEC_USIGN (TETYPE (root->left->left)))
-       return root;
+        return root;
 
       if (!IS_AST_LIT_VALUE (root->left->right) ||
-         !IS_AST_LIT_VALUE (root->right->right))
-       return root;
+          !IS_AST_LIT_VALUE (root->right->right))
+        return root;
 
       /* make sure it is the same expression */
       if (!isAstEqual (root->left->left,
-                      root->right->left))
-       return root;
+                       root->right->left))
+        return root;
 
       if (AST_LIT_VALUE (root->left->right) !=
-         (getSize (TTYPE (root->left->left)) * 4))
-       return root;
+          (getSize (TTYPE (root->left->left)) * 4))
+        return root;
 
       if (AST_LIT_VALUE (root->right->right) !=
-         (getSize (TTYPE (root->left->left)) * 4))
-       return root;
+          (getSize (TTYPE (root->left->left)) * 4))
+        return root;
 
       /* make sure the port supports SWAP */
       if (port->hasExtBitOp
@@ -4674,7 +5699,7 @@ optimizeSWAP (ast * root)
 }
 
 /*-----------------------------------------------------------------*/
-/* optimizeCompare - otimizes compares for bit variables     */
+/* optimizeCompare - optimizes compares for bit variables          */
 /*-----------------------------------------------------------------*/
 static ast *
 optimizeCompare (ast * root)
@@ -4701,27 +5726,27 @@ optimizeCompare (ast * root)
   if (isAstEqual (root->left, root->right))
     {
       switch (root->opval.op)
-       {
-       case '>':
-       case '<':
-       case NE_OP:
-         optExpr = newAst_VALUE (constVal ("0"));
-         break;
-       case GE_OP:
-       case LE_OP:
-       case EQ_OP:
-         optExpr = newAst_VALUE (constVal ("1"));
-         break;
-       }
-
-      return decorateType (optExpr);
+        {
+        case '>':
+        case '<':
+        case NE_OP:
+          optExpr = newAst_VALUE (constVal ("0"));
+          break;
+        case GE_OP:
+        case LE_OP:
+        case EQ_OP:
+          optExpr = newAst_VALUE (constVal ("1"));
+          break;
+        }
+
+      return decorateType (optExpr, RESULT_TYPE_NONE);
     }
 
   vleft = (root->left->type == EX_VALUE ?
-          root->left->opval.val : NULL);
+           root->left->opval.val : NULL);
 
   vright = (root->right->type == EX_VALUE ?
-           root->right->opval.val : NULL);
+            root->right->opval.val : NULL);
 
   /* if left is a BITVAR in BITSPACE */
   /* and right is a LITERAL then opt- */
@@ -4734,62 +5759,62 @@ optimizeCompare (ast * root)
 
       /* if right side > 1 then comparison may never succeed */
       if ((litValue = (int) floatFromVal (vright)) > 1)
-       {
-         werror (W_BAD_COMPARE);
-         goto noOptimize;
-       }
+        {
+          werror (W_BAD_COMPARE);
+          goto noOptimize;
+        }
 
       if (litValue)
-       {
-         switch (root->opval.op)
-           {
-           case '>':           /* bit value greater than 1 cannot be */
-             werror (W_BAD_COMPARE);
-             goto noOptimize;
-             break;
-
-           case '<':           /* bit value < 1 means 0 */
-           case NE_OP:
-             optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
-             break;
-
-           case LE_OP: /* bit value <= 1 means no check */
-             optExpr = newAst_VALUE (vright);
-             break;
-
-           case GE_OP: /* bit value >= 1 means only check for = */
-           case EQ_OP:
-             optExpr = newAst_VALUE (vleft);
-             break;
-           }
-       }
+        {
+          switch (root->opval.op)
+            {
+            case '>':           /* bit value greater than 1 cannot be */
+              werror (W_BAD_COMPARE);
+              goto noOptimize;
+              break;
+
+            case '<':           /* bit value < 1 means 0 */
+            case NE_OP:
+              optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
+              break;
+
+            case LE_OP: /* bit value <= 1 means no check */
+              optExpr = newAst_VALUE (vright);
+              break;
+
+            case GE_OP: /* bit value >= 1 means only check for = */
+            case EQ_OP:
+              optExpr = newAst_VALUE (vleft);
+              break;
+            }
+        }
       else
-       {                       /* literal is zero */
-         switch (root->opval.op)
-           {
-           case '<':           /* bit value < 0 cannot be */
-             werror (W_BAD_COMPARE);
-             goto noOptimize;
-             break;
-
-           case '>':           /* bit value > 0 means 1 */
-           case NE_OP:
-             optExpr = newAst_VALUE (vleft);
-             break;
-
-           case LE_OP: /* bit value <= 0 means no check */
-           case GE_OP: /* bit value >= 0 means no check */
-             werror (W_BAD_COMPARE);
-             goto noOptimize;
-             break;
-
-           case EQ_OP: /* bit == 0 means ! of bit */
-             optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
-             break;
-           }
-       }
-      return decorateType (resolveSymbols (optExpr));
-    }                          /* end-of-if of BITVAR */
+        {                       /* literal is zero */
+          switch (root->opval.op)
+            {
+            case '<':           /* bit value < 0 cannot be */
+              werror (W_BAD_COMPARE);
+              goto noOptimize;
+              break;
+
+            case '>':           /* bit value > 0 means 1 */
+            case NE_OP:
+              optExpr = newAst_VALUE (vleft);
+              break;
+
+            case LE_OP: /* bit value <= 0 means no check */
+            case GE_OP: /* bit value >= 0 means no check */
+              werror (W_BAD_COMPARE);
+              goto noOptimize;
+              break;
+
+            case EQ_OP: /* bit == 0 means ! of bit */
+              optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
+              break;
+            }
+        }
+      return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
+    }                           /* end-of-if of BITVAR */
 
 noOptimize:
   return root;
@@ -4797,7 +5822,7 @@ noOptimize:
 /*-----------------------------------------------------------------*/
 /* addSymToBlock : adds the symbol to the first block we find      */
 /*-----------------------------------------------------------------*/
-void 
+void
 addSymToBlock (symbol * sym, ast * tree)
 {
   /* reached end of tree or a leaf */
@@ -4823,13 +5848,13 @@ addSymToBlock (symbol * sym, ast * tree)
 /*-----------------------------------------------------------------*/
 /* processRegParms - do processing for register parameters         */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 processRegParms (value * args, ast * body)
 {
   while (args)
     {
       if (IS_REGPARM (args->etype))
-       addSymToBlock (args->sym, body);
+        addSymToBlock (args->sym, body);
       args = args->next;
     }
 }
@@ -4885,34 +5910,39 @@ createFunction (symbol * name, ast * body)
          actually means we are now compiling the compiler
          support routine */
       if (name->cdef)
-       {
-         addSet (&publics, name);
-       }
+        {
+          addSet (&publics, name);
+        }
     }
   else
     {
-      addSymChain (name);
+      addSymChain (&name);
       allocVariables (name);
     }
   name->lastLine = mylineno;
   currFunc = name;
 
   /* set the stack pointer */
-  /* PENDING: check this for the mcs51 */
-  stackPtr = -port->stack.direction * port->stack.call_overhead;
+  stackPtr  = -port->stack.direction * port->stack.call_overhead;
+  xstackPtr = 0;
+
   if (IFFUNC_ISISR (name->type))
     stackPtr -= port->stack.direction * port->stack.isr_overhead;
-  if (IFFUNC_ISREENT (name->type) || options.stackAuto)
-    stackPtr -= port->stack.direction * port->stack.reent_overhead;
 
-  xstackPtr = -port->stack.direction * port->stack.call_overhead;
+  if (IFFUNC_ISREENT (name->type) || options.stackAuto)
+    {
+      if (options.useXstack)
+        xstackPtr -= port->stack.direction * port->stack.reent_overhead;
+      else
+        stackPtr  -= port->stack.direction * port->stack.reent_overhead;
+    }
 
-  fetype = getSpec (name->type);       /* get the specifier for the function */
+  fetype = getSpec (name->type);        /* get the specifier for the function */
   /* if this is a reentrant function then */
   if (IFFUNC_ISREENT (name->type))
     reentrant++;
 
-  allocParms (FUNC_ARGS(name->type));  /* allocate the parameters */
+  allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
 
   /* do processing for parameters that are passed in registers */
   processRegParms (FUNC_ARGS(name->type), body);
@@ -4921,22 +5951,24 @@ 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);
 
+  /* 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;
 
-  /* 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);  /* propagateType & do semantic checks */
-
-  ex = newAst_VALUE (symbolVal (name));        /* create name */
+  ex = newAst_VALUE (symbolVal (name)); /* create name */
   ex = newNode (FUNCTION, ex, body);
   ex->values.args = FUNC_ARGS(name->type);
   ex->decorated=1;
@@ -4965,7 +5997,7 @@ createFunction (symbol * name, ast * body)
     {
       GcurMemmap = statsg;
       codeOutFile = statsg->oFile;
-      eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos))));
+      eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
       staticAutos = NULL;
     }
 
@@ -5009,697 +6041,718 @@ 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);
-
-       /*------------------------------------------------------------------*/
-       /*----------------------------*/
-       /*   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, %g", (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;
-               /*------------------------------------------------------------------*/
-               /*----------------------------*/
-               /*    compliment              */
-               /*----------------------------*/
-       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 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 ;
-       }
+        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);
+
+        /*------------------------------------------------------------------*/
+        /*----------------------------*/
+        /*   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) floatFromVal(tree->opval.val));
+                        else
+                                fprintf(outfile,"%d", (TYPE_TARGET_LONG) floatFromVal(tree->opval.val));
+                        fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) floatFromVal(tree->opval.val),
+                                                      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) 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 ;
+        }
 }
 
 void PA(ast *t)
 {
-       ast_print(t,stdout,0);
+        ast_print(t,stdout,0);
 }
 
 
@@ -5710,12 +6763,12 @@ void PA(ast *t)
 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)
@@ -5724,6 +6777,6 @@ int astErrors(ast *t)
       errors += astErrors(t->left);
       errors += astErrors(t->right);
     }
-    
+
   return errors;
 }