* fixed GCC 4.4.0 mingw compilation:
[fw/sdcc] / src / SDCCast.c
index d9f4eed75d346596e4c31994bb92941163f47ec8..391408318222ae2d9a396d048770554239edceaf 100644 (file)
    what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
+#define DEBUG_CF(x) /* puts(x); */
+
 #include "common.h"
-#include "newalloc.h"
 
-int currLineno  = 0;
-set *astList = NULL ;
+int currLineno = 0;
+set *astList = NULL;
 set *operKeyReset = NULL;
 ast *staticAutos = NULL;
-int labelKey = 1 ;
+int labelKey = 1;
+static struct {
+  int count;            /* number of inline functions inserted */
+  symbol * retsym;      /* variable for inlined function return value */
+  symbol * retlab;      /* label ending inlined function (virtual return) */
+} inlineState;
 
 #define LRVAL(x) x->left->rvalue
 #define RRVAL(x) x->right->rvalue
@@ -46,178 +52,158 @@ int labelKey = 1 ;
 #define ALLOCATE 1
 #define DEALLOCATE 2
 
-char  buffer[1024];
 int noLineno = 0;
-int noAlloc = 0 ;
-symbol *currFunc ;
-ast  *createIval  (ast *, sym_link *, initList *, ast *);
-ast *createIvalCharPtr (ast *, sym_link *, ast *);
-ast *optimizeRRCRLC ( ast * );
-ast *optimizeGetHbit(ast *);
-ast *backPatchLabels (ast *,symbol *,symbol *);
-int  inInitMode = 0;
-FILE *codeOutFile ;
-int ptt(ast *tree) {
-    printTypeChain(tree->ftype,stdout);
-    return 0;
+int noAlloc = 0;
+symbol *currFunc=NULL;
+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 *, 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 */
+struct dbuf_s *codeOutBuf;
+int
+ptt (ast * tree)
+{
+  printTypeChain (tree->ftype, stdout);
+  return 0;
 }
 
 
 /*-----------------------------------------------------------------*/
-/* newAst - creates a fresh node for an expression tree           */
+/* newAst - creates a fresh node for an expression tree            */
 /*-----------------------------------------------------------------*/
-#if 0
-ast  *newAst (int  type, void *op )
-{
-    ast  *ex ;
-    static int oldLineno = 0 ;
-
-    Safe_calloc(1,ex,sizeof(ast));
-
-    ex->type = type ;
-    ex->lineno = (noLineno ? oldLineno : yylineno);
-    ex->filename = currFname ;
-    ex->level = NestLevel ;
-    ex->block = currBlockno ;
-    ex->initMode = inInitMode;
-
-    /* depending on the type */
-    switch (type)   {
-    case  EX_VALUE :
-  ex->opval.val = (value *) op;
-  break ;
-    case EX_OP     :
-  ex->opval.op   = (long) op ;
-  break ;
-    case EX_LINK   :
-  ex->opval.lnk  = (sym_link *) op;
-  break ;
-    case EX_STMNT  :
-  ex->opval.stmnt= (unsigned) op;
-    }
-
-    return ex;
-}
-#endif
-
-static ast* newAst_(unsigned type)
-{
-    ast  *ex ;
-    static int oldLineno = 0 ;
-
-    ex = Safe_calloc(1,sizeof(ast));
-
-    ex->type = type ;
-    ex->lineno = (noLineno ? oldLineno : yylineno);
-    ex->filename = currFname ;
-    ex->level = NestLevel ;
-    ex->block = currBlockno ;
-    ex->initMode = inInitMode;
-    return ex;
-}
-
-ast* newAst_VALUE(value*val)
+static ast *
+newAst_ (unsigned type)
 {
-      ast* ex = newAst_(EX_VALUE);
-      ex->opval.val = val;
-      return ex;
+  ast *ex;
+
+  ex = Safe_alloc ( sizeof (ast));
+
+  ex->type = type;
+  ex->lineno = (noLineno ? 0 : lexLineno);
+  ex->filename = lexFilename;
+  ex->level = NestLevel;
+  ex->block = currBlockno;
+  ex->initMode = inInitMode;
+  ex->seqPoint = seqPointNo;
+  return ex;
 }
 
-ast* newAst_OP(unsigned op)
+ast *
+newAst_VALUE (value * val)
 {
-      ast*ex = newAst_(EX_OP);
-      ex->opval.op = op;
-      return ex;
+  ast *ex = newAst_ (EX_VALUE);
+  ex->opval.val = val;
+  return ex;
 }
 
-ast* newAst_LINK(sym_link*val)
+ast *
+newAst_OP (unsigned op)
 {
-      ast* ex = newAst_(EX_LINK);
-      ex->opval.lnk = val;
-      return ex;
+  ast *ex = newAst_ (EX_OP);
+  ex->opval.op = op;
+  return ex;
 }
 
-ast* newAst_STMNT(unsigned val)
+ast *
+newAst_LINK (sym_link * val)
 {
-      ast* ex = newAst_(EX_STMNT);
-      ex->opval.stmnt = val;
-      return ex;
+  ast *ex = newAst_ (EX_LINK);
+  ex->opval.lnk = val;
+  return ex;
 }
 
 /*-----------------------------------------------------------------*/
 /* newNode - creates a new node                                    */
 /*-----------------------------------------------------------------*/
-ast  *newNode ( long op,   ast  *left, ast *right   )
+ast *
+newNode (long op, ast * left, ast * right)
 {
-    ast  *ex ;
+  ast *ex;
 
-    ex = newAst_OP(op) ;
-    ex->left    = left ;
-    ex->right   = right;
+  ex = newAst_OP (op);
+  ex->left = left;
+  ex->right = right;
 
-    return ex ;
+  return ex;
 }
 
 /*-----------------------------------------------------------------*/
 /* newIfxNode - creates a new Ifx Node                             */
 /*-----------------------------------------------------------------*/
-ast *newIfxNode (ast *condAst, symbol *trueLabel, symbol *falseLabel)
+ast *
+newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
 {
-    ast *ifxNode ;
-
-    /* if this is a literal then we already know the result */
-    if (condAst->etype && IS_LITERAL(condAst->etype)) {
+  ast *ifxNode;
 
-  /* then depending on the expression value */
-  if ( floatFromVal(condAst->opval.val) )
-        ifxNode = newNode(GOTO,
-        newAst_VALUE(symbolVal(trueLabel)),
-        NULL);
-  else
-        ifxNode = newNode(GOTO,
-        newAst_VALUE(symbolVal(falseLabel)),
-        NULL);
+  /* if this is a literal then we already know the result */
+  if (condAst->etype && IS_LITERAL (condAst->etype))
+    {
+      /* then depending on the expression value */
+      if (floatFromVal (condAst->opval.val))
+        ifxNode = newNode (GOTO,
+                           newAst_VALUE (symbolVal (trueLabel)),
+                           NULL);
+      else
+        ifxNode = newNode (GOTO,
+                           newAst_VALUE (symbolVal (falseLabel)),
+                           NULL);
     }
-    else {
-  ifxNode = newNode(IFX,condAst,NULL);
-  ifxNode->trueLabel = trueLabel;
-  ifxNode->falseLabel= falseLabel;
+  else
+    {
+      ifxNode = newNode (IFX, condAst, NULL);
+      ifxNode->trueLabel = trueLabel;
+      ifxNode->falseLabel = falseLabel;
     }
 
-    return ifxNode ;
+  return ifxNode;
 }
 
 /*-----------------------------------------------------------------*/
-/* copyAstValues - copies value portion of ast if needed     */
+/* copyAstValues - copies value portion of ast if needed           */
 /*-----------------------------------------------------------------*/
-void copyAstValues (ast *dest,ast *src)
+void
+copyAstValues (ast * dest, ast * src)
 {
-    switch (src->opval.op) {
+  switch (src->opval.op)
+    {
     case BLOCK:
-  dest->values.sym     = copySymbolChain(src->values.sym);
-  break;
+      dest->values.sym = copySymbolChain (src->values.sym);
+      break;
 
     case SWITCH:
-  dest->values.switchVals.swVals =
-      copyValue(src->values.switchVals.swVals);
-  dest->values.switchVals.swDefault =
-      src->values.switchVals.swDefault ;
-  dest->values.switchVals.swNum  =
-      src->values.switchVals.swNum ;
-  break ;
+      dest->values.switchVals.swVals =
+        copyValue (src->values.switchVals.swVals);
+      dest->values.switchVals.swDefault =
+        src->values.switchVals.swDefault;
+      dest->values.switchVals.swNum =
+        src->values.switchVals.swNum;
+      break;
 
     case INLINEASM:
-  dest->values.inlineasm = Safe_calloc(1,strlen(src->values.inlineasm)+1);
-  strcpy(dest->values.inlineasm,src->values.inlineasm);
+      dest->values.inlineasm =  Safe_strdup(src->values.inlineasm);
+      break;
+
+    case ARRAYINIT:
+        dest->values.constlist = copyLiteralList(src->values.constlist);
+        break;
 
     case FOR:
-   AST_FOR(dest,trueLabel) = copySymbol(AST_FOR(src,trueLabel));
-   AST_FOR(dest,continueLabel) = copySymbol(AST_FOR(src,continueLabel));
-   AST_FOR(dest,falseLabel) =  copySymbol(AST_FOR(src,falseLabel));
-   AST_FOR(dest,condLabel)  =  copySymbol(AST_FOR(src,condLabel));
-   AST_FOR(dest,initExpr)   =  copyAst (AST_FOR(src,initExpr)) ;
-   AST_FOR(dest,condExpr)   =  copyAst (AST_FOR(src,condExpr)) ;
-   AST_FOR(dest,loopExpr)   =  copyAst (AST_FOR(src,loopExpr)) ;
+      AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
+      AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
+      AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
+      AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
+      AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
+      AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
+      AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
     }
 
 }
@@ -225,307 +211,500 @@ void copyAstValues (ast *dest,ast *src)
 /*-----------------------------------------------------------------*/
 /* copyAst - makes a copy of a given astession                     */
 /*-----------------------------------------------------------------*/
-ast  *copyAst (ast   *src)
+ast *
+copyAst (ast * src)
 {
-    ast  *dest;
+  ast *dest;
 
-    if (!src)  return NULL ;
+  if (!src)
+    return NULL;
 
-    dest = Safe_calloc(1,sizeof(ast));
+  dest = Safe_alloc ( sizeof (ast));
 
-    dest->type = src->type  ;
-    dest->lineno = src->lineno ;
-    dest->level  = src->level  ;
-    dest->funcName = src->funcName;
-    dest->argSym = src->argSym;
+  dest->type = src->type;
+  dest->filename = src->filename;
+  dest->lineno = src->lineno;
+  dest->level = src->level;
+  dest->funcName = src->funcName;
+  dest->reversed = src->reversed;
 
-    /* if this is a leaf */
-    /* if value */
-    if (src->type == EX_VALUE)   {
-  dest->opval.val = copyValue(src->opval.val);
-  goto exit;
+  if (src->ftype)
+    dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
+
+  /* if this is a leaf */
+  /* if value */
+  if (src->type == EX_VALUE)
+    {
+      dest->opval.val = copyValue (src->opval.val);
+      goto exit;
     }
 
-    /* if link */
-    if (src->type == EX_LINK)   {
-  dest->opval.lnk = copyLinkChain(src->opval.lnk);
-  goto exit ;
+  /* if link */
+  if (src->type == EX_LINK)
+    {
+      dest->opval.lnk = copyLinkChain (src->opval.lnk);
+      goto exit;
     }
 
-    dest->opval.op = src->opval.op ;
+  dest->opval.op = src->opval.op;
+
+  /* if this is a node that has special values */
+  copyAstValues (dest, src);
+
+  dest->trueLabel = copySymbol (src->trueLabel);
+  dest->falseLabel = copySymbol (src->falseLabel);
+  dest->left = copyAst (src->left);
+  dest->right = copyAst (src->right);
+exit:
+  return dest;
+
+}
+#if 0
+/*-----------------------------------------------------------------*/
+/* removeIncDecOps: remove for side effects in *_ASSIGN's          */
+/*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
+/*-----------------------------------------------------------------*/
+ast *removeIncDecOps (ast * tree) {
+
+  // traverse the tree and remove inc/dec ops
+
+  if (!tree)
+    return NULL;
+
+  if (tree->type == EX_OP &&
+      (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+    if (tree->left)
+      tree=tree->left;
+    else
+      tree=tree->right;
+  }
+
+  tree->left=removeIncDecOps(tree->left);
+  tree->right=removeIncDecOps(tree->right);
+
+ return tree;
+}
+
+/*-----------------------------------------------------------------*/
+/* removePreIncDecOps: remove for side effects in *_ASSIGN's       */
+/*                  "*++s += 3" -> "*++s = *++s + 3"               */
+/*-----------------------------------------------------------------*/
+ast *removePreIncDecOps (ast * tree) {
+
+  // traverse the tree and remove pre-inc/dec ops
+
+  if (!tree)
+    return NULL;
+
+  if (tree->type == EX_OP &&
+      (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+    if (tree->right)
+      tree=tree->right;
+  }
+
+  tree->left=removePreIncDecOps(tree->left);
+  tree->right=removePreIncDecOps(tree->right);
+
+ return tree;
+}
+
+/*-----------------------------------------------------------------*/
+/* removePostIncDecOps: remove for side effects in *_ASSIGN's      */
+/*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
+/*-----------------------------------------------------------------*/
+ast *removePostIncDecOps (ast * tree) {
+
+  // traverse the tree and remove pre-inc/dec ops
+
+  if (!tree)
+    return NULL;
+
+  if (tree->type == EX_OP &&
+      (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+    if (tree->left)
+      tree=tree->left;
+  }
+
+  tree->left=removePostIncDecOps(tree->left);
+  tree->right=removePostIncDecOps(tree->right);
+
+ return tree;
+}
+#endif
+/*-----------------------------------------------------------------*/
+/* replaceAstWithTemporary: Replace the AST pointed to by the arg  */
+/*            with a reference to a new temporary variable. Returns*/
+/*            an AST which assigns the original value to the       */
+/*            temporary.                                           */
+/*-----------------------------------------------------------------*/
+static ast *replaceAstWithTemporary(ast **treeptr)
+{
+  symbol *sym = newSymbol (genSymName(NestLevel), NestLevel );
+  ast *tempvar;
+
+  /* Tell gatherImplicitVariables() to automatically give the
+     symbol the correct type */
+  sym->infertype = 1;
+  sym->type = NULL;
+  sym->etype = NULL;
+
+  tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr);
+  *treeptr = newAst_VALUE(symbolVal(sym));
+
+  addSymChain(&sym);
+
+  return tempvar;
+}
+
+/*-----------------------------------------------------------------*/
+/* createRMW: Create a read-modify-write expression, using a       */
+/*            temporary variable if necessary to avoid duplicating */
+/*            any side effects, for use in e.g.                    */
+/*               foo()->count += 5;      becomes                   */
+/*               tmp = foo(); tmp->count = tmp->count + 5;         */
+/*-----------------------------------------------------------------*/
+ast * createRMW (ast *target, unsigned op, ast *operand)
+{
+  ast *readval, *writeval;
+  ast *tempvar1 = NULL;
+  ast *tempvar2 = NULL;
+  ast *result;
+
+  if (!target || !operand) {
+    return NULL;
+  }
+
+  /* we need to create two copies of target: one to read from and
+     one to write to. but we need to do this without duplicating
+     any side effects that may be contained in the tree. */
+
+  if (IS_AST_OP(target)) {
+    /* if this is a dereference, put the referenced item in the temporary */
+    if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) {
+      /* create a new temporary containing the item being dereferenced */
+      if (hasSEFcalls(target->left))
+        tempvar1 = replaceAstWithTemporary(&(target->left));
+    } else if (target->opval.op == '[') {
+      /* Array access is similar, but we have to avoid side effects in
+         both values [WIML: Why not transform a[b] to *(a+b) in parser?] */
+      if (hasSEFcalls(target->left))
+        tempvar1 = replaceAstWithTemporary(&(target->left));
+      if (hasSEFcalls(target->right))
+        tempvar2 = replaceAstWithTemporary(&(target->right));
+    } else if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
+      /* illegal pre/post-increment/decrement */
+      werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
+    } else {
+      /* we would have to handle '.', but it is not generated any more */
+      wassertl(target->opval.op != '.', "obsolete opcode in tree");
+
+      /* no other kinds of ASTs are lvalues and can contain side effects */
+    }
+  }
 
-    /* if this is a node that has special values */
-    copyAstValues (dest,src);
+  readval = target;
+  writeval = copyAst(target);
 
-    if ( src->ftype )
-  dest->etype = getSpec(dest->ftype = copyLinkChain(src->ftype)) ;
+  result = newNode('=', writeval, newNode(op, readval, operand));
+  if (tempvar2)
+    result = newNode(',', tempvar2, result);
+  if (tempvar1)
+    result = newNode(',', tempvar1, result);
 
-    dest->trueLabel = copySymbol (src->trueLabel);
-    dest->falseLabel= copySymbol (src->falseLabel);
-    dest->left = copyAst(src->left);
-    dest->right= copyAst(src->right);
- exit:
-    return dest ;
+  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)
+bool
+hasSEFcalls (ast * tree)
 {
-    if (!tree)
-  return FALSE ;
+  if (!tree)
+    return FALSE;
 
-    if (tree->type == EX_OP &&
-  ( tree->opval.op == CALL  ||
-    tree->opval.op == PCALL ||
-    tree->opval.op == '='   ||
-    tree->opval.op == INC_OP ||
-    tree->opval.op == DEC_OP ))
-  return TRUE;
+  if (tree->type == EX_OP &&
+      (tree->opval.op == CALL ||
+       tree->opval.op == PCALL ||
+       tree->opval.op == '=' ||
+       tree->opval.op == INC_OP ||
+       tree->opval.op == DEC_OP))
+    return TRUE;
 
-    return ( hasSEFcalls(tree->left) |
-       hasSEFcalls(tree->right));
+  return (hasSEFcalls (tree->left) |
+          hasSEFcalls (tree->right));
 }
 
 /*-----------------------------------------------------------------*/
 /* isAstEqual - compares two asts & returns 1 if they are equal    */
 /*-----------------------------------------------------------------*/
-int isAstEqual (ast *t1, ast *t2)
+static int
+isAstEqual (ast * t1, ast * t2)
 {
-    if (!t1 && !t2)
-  return 1;
+  if (!t1 && !t2)
+    return 1;
 
-    if (!t1 || !t2)
-  return 0;
+  if (!t1 || !t2)
+    return 0;
 
-    /* match type */
-    if (t1->type != t2->type)
-  return 0;
+  /* match type */
+  if (t1->type != t2->type)
+    return 0;
 
-    switch (t1->type) {
+  switch (t1->type)
+    {
     case EX_OP:
-  if (t1->opval.op != t2->opval.op)
-      return 0;
-  return ( isAstEqual(t1->left,t2->left) &&
-     isAstEqual(t1->right,t2->right));
-  break;
+      if (t1->opval.op != t2->opval.op)
+        return 0;
+      return (isAstEqual (t1->left, t2->left) &&
+              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);
-  }
-  else {
-      if (t2->opval.val->sym)
-    return 0;
+      if (t1->opval.val->sym)
+        {
+          if (!t2->opval.val->sym)
+            return 0;
+          else
+            return isSymbolEqual (t1->opval.val->sym,
+                                  t2->opval.val->sym);
+        }
       else
-    return (floatFromVal(t1->opval.val) ==
-      floatFromVal(t2->opval.val));
-  }
-  break;
+        {
+          if (t2->opval.val->sym)
+            return 0;
+          else
+            return (floatFromVal (t1->opval.val) ==
+                    floatFromVal (t2->opval.val));
+        }
+      break;
 
-  /* only compare these two types */
-    default :
-  return 0;
+      /* only compare these two types */
+    default:
+      return 0;
     }
 
-    return 0;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* resolveSymbols - resolve symbols from the symbol table          */
 /*-----------------------------------------------------------------*/
-ast *resolveSymbols (ast *tree)
+ast *
+resolveSymbols (ast * tree)
 {
-    /* walk the entire tree and check for values */
-    /* with symbols if we find one then replace  */
-    /* symbol with that from the symbol table    */
+  /* walk the entire tree and check for values */
+  /* with symbols if we find one then replace  */
+  /* symbol with that from the symbol table    */
 
-    if ( tree == NULL )
-  return tree ;
+  if (tree == NULL)
+    return 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    )) {
-  filename = tree->filename ;
-  lineno = tree->lineno ;
+#if 0
+  /* print the line          */
+  /* if not block & function */
+  if (tree->type == EX_OP &&
+      (tree->opval.op != FUNCTION &&
+       tree->opval.op != BLOCK &&
+       tree->opval.op != NULLOP))
+    {
+      filename = tree->filename;
+      lineno = tree->lineno;
     }
+#endif
 
-    /* make sure we resolve the true & false labels for ifx */
-    if (tree->type == EX_OP && tree->opval.op == IFX ) {
-  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);
-  }
+  /* make sure we resolve the true & false labels for ifx */
+  if (tree->type == EX_OP && tree->opval.op == IFX)
+    {
+      symbol *csym;
 
-  if (tree->falseLabel) {
-      if (( csym = findSym(LabelTab,
-         tree->falseLabel,
-         tree->falseLabel->name)))
-    tree->falseLabel = csym ;
-      else
-    werror(E_LABEL_UNDEF,tree->falseLabel->name);
-  }
+      if (tree->trueLabel)
+        {
+          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
+            werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+                      tree->falseLabel->name);
+        }
     }
 
-    /* if this is a label resolve it from the labelTab*/
-    if (IS_AST_VALUE(tree)   &&
-  tree->opval.val->sym &&
-  tree->opval.val->sym->islbl) {
-
-  symbol *csym = findSym (LabelTab, tree->opval.val->sym ,
-        tree->opval.val->sym->name);
+  /* if this is a label resolve it from the labelTab */
+  if (IS_AST_VALUE (tree) &&
+      tree->opval.val->sym &&
+      tree->opval.val->sym->islbl)
+    {
+      symbol *csym = findSym (LabelTab, tree->opval.val->sym,
+                              tree->opval.val->sym->name);
 
-  if (!csym)
-      werror (E_LABEL_UNDEF,tree->opval.val->sym->name);
-  else
-      tree->opval.val->sym = csym ;
+      if (!csym)
+        werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+                  tree->opval.val->sym->name);
+      else
+        tree->opval.val->sym = csym;
 
-  goto resolveChildren ;
+      goto resolveChildren;
     }
 
-    /* do only for leafs */
-    if (IS_AST_VALUE(tree)   &&
-  tree->opval.val->sym &&
-  ! tree->opval.val->sym->implicit ) {
-
-  symbol *csym = findSymWithLevel (SymbolTab,tree->opval.val->sym);
+  /* do only for leafs */
+  if (IS_AST_VALUE (tree) &&
+      tree->opval.val->sym &&
+      !tree->opval.val->sym->implicit)
+    {
+      symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
 
-  /* if found in the symbol table & they r not the same */
-  if (csym && tree->opval.val->sym != csym ) {
-      tree->opval.val->sym = csym ;
-      tree->opval.val->type = csym->type;
-      tree->opval.val->etype = csym->etype;
-  }
+      /* if found in the symbol table & they are 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;
+        }
 
-  /* 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();
-    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);
-      } 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 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;
+              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:
-    resolveSymbols (tree->left);
-    resolveSymbols (tree->right);
+resolveChildren:
+  resolveSymbols (tree->left);
+  resolveSymbols (tree->right);
 
-    return tree;
+  return tree;
 }
 
-/*-----------------------------------------------------------------*/
-/* setAstLineno - walks a ast tree & sets the line number          */
-/*-----------------------------------------------------------------*/
-int setAstLineno ( ast *tree, int lineno)
+/*------------------------------------------------------------------------*/
+/* setAstFileLine - walks a ast tree & sets the file name and line number */
+/*------------------------------------------------------------------------*/
+int setAstFileLine (ast * tree, char *filename, int lineno)
 {
-    if (!tree)
-  return 0;
-
-    tree->lineno = lineno ;
-    setAstLineno ( tree->left, lineno);
-    setAstLineno ( tree->right, lineno);
+  if (!tree)
     return 0;
-}
 
-#if 0
-/* this functions seems to be superfluous?! kmh */
+  tree->filename = filename;
+  tree->lineno = lineno;
+  setAstFileLine (tree->left, filename, lineno);
+  setAstFileLine (tree->right, filename, lineno);
+  return 0;
+}
 
 /*-----------------------------------------------------------------*/
-/* resolveFromTable - will return the symbal table value           */
+/* funcOfType :- function of type with name                        */
 /*-----------------------------------------------------------------*/
-value *resolveFromTable (value *val)
+symbol *
+funcOfType (char *name, sym_link * type, sym_link * argType,
+            int nArgs, int rent)
 {
-    symbol *csym ;
-
-    if (!val->sym)
-  return val;
-
-    csym = findSymWithLevel (SymbolTab,val->sym);
-
-    /* if found in the symbol table & they r not the same */
-    if (csym && val->sym != csym &&
-  csym->level == val->sym->level &&
-        csym->_isparm &&
-  !csym->ismyparm) {
+  symbol *sym;
+  /* create the symbol */
+  sym = newSymbol (name, 0);
+
+  /* setup return value */
+  sym->type = newLink (DECLARATOR);
+  DCL_TYPE (sym->type) = FUNCTION;
+  sym->type->next = copyLinkChain (type);
+  sym->etype = getSpec (sym->type);
+  FUNC_ISREENT(sym->type) = rent ? 1 : 0;
+
+  /* if arguments required */
+  if (nArgs)
+    {
+      value *args;
+      args = FUNC_ARGS(sym->type) = newValue ();
 
-  val->sym = csym ;
-  val->type = csym->type;
-  val->etype = csym->etype;
+      while (nArgs--)
+        {
+          args->type = copyLinkChain (argType);
+          args->etype = getSpec (args->type);
+          SPEC_EXTR(args->etype)=1;
+          if (!nArgs)
+            break;
+          args = args->next = newValue ();
+        }
     }
 
-    return val;
+  /* save it */
+  addSymChain (&sym);
+  sym->cdef = 1;
+  allocVariables (sym);
+  return sym;
+
 }
-#endif
 
 /*-----------------------------------------------------------------*/
-/* funcOfType :- function of type with name                        */
+/* funcOfTypeVarg :- function of type with name and argtype        */
 /*-----------------------------------------------------------------*/
-symbol *funcOfType (char *name, sym_link *type, sym_link *argType,
-        int nArgs , int rent)
+symbol *
+funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
 {
+
     symbol *sym;
-    int argStack = 0;
+    int ;
     /* create the symbol */
-    sym = newSymbol (name,0);
+    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 = sym->args = newValue();
-
-  while (nArgs--) {
-      argStack += getSize(type);
-      args->type = copyLinkChain(argType);
-      args->etype = getSpec(args->type);
-      if (!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 ();
+        }
     }
 
-    /* setup return value */
-    sym->type = newLink();
-    DCL_TYPE(sym->type) = FUNCTION;
-    sym->type->next = copyLinkChain(type);
-    sym->etype = getSpec(sym->type);
-    SPEC_RENT(sym->etype) = rent;
-
     /* save it */
-    addSymChain(sym);
+    addSymChain (&sym);
     sym->cdef = 1;
-    sym->argStack = (rent ? argStack : 0);
     allocVariables (sym);
     return sym;
 
@@ -534,484 +713,753 @@ symbol *funcOfType (char *name, sym_link *type, sym_link *argType,
 /*-----------------------------------------------------------------*/
 /* reverseParms - will reverse a parameter tree                    */
 /*-----------------------------------------------------------------*/
-void reverseParms (ast *ptree)
+static void
+reverseParms (ast * ptree)
 {
-    ast *ttree;
-    if (!ptree)
-  return ;
+  ast *ttree;
+  if (!ptree)
+    return;
+
+  /* top down if we find a nonParm tree then quit */
+  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;
+        }
 
-    /* top down if we find a nonParm tree then quit */
-    if (ptree->type == EX_OP && ptree->opval.op == PARAM ) {
-  ttree = ptree->left;
-  ptree->left = ptree->right;
-  ptree->right = ttree;
-  reverseParms(ptree->left);
-  reverseParms(ptree->right);
+      /* Now reverse */
+      ttree = ptree->left;
+      ptree->left = ptree->right;
+      ptree->right = ttree;
+      ptree->reversed = 1;
+      reverseParms (ptree->left);
+      reverseParms (ptree->right);
     }
 
-    return ;
+  return;
 }
 
 /*-----------------------------------------------------------------*/
 /* processParms  - makes sure the parameters are okay and do some  */
 /*                 processing with them                            */
 /*-----------------------------------------------------------------*/
-int processParms (ast  *func,
-                 value *defParm,
-                 ast   *actParm,
-                 int   *parmNumber,
-                 bool  rightmost)
+static int
+processParms (ast *func,
+              value *defParm,
+              ast **actParm,
+              int *parmNumber, /* unused, although updated */
+              bool rightmost)
 {
-    sym_link *fetype = func->etype;
+  RESULT_TYPE resultType;
+  sym_link *functype;
 
-    /* if none of them exist */
-    if ( !defParm && !actParm)
-  return 0;
+  /* if none of them exist */
+  if (!defParm && !*actParm)
+    return 0;
 
-    /* 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 && !IS_RENT(fetype) && !options.stackAuto) {
-  werror (E_NONRENT_ARGS);
-  return 1;
+  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);
     }
 
-    /* if defined parameters ended but actual parameters */
-    /* exist and this is not defined as a variable arg   */
-    /* also check if statckAuto option is specified      */
-    if ((! defParm) && actParm && (!func->hasVargs ) &&
-  !options.stackAuto && !IS_RENT(fetype)) {
-  werror(E_TOO_MANY_PARMS);
-  return 1;
+  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 reentrant then we cannot */
+  /* have parameters                                  */
+  /* PIC16 port can... */
+  if (!TARGET_IS_PIC16)
+    {
+      if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
+        {
+          werror (E_NONRENT_ARGS);
+          fatalError++;
+          return 1;
+        }
     }
 
-    /* if defined parameters present but no actual parameters */
-    if ( defParm && ! actParm) {
-      werror(E_TOO_FEW_PARMS);
+  /* if defined parameters ended but actual parameters */
+  /* exist and this is not defined as a variable arg   */
+  if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
+    {
+      werror (E_TOO_MANY_PARMS);
       return 1;
     }
 
-    /* If this is a varargs function... */
-    if (!defParm && actParm && func->hasVargs )
+  /* if defined parameters present but no actual parameters */
+  if (defParm && !*actParm)
     {
-        ast *newType = NULL;
+      werror (E_TOO_FEW_PARMS);
+      return 1;
+    }
 
-  if (IS_CAST_OP(actParm)
-   || (IS_AST_LIT_VALUE(actParm) && actParm->values.literalFromCast))
-  {
-     /* Parameter was explicitly typecast; don't touch it. */
-     return 0;
-  }
+  /* 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(functype))
+    {
+      ast *newType = NULL;
+      sym_link *ftype;
+
+      /* don't perform integer promotion of explicitly typecasted variable arguments
+       * if sdcc extensions are enabled */
+      if (options.std_sdcc &&
+        (IS_CAST_OP (*actParm) ||
+        (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
+        (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
+        {
+          /* Parameter was explicitly typecast; don't touch it. */
+          return 0;
+        }
+
+      ftype = (*actParm)->ftype;
 
-        /* If it's a small integer, upcast to int. */
-      if (IS_INTEGRAL(actParm->ftype)
-         && getSize(actParm->ftype) < (unsigned) INTSIZE)
+      /* If it's a char, upcast to int. */
+      if (IS_INTEGRAL (ftype)
+          && (getSize (ftype) < (unsigned) INTSIZE))
         {
-      newType = newAst_LINK(INTTYPE);
+          newType = newAst_LINK(INTTYPE);
         }
 
-        if (IS_PTR(actParm->ftype) && !IS_GENPTR(actParm->ftype))
+      if (IS_PTR(ftype) && !IS_GENPTR(ftype))
         {
-            newType = newAst_LINK(copyLinkChain(actParm->ftype));
-            DCL_TYPE(newType->opval.lnk) = GPOINTER;
+          newType = newAst_LINK (copyLinkChain(ftype));
+          DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
         }
 
-        if (IS_AGGREGATE(actParm->ftype))
+      if (IS_AGGREGATE (ftype))
         {
-            newType = newAst_LINK(copyLinkChain(actParm->ftype));
-            DCL_TYPE(newType->opval.lnk) = GPOINTER;
+          newType = newAst_LINK (copyLinkChain (ftype));
+          DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
         }
 
-        if (newType)
+      if (newType)
         {
           /* cast required; change this op to a cast. */
-            ast *parmCopy = resolveSymbols(copyAst(actParm));
+          (*actParm)->decorated = 0;
+           *actParm = newNode (CAST, newType, *actParm);
+          (*actParm)->filename = (*actParm)->right->filename;
+          (*actParm)->lineno = (*actParm)->right->lineno;
 
-      actParm->type = EX_OP;
-      actParm->opval.op = CAST;
-      actParm->left = newType;
-      actParm->right= parmCopy;
-      decorateType(actParm);
+          decorateType (*actParm, RESULT_TYPE_NONE);
         }
-        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));
-        }
-        return 0;
-    }
+      return 0;
+    } /* vararg */
 
-    /* if defined parameters ended but actual has not & */
-    /* stackAuto                */
-    if (! defParm && actParm &&
-  (options.stackAuto || IS_RENT(fetype)))
-  return 0;
+  /* if defined parameters ended but actual has not & */
+  /* reentrant */
+  if (!defParm && *actParm &&
+      (options.stackAuto || IFFUNC_ISREENT (functype)))
+    return 0;
+
+  resolveSymbols (*actParm);
 
-    resolveSymbols(actParm);
-    /* if this is a PARAM node then match left & right */
-    if ( actParm->type == EX_OP && actParm->opval.op == PARAM) 
+  /* the parameter type must be at least castable */
+  if (compareType (defParm->type, (*actParm)->ftype) == 0)
     {
-      return (processParms(func,defParm,actParm->left,parmNumber,FALSE) ||
-              processParms(func,defParm->next, actParm->right,parmNumber,rightmost));
+      werror (E_INCOMPAT_TYPES);
+      printFromToType ((*actParm)->ftype, defParm->type);
+      return 1;
     }
-    else 
+
+  /* if the parameter is castable then add the cast */
+  if (compareType (defParm->type, (*actParm)->ftype) < 0)
     {
-        /* 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;
-        }
-    }
-    
-    /* the parameter type must be at least castable */
-    if (checkType(defParm->type,actParm->ftype) == 0) {
-  werror(E_TYPE_MISMATCH_PARM,*parmNumber);
-        werror(E_CONTINUE,"defined type ");
-  printTypeChain(defParm->type,stderr);fprintf(stderr,"\n");
-  werror(E_CONTINUE,"actual type ");
-  printTypeChain(actParm->ftype,stderr);fprintf(stderr,"\n");
+      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)->decorated = 0; /* force typechecking */
+      decorateType (*actParm, IS_GENPTR (defParm->type) ? RESULT_TYPE_GPTR : resultType);
     }
 
-    /* if the parameter is castable then add the cast */
-    if ( checkType (defParm->type,actParm->ftype) < 0) {
-  ast *pTree = resolveSymbols(copyAst(actParm));
+  /* 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);
 
-  /* 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;
+  /* if the function is being called via a pointer &  */
+  /* this parameter is not passed in registers        */
+  /* then the function must be defined reentrant      */
+  if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
+      !IFFUNC_ISREENT (functype) && !options.stackAuto)
+    {
+      werror (E_NONRENT_ARGS);
+      fatalError++;
+      return 1;
     }
 
-/*    actParm->argSym = resolveFromTable(defParm)->sym ; */
-
-    actParm->argSym = defParm->sym;
-    /* 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);
-    (*parmNumber)++;
-    return 0;
+  (*parmNumber)++;
+  return 0;
 }
+
 /*-----------------------------------------------------------------*/
 /* createIvalType - generates ival for basic types                 */
 /*-----------------------------------------------------------------*/
-ast *createIvalType ( ast *sym,sym_link  *type, initList *ilist)
+static ast *
+createIvalType (ast * sym, sym_link * type, initList * ilist)
 {
-    ast *iExpr;
+  ast *iExpr;
 
-    /* if initList is deep */
-    if ( ilist->type == INIT_DEEP )
-  ilist =  ilist->init.deep  ;
+  /* if initList is deep */
+  if (ilist && ilist->type == INIT_DEEP)
+    ilist = ilist->init.deep;
 
-    iExpr = decorateType(resolveSymbols(list2expr(ilist)));
-    return decorateType(newNode('=',sym,iExpr));
+  if (ilist)
+    iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
+  else
+    iExpr = newAst_VALUE (valueFromLit (0));
+  return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
 }
 
 /*-----------------------------------------------------------------*/
 /* createIvalStruct - generates initial value for structures       */
 /*-----------------------------------------------------------------*/
-ast *createIvalStruct (ast *sym,sym_link *type,initList *ilist)
+static ast *
+createIvalStruct (ast *sym, sym_link *type, initList *ilist, ast *rootValue)
 {
-    ast *rast = NULL ;
-    symbol   *sflds  ;
-    initList *iloop  ;
+  ast *rast = NULL;
+  ast *lAst;
+  symbol *sflds;
+  initList *iloop;
+  sym_link * etype = getSpec (type);
 
-    sflds = SPEC_STRUCT(type)->fields  ;
-    if (ilist->type != INIT_DEEP) {
-  werror(E_INIT_STRUCT,"");
-  return NULL ;
+  if (ilist && ilist->type != INIT_DEEP)
+    {
+      werror (E_INIT_STRUCT, "");
+      return NULL;
     }
 
-    iloop = ilist->init.deep;
+  iloop = ilist ? ilist->init.deep : NULL;
 
-    for ( ; sflds ; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL )) {
-  ast *lAst ;
+  for (sflds = SPEC_STRUCT (type)->fields; sflds; sflds = sflds->next)
+    {
+      /* if we have come to end */
+      if (!iloop && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
+        break;
 
-  /* if we have come to end */
-  if (!iloop)
-      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)));
+      if (!IS_BITFIELD (sflds->type) || !SPEC_BUNNAMED (sflds->etype))
+        {
+          sflds->implicit = 1;
+          lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
+          lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
+          rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast, rootValue)), RESULT_TYPE_NONE);
+          iloop = iloop ? iloop->next : NULL;
+        }
+    }
+
+  if (iloop)
+    {
+      if (IS_AST_VALUE (sym))
+        werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+                  W_EXCESS_INITIALIZERS, "struct",
+                  sym->opval.val->sym->name);
+      else
+        werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
     }
-    return rast ;
-}
 
+  return rast;
+}
 
 /*-----------------------------------------------------------------*/
 /* createIvalArray - generates code for array initialization       */
 /*-----------------------------------------------------------------*/
-ast *createIvalArray (ast  *sym, sym_link *type, initList *ilist)
+static ast *
+createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
 {
-    ast *rast = NULL;
-    initList *iloop ;
-    int lcnt = 0, size =0 ;
-
-    /* take care of the special   case  */
-    /* array of characters can be init  */
-    /* by a string                      */
-    if ( IS_CHAR(type->next) )
-  if ( (rast = createIvalCharPtr(sym,
-               type,
-               decorateType(resolveSymbols(list2expr(ilist))))))
+  ast *rast = NULL;
+  initList *iloop;
+  int lcnt = 0, size = 0;
+  literalList *literalL;
+  sym_link * etype = getSpec (type);
+
+  /* take care of the special   case  */
+  /* array of characters can be init  */
+  /* by a string                      */
+  if (IS_CHAR (type->next))
+    if ((rast = createIvalCharPtr (sym,
+                                   type,
+                                   decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
+                                   rootValue)))
+
+      return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
+
+  /* not the special case */
+  if (ilist && ilist->type != INIT_DEEP)
+    {
+      werror (E_INIT_STRUCT, "");
+      return NULL;
+    }
 
-      return decorateType(resolveSymbols(rast));
+  iloop = ilist ? ilist->init.deep : NULL;
+  lcnt = DCL_ELEM (type);
 
-    /* not the special case             */
-    if (ilist->type != INIT_DEEP) {
-  werror(E_INIT_STRUCT,"");
-  return NULL;
+  if (!iloop &&
+      (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
+    {
+      return NULL;
     }
 
-    iloop = ilist->init.deep   ;
-    lcnt = DCL_ELEM(type);
+  if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL, lcnt))
+    {
+      ast *aSym;
 
-    for (;;)  {
-  ast *aSym ;
-  size++ ;
+      aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
 
-  aSym = newNode('[',sym,newAst_VALUE(valueFromLit((float) (size-1))));
-  aSym = decorateType(resolveSymbols(aSym));
-  rast = createIval (aSym,type->next,iloop,rast)   ;
-  iloop = (iloop ? iloop->next : NULL) ;
-  if (!iloop)
-      break;
-  /* if not array limits given & we */
-  /* are out of initialisers then   */
-  if (!DCL_ELEM(type) && !iloop)
-      break ;
+      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;
+        }
 
-  /* no of elements given and we    */
-  /* have generated for all of them */
-  if (!--lcnt)
-      break ;
+      if (lcnt && size > lcnt)
+        {
+          // Array size was specified, and we have more initializers than needed.
+          werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+                    W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
+        }
+    }
+  else
+    {
+      for (;;)
+        {
+          ast *aSym;
+
+          if (!iloop &&
+              (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
+            {
+              break;
+            }
+
+          aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
+          aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
+          rast = createIval (aSym, type->next, iloop, rast, rootValue);
+          lcnt--;
+          iloop = (iloop ? iloop->next : NULL);
+
+          /* no of elements given and we    */
+          /* have generated for all of them */
+          if (!lcnt && iloop)
+            {
+              // is this a better way? at least it won't crash
+              char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+              werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
+
+              break;
+            }
+        }
     }
 
-    /* if we have not been given a size  */
-    if (!DCL_ELEM(type))
-  DCL_ELEM(type) = size;
+  /* if we have not been given a size  */
+  if (!DCL_ELEM (type))
+    {
+      /* 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);
 }
 
 
 /*-----------------------------------------------------------------*/
 /* createIvalCharPtr - generates initial values for char pointers  */
 /*-----------------------------------------------------------------*/
-ast *createIvalCharPtr (ast *sym, sym_link *type, ast *iexpr)
-{
-    ast *rast = NULL ;
-
-    /* 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)))
-  return newNode('=',sym,iexpr);
-
-    /* left side is an array so we have to assign each */
-    /* element                                         */
-    if (( IS_LITERAL(iexpr->etype) ||
-    SPEC_SCLS(iexpr->etype) == S_CODE )
-  && IS_ARRAY(iexpr->ftype))  {
-
-  /* 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))));
-  return decorateType(resolveSymbols(rast));
+static ast *
+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)))
+    return newNode ('=', sym, iexpr);
+
+  /* left side is an array so we have to assign each element */
+  if (!iexpr)
+    {
+      /* for each character generate an assignment */
+      /* to the array element */
+      unsigned int i = 0;
+      unsigned int symsize = getSize (type);
+
+      if (!AST_SYMBOL (rootVal)->islocal || SPEC_STAT (getSpec (type)))
+        return NULL;
+
+      for (i = 0; i < symsize; ++i)
+        {
+          rast = newNode (NULLOP,
+                          rast,
+                          newNode ('=',
+                                   newNode ('[', sym,
+                                            newAst_VALUE (valueFromLit ((float) i))),
+                                   newAst_VALUE (valueFromLit (0))));
+        }
+
+      return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
+    }
+
+  if ((IS_LITERAL (iexpr->etype) ||
+       SPEC_SCLS (iexpr->etype) == S_CODE)
+      && IS_ARRAY (iexpr->ftype))
+    {
+      /* for each character generate an assignment */
+      /* to the array element */
+      char *s = SPEC_CVAL (iexpr->etype).v_char;
+      unsigned int i = 0;
+      unsigned int symsize = getSize (type);
+
+      size = getSize (iexpr->ftype);
+      if (symsize && size > symsize)
+        {
+          if (size > symsize)
+            {
+              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++))));
+        }
+
+      // now WE don't need iexpr's symbol anymore
+      freeStringSymbol(AST_SYMBOL(iexpr));
+
+      /* if we have not been given a size  */
+      if (!DCL_ELEM (type))
+        {
+          /* check, if it's a flexible array */
+          if (IS_STRUCT (AST_VALUE (rootVal)->type))
+            AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
+          else
+            DCL_ELEM (type) = size;
+        }
+
+      return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
     }
 
-    return NULL ;
+  return NULL;
 }
 
 /*-----------------------------------------------------------------*/
 /* createIvalPtr - generates initial value for pointers            */
 /*-----------------------------------------------------------------*/
-ast *createIvalPtr (ast *sym,sym_link *type,initList *ilist)
+static ast *
+createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
 {
-    ast *rast;
-    ast *iexpr ;
+  ast *rast;
+  ast *iexpr;
 
-    /* if deep then   */
-    if ( ilist->type == INIT_DEEP )
-  ilist = ilist->init.deep   ;
+  /* if deep then   */
+  if (ilist && 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 character pointer */
+  if (IS_CHAR (type->next))
+    if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
       return rast;
 
-    return newNode('=',sym,iexpr);
+  return newNode ('=', sym, iexpr);
 }
 
 /*-----------------------------------------------------------------*/
 /* createIval - generates code for initial value                   */
 /*-----------------------------------------------------------------*/
-ast  *createIval  (ast *sym, sym_link *type, initList *ilist, ast *wid)
+static ast *
+createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
 {
-    ast *rast = NULL;
+  ast *rast = NULL;
 
-    if (!ilist)
-  return NULL ;
+  if (!ilist && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (getSpec (type))))
+    return NULL;
 
-    /* if structure then    */
-    if (IS_STRUCT(type))
-  rast =  createIvalStruct(sym, type,ilist);
-    else
-  /* if this is a pointer */
-  if (IS_PTR(type))
-      rast = createIvalPtr(sym, type,ilist);
+  /* if structure then    */
+  if (IS_STRUCT (type))
+    rast = createIvalStruct (sym, type, ilist, rootValue);
+  else
+    /* if this is a pointer */
+  if (IS_PTR (type))
+    rast = createIvalPtr (sym, type, ilist, rootValue);
+  else
+    /* if this is an array   */
+  if (IS_ARRAY (type))
+    rast = createIvalArray (sym, type, ilist, rootValue);
   else
-      /* if this is an array   */
-      if (IS_ARRAY(type))
-    rast = createIvalArray(sym, type,ilist);
-      else
     /* if type is SPECIFIER */
-    if (IS_SPEC(type))
-        rast =  createIvalType (sym,type,ilist);
-    if ( wid )
-  return decorateType(resolveSymbols(newNode(NULLOP,wid,rast)));
-    else
-  return decorateType(resolveSymbols(rast)) ;
+  if (IS_SPEC (type))
+    rast = createIvalType (sym, type, ilist);
+
+  if (wid)
+    return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
+  else
+    return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 }
 
 /*-----------------------------------------------------------------*/
 /* initAggregates - initialises aggregate variables with initv     */
 /*-----------------------------------------------------------------*/
-ast *initAggregates ( symbol *sym, initList *ival, ast *wid)
+ast * initAggregates (symbol * sym, initList * ival, ast * wid)
 {
-    return createIval (newAst_VALUE(symbolVal(sym)),sym->type,ival,wid);
+  ast *newAst = newAst_VALUE (symbolVal (sym));
+  return createIval (newAst, sym->type, ival, wid, newAst);
 }
 
 /*-----------------------------------------------------------------*/
 /* gatherAutoInit - creates assignment expressions for initial     */
-/*    values                 */
+/*                  values                                         */
 /*-----------------------------------------------------------------*/
-ast *gatherAutoInit ( symbol *autoChain )
+static ast *
+gatherAutoInit (symbol * autoChain)
 {
-    ast *init = NULL ;
-    ast *work ;
-    symbol  *sym;
+  ast *init = NULL;
+  ast *work;
+  symbol *sym;
 
-    inInitMode =1;
-    for ( sym = autoChain ; sym ; sym = sym->next ) {
-
-  /* resolve the symbols in the ival */
-  if (sym->ival)
-      resolveIvalSym(sym->ival);
-
-  /* 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->name,0,0);
-
-      /* now lift the code to main */
-      if (IS_AGGREGATE(sym->type))
-    work = initAggregates (sym, sym->ival,NULL);
-      else
-    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 ;
+  inInitMode = 1;
+  for (sym = autoChain; sym; sym = sym->next)
+    {
+      /* resolve the symbols in the ival */
+      if (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
 
-      continue;
-  }
+      /* 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) {
+              werrorfl (sym->fileDef, sym->lineDef,
+                        W_EXCESS_INITIALIZERS, "scalar",
+                        sym->name);
+            }
+            work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
+                            list2expr (sym->ival));
+          }
+
+          setAstFileLine (work, sym->fileDef, 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) {
-      if (IS_AGGREGATE(sym->type))
-    work = initAggregates (sym,sym->ival,NULL);
-      else
-    work = newNode('=' ,newAst_VALUE(symbolVal(sym)),
-             list2expr(sym->ival));
+      /* 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 */
+          filename = sym->fileDef;
+          lineno = sym->lineDef;
+          setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
+
+          if (IS_AGGREGATE (sym->type))
+            {
+              work = initAggregates (sym, sym->ival, NULL);
+            }
+          else
+            {
+              if (getNelements(sym->type, sym->ival)>1)
+                {
+                  werrorfl (sym->fileDef, sym->lineDef,
+                            W_EXCESS_INITIALIZERS, "scalar",
+                            sym->name);
+                }
+              work = newNode ('=', newAst_VALUE (symbolVal (sym)),
+                              list2expr (sym->ival));
+            }
+
+          // just to be sure
+          setAstFileLine (work, sym->fileDef, sym->lineDef);
+
+          sym->ival = NULL;
+          if (init)
+            init = newNode (NULLOP, init, work);
+          else
+            init = work;
+        }
+    }
+  inInitMode = 0;
+  return init;
+}
 
-      setAstLineno (work,sym->lineDef);
-      sym->ival = NULL ;
-      if ( init )
-    init = newNode(NULLOP,init,work);
-      else
-    init = work ;
-  }
+/*-----------------------------------------------------------------*/
+/* freeStringSymbol - delete a literal string if no more usage     */
+/*-----------------------------------------------------------------*/
+void freeStringSymbol(symbol *sym) {
+  /* make sure this is a literal string */
+  assert (sym->isstrlit);
+  if (--sym->isstrlit == 0) { // lower the usage count
+    memmap *segment=SPEC_OCLS(sym->etype);
+    if (segment) {
+      deleteSetItem(&segment->syms, sym);
     }
-    inInitMode = 0;
-    return init ;
+  }
 }
 
 /*-----------------------------------------------------------------*/
 /* stringToSymbol - creates a symbol from a literal string         */
 /*-----------------------------------------------------------------*/
-static value *stringToSymbol (value *val)
+static value *
+stringToSymbol (value * val)
 {
-    char name[SDCC_NAME_MAX+1];
-    static int charLbl = 0;
-    symbol *sym ;
-
-    sprintf(name,"_str_%d",charLbl++);
-    sym = newSymbol(name,0); /* make it @ level 0 */
-    strcpy(sym->rname,name);
+  char name[SDCC_NAME_MAX + 1];
+  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;
+      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);
+        }
+    }
 
-    /* copy the type from the value passed */
-    sym->type = copyLinkChain(val->type);
-    sym->etype = getSpec(sym->type);
-    /* change to storage class & output class */
-    SPEC_SCLS(sym->etype) = S_CODE ;
-    SPEC_CVAL(sym->etype).v_char = SPEC_CVAL(val->etype).v_char ;
-    SPEC_STAT(sym->etype) = 1;
-    /* make the level & block = 0 */
-    sym->block = sym->level = 0;
-    sym->isstrlit = 1;
-    /* create an ival */
-    sym->ival = newiList(INIT_NODE,newAst_VALUE(val));
-    if (noAlloc == 0) {
-  /* allocate it */
-  addSymChain(sym);
-  allocVariables(sym);
+  SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
+  sym = newSymbol (name, 0);    /* make it @ level 0 */
+  strncpyz (sym->rname, name, SDCC_NAME_MAX);
+
+  /* copy the type from the value passed */
+  sym->type = copyLinkChain (val->type);
+  sym->etype = getSpec (sym->type);
+  /* change to storage class & output class */
+  SPEC_SCLS (sym->etype) = S_CODE;
+  SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
+  SPEC_STAT (sym->etype) = 1;
+  /* make the level & block = 0 */
+  sym->block = sym->level = 0;
+  sym->isstrlit = 1;
+  /* create an ival */
+  sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
+  if (noAlloc == 0)
+    {
+      /* allocate it */
+      addSymChain (&sym);
+      allocVariables (sym);
     }
-    sym->ival = NULL;
-    return symbolVal(sym);
+  sym->ival = NULL;
+  return symbolVal (sym);
 
 }
 
@@ -1020,402 +1468,551 @@ static value *stringToSymbol (value *val)
 /*                    a block is found then will allocate the syms */
 /*                    will also gather the auto inits present      */
 /*-----------------------------------------------------------------*/
-ast *processBlockVars ( ast *tree , int *stack, int action)
+ast *
+processBlockVars (ast * tree, int *stack, int action)
 {
-    if (! tree)
-  return NULL ;
+  if (!tree)
+    return NULL;
 
-    /* if this is a block */
-    if (tree->type == EX_OP && tree->opval.op == BLOCK ) {
-  ast *autoInit ;
+  /* if this is a block */
+  if (tree->type == EX_OP && tree->opval.op == BLOCK)
+    {
+      ast *autoInit;
 
-  if (action == ALLOCATE) {
-      autoInit = gatherAutoInit (tree->values.sym);
-      *stack += allocVariables (tree->values.sym);
+      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);
-  } else /* action is deallocate */
-      deallocLocal (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);
     }
 
-    processBlockVars (tree->left, stack, action);
-    processBlockVars (tree->right, stack, action);
-    return tree ;
+  processBlockVars (tree->left, stack, action);
+  processBlockVars (tree->right, stack, action);
+  return tree;
+}
+
+/*-------------------------------------------------------------*/
+/* constExprTree - returns TRUE if this tree is a constant     */
+/*                 expression                                  */
+/*-------------------------------------------------------------*/
+bool constExprTree (ast *cexpr) {
+
+  if (!cexpr) {
+    return TRUE;
+  }
+
+  cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
+
+  switch (cexpr->type)
+    {
+    case EX_VALUE:
+      if (IS_AST_LIT_VALUE(cexpr)) {
+        // 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;
+      }
+      if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
+        // 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
+        //printf(" code space symbol");
+        return TRUE;
+      }
+      return FALSE;
+    case EX_LINK:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "unexpected link in expression tree\n");
+      return FALSE;
+    case EX_OP:
+      if (cexpr->opval.op==ARRAYINIT) {
+        // this is a list of literals
+        return TRUE;
+      }
+      if (cexpr->opval.op=='=') {
+        return constExprTree(cexpr->right);
+      }
+      if (cexpr->opval.op==CAST) {
+        // cast ignored, maybe we should throw a warning here?
+        return constExprTree(cexpr->right);
+      }
+      if (cexpr->opval.op=='&') {
+        return TRUE;
+      }
+      if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
+        return FALSE;
+      }
+      if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
+        return TRUE;
+      }
+      return FALSE;
+    case EX_OPERAND:
+      return IS_CONSTANT(operandType(cexpr->opval.oprnd));
+    }
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
 /* constExprValue - returns the value of a constant expression     */
+/*                  or NULL if it is not a constant expression     */
 /*-----------------------------------------------------------------*/
-value *constExprValue (ast *cexpr, int check)
-{
-    cexpr = decorateType(resolveSymbols(cexpr));
-
-    /* if this is not a constant then */
-    if (!IS_LITERAL(cexpr->ftype)) {
-  /* 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);
-      strcpy(val->name,cexpr->opval.val->sym->rname);
-      return val;
-  }
+value *
+constExprValue (ast * cexpr, int check)
+{
+  cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
 
-  /* if we are casting a literal value then */
-  if (IS_AST_OP(cexpr)        &&
-      cexpr->opval.op == CAST &&
-      IS_LITERAL(cexpr->left->ftype))
-      return valCastLiteral(cexpr->ftype,
-          floatFromVal(cexpr->left->opval.val));
+  /* if this is not a constant then */
+  if (!IS_LITERAL (cexpr->ftype))
+    {
+      /* 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;
+        }
 
-  if (IS_AST_VALUE(cexpr))
-      return cexpr->opval.val;
+      /* if we are casting a literal value then */
+      if (IS_AST_OP (cexpr) &&
+          cexpr->opval.op == CAST &&
+          IS_LITERAL (cexpr->right->ftype))
+        {
+          return valCastLiteral (cexpr->ftype,
+                                 floatFromVal (cexpr->right->opval.val));
+        }
+
+      if (IS_AST_VALUE (cexpr))
+        {
+          return cexpr->opval.val;
+        }
 
-  if (check)
-      werror(E_CONST_EXPECTED,"found expression");
+      if (check)
+        werror (E_CONST_EXPECTED, "found expression");
 
-  return NULL ;
+      return NULL;
     }
 
-    /* return the value */
-    return cexpr->opval.val ;
-
+  /* return the value */
+  if (IS_AST_VALUE (cexpr))
+    {
+      return cexpr->opval.val;
+    }
+  return NULL;
 }
 
 /*-----------------------------------------------------------------*/
 /* isLabelInAst - will return true if a given label is found       */
 /*-----------------------------------------------------------------*/
-bool isLabelInAst (symbol *label, ast *tree)
+bool
+isLabelInAst (symbol * label, ast * tree)
 {
-    if (!tree  || IS_AST_VALUE(tree) || IS_AST_LINK(tree))
-  return FALSE ;
-
-    if (IS_AST_OP(tree) &&
-  tree->opval.op == LABEL &&
-  isSymbolEqual(AST_SYMBOL(tree->left),label))
-  return TRUE;
+  if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
+    return FALSE;
 
-    return isLabelInAst(label,tree->right) &&
-  isLabelInAst(label,tree->left);
+  if (IS_AST_OP (tree) &&
+      tree->opval.op == LABEL &&
+      isSymbolEqual (AST_SYMBOL (tree->left), label))
+    return TRUE;
 
+  return isLabelInAst (label, tree->right) &&
+    isLabelInAst (label, tree->left);
 }
 
 /*-----------------------------------------------------------------*/
 /* isLoopCountable - return true if the loop count can be determi- */
 /* -ned at compile time .                                          */
 /*-----------------------------------------------------------------*/
-bool isLoopCountable (ast *initExpr, ast *condExpr, ast *loopExpr,
-          symbol **sym,ast **init, ast **end)
+static bool
+isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
+                 symbol ** sym, ast ** init, ast ** end)
 {
 
-    /* the loop is considered countable if the following
-       conditions are true :-
+  /* the loop is considered countable if the following
+     conditions are true :-
 
-       a) initExpr :- <sym> = <const>
-       b) condExpr :- <sym> < <const1>
-       c) loopExpr :- <sym> ++
-    */
+     a) initExpr :- <sym> = <const>
+     b) condExpr :- <sym> < <const1>
+     c) loopExpr :- <sym> ++
+   */
 
-    /* first check the initExpr */
-    if ( IS_AST_OP(initExpr)       &&
-   initExpr->opval.op == '=' && /* is assignment */
-   IS_AST_SYM_VALUE(initExpr->left)) { /* left is a symbol */
+  /* first check the initExpr */
+  if (IS_AST_OP (initExpr) &&
+      initExpr->opval.op == '=' &&      /* is assignment */
+      IS_AST_SYM_VALUE (initExpr->left))
+    {                           /* left is a symbol */
 
-  *sym = AST_SYMBOL(initExpr->left);
-  *init= initExpr->right;
+      *sym = AST_SYMBOL (initExpr->left);
+      *init = initExpr->right;
     }
-    else
-  return FALSE;
-
-    /* for now the symbol has to be of
-       integral type */
-    if (!IS_INTEGRAL((*sym)->type))
-  return FALSE;
+  else
+    return FALSE;
 
-    /* now check condExpr */
-    if (IS_AST_OP(condExpr)) {
+  /* don't reverse loop with volatile counter */
+  if (IS_VOLATILE ((*sym)->type))
+    return FALSE;
 
-  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;
+  /* for now the symbol has to be of
+     integral type */
+  if (!IS_INTEGRAL ((*sym)->type))
+    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 ;
+  /* now check condExpr */
+  if (IS_AST_OP (condExpr))
+    {
 
-  default:
-      return FALSE ;
-  }
+      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 (constCharVal (1)));
+              break;
+            }
+          return FALSE;
+
+        default:
+          return FALSE;
+        }
 
     }
+  else
+    return FALSE;
 
-    /* check loop expression is of the form <sym>++ */
-    if (!IS_AST_OP(loopExpr))
-  return FALSE ;
+  /* check loop expression is of the form <sym>++ */
+  if (!IS_AST_OP (loopExpr))
+    return FALSE;
 
-    /* check if <sym> ++ */
-    if (loopExpr->opval.op == INC_OP) {
+  /* check if <sym> ++ */
+  if (loopExpr->opval.op == INC_OP)
+    {
 
-  if (loopExpr->left) {
-      /* pre */
-      if (IS_AST_SYM_VALUE(loopExpr->left) &&
-    isSymbolEqual(*sym,AST_SYMBOL(loopExpr->left)))
-    return TRUE ;
+      if (loopExpr->left)
+        {
+          /* 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 ;
-  }
+        }
+      else
+        {
+          /* 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 ) {
+  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) &&
+              AST_ULONG_VALUE (loopExpr->right) != 1)
+            return TRUE;
+        }
     }
 
-    return FALSE;
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
 /* astHasVolatile - returns true if ast contains any volatile      */
 /*-----------------------------------------------------------------*/
-bool astHasVolatile (ast *tree)
+bool
+astHasVolatile (ast * tree)
 {
-    if (!tree)
-  return FALSE ;
+  if (!tree)
+    return FALSE;
 
-    if (TETYPE(tree) && IS_VOLATILE(TETYPE(tree)))
-  return TRUE;
+  if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
+    return TRUE;
 
-    if (IS_AST_OP(tree))
-  return astHasVolatile(tree->left) ||
-      astHasVolatile(tree->right);
-    else
-  return FALSE ;
+  if (IS_AST_OP (tree))
+    return astHasVolatile (tree->left) ||
+      astHasVolatile (tree->right);
+  else
+    return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
-/* astHasPointer - return true if the ast contains any ptr variable*/
+/* astHasPointer - return true if the ast contains any ptr variable */
 /*-----------------------------------------------------------------*/
-bool astHasPointer (ast *tree)
+bool
+astHasPointer (ast * tree)
 {
-    if (!tree)
-  return FALSE ;
+  if (!tree)
+    return FALSE;
 
-    if (IS_AST_LINK(tree))
-  return TRUE;
+  if (IS_AST_LINK (tree))
+    return TRUE;
 
-    /* if we hit an array expression then check
-       only the left side */
-    if (IS_AST_OP(tree) && tree->opval.op == '[')
-  return astHasPointer(tree->left);
+  /* if we hit an array expression then check
+     only the left side */
+  if (IS_AST_OP (tree) && tree->opval.op == '[')
+    return astHasPointer (tree->left);
 
-    if (IS_AST_VALUE(tree))
-      return IS_PTR(tree->ftype) || IS_ARRAY(tree->ftype);
+  if (IS_AST_VALUE (tree))
+    return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
 
-    return astHasPointer(tree->left) ||
-  astHasPointer(tree->right);
+  return astHasPointer (tree->left) ||
+    astHasPointer (tree->right);
 
 }
 
 /*-----------------------------------------------------------------*/
 /* astHasSymbol - return true if the ast has the given symbol      */
 /*-----------------------------------------------------------------*/
-bool astHasSymbol (ast *tree, symbol *sym)
+bool
+astHasSymbol (ast * tree, symbol * sym)
 {
-    if (!tree || IS_AST_LINK(tree))
-  return FALSE ;
+  if (!tree || IS_AST_LINK (tree))
+    return FALSE;
 
-    if (IS_AST_VALUE(tree)) {
-  if (IS_AST_SYM_VALUE(tree))
-      return isSymbolEqual(AST_SYMBOL(tree),sym);
-  else
-      return FALSE;
+  if (IS_AST_VALUE (tree))
+    {
+      if (IS_AST_SYM_VALUE (tree))
+        return isSymbolEqual (AST_SYMBOL (tree), sym);
+      else
+        return FALSE;
     }
 
-    return astHasSymbol(tree->left,sym) ||
-  astHasSymbol(tree->right,sym);
+  return astHasSymbol (tree->left, sym) ||
+    astHasSymbol (tree->right, sym);
 }
 
 /*-----------------------------------------------------------------*/
-/* isConformingBody - the loop body has to conform to a set of rules */
-/* for the loop to be considered reversible read on for rules      */
+/* astHasDeref - return true if the ast has an indirect access     */
 /*-----------------------------------------------------------------*/
-bool isConformingBody (ast *pbody, symbol *sym, ast *body)
+static bool
+astHasDeref (ast * tree)
 {
+  if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
+    return FALSE;
 
-    /* we are going to do a pre-order traversal of the
-       tree && check for the following conditions. (essentially
-       a set of very shallow tests )
-       a) the sym passed does not participate in
-          any arithmetic operation
-       b) There are no function calls
-       c) all jumps are within the body
-       d) address of loop control variable not taken
-       e) if an assignment has a pointer on the
-          left hand side make sure right does not have
-    loop control variable */
-
-    /* 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;
-
-    /* we will walk the body in a pre-order traversal for
-       efficiency sake */
-    switch (pbody->opval.op) {
-    /*------------------------------------------------------------------*/
-    case  '['   :
-  return isConformingBody (pbody->right,sym,body);
-
-  /*------------------------------------------------------------------*/
-    case  PTR_OP:
-    case  '.'   :
-  return TRUE;
-
-  /*------------------------------------------------------------------*/
-    case  INC_OP:  /* incerement operator unary so left only */
-    case  DEC_OP:
-
-  /* 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;
-
-  if (pbody->right                &&
-      IS_AST_SYM_VALUE(pbody->right) &&
-      isSymbolEqual(AST_SYMBOL(pbody->right),sym))
-      return FALSE;
-
-  return TRUE;
+  if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
 
-  /*------------------------------------------------------------------*/
+  return astHasDeref (tree->left) || astHasDeref (tree->right);
+}
 
-    case '*' :  /* can be unary  : if right is null then unary operation */
-    case '+' :
-    case '-' :
-    case  '&':
+/*-----------------------------------------------------------------*/
+/* isConformingBody - the loop body has to conform to a set of     */
+/* rules for the loop to be considered reversible read on for rules*/
+/*-----------------------------------------------------------------*/
+bool
+isConformingBody (ast * pbody, symbol * sym, ast * body)
+{
 
-  /* if right is NULL then unary operation  */
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*  address of                */
-  /*----------------------------*/
-  if ( ! pbody->right ) {
-      if (IS_AST_SYM_VALUE(pbody->left) &&
-    isSymbolEqual(AST_SYMBOL(pbody->left),sym))
+  /* we are going to do a pre-order traversal of the
+     tree && check for the following conditions. (essentially
+     a set of very shallow tests )
+     a) the sym passed does not participate in any arithmetic operation
+     b) There are no function calls
+     c) all jumps are within the body
+     d) address of loop control variable not taken
+     e) if an assignment has a pointer on the left hand side make sure
+        right does not have loop control variable
+  */
+
+  /* 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;
+
+  /* we will walk the body in a pre-order traversal for
+     efficiency sake */
+  switch (pbody->opval.op)
+    {
+/*------------------------------------------------------------------*/
+    case '[':
+      // if the loopvar is used as an index
+      /* 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)
+              && isConformingBody (pbody->left, sym, body);
+
+/*------------------------------------------------------------------*/
+    case PTR_OP:
+    case '.':
+      return TRUE;
+
+/*------------------------------------------------------------------*/
+    case INC_OP:
+    case DEC_OP:
+
+      /* 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;
+
+      if (pbody->right &&
+          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 '+':
+    case '-':
+    case '&':
+
+      /* if right is NULL then unary operation  */
+/*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*  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);
+        }
       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;
+        }
 
 
-  /*------------------------------------------------------------------*/
-    case  '|':
-    case  '^':
-    case  '/':
-    case  '%':
+/*------------------------------------------------------------------*/
+    case '|':
+    case '^':
+    case '/':
+    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 ;
+      if (IS_AST_SYM_VALUE (pbody->left) &&
+          isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+        return FALSE;
 
-  if (IS_AST_SYM_VALUE(pbody->right) &&
-      isSymbolEqual(AST_SYMBOL(pbody->right),sym))
-      return FALSE ;
+      if (IS_AST_SYM_VALUE (pbody->right) &&
+          isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+        return FALSE;
 
-  return isConformingBody(pbody->left,sym,body) &&
-      isConformingBody(pbody->right,sym,body);
+      return isConformingBody (pbody->left, sym, body) &&
+        isConformingBody (pbody->right, sym, body);
 
-    case '~' :
-    case '!' :
+    case '~':
+    case '!':
     case RRC:
     case RLC:
     case GETHBIT:
-  if (IS_AST_SYM_VALUE(pbody->left) &&
-      isSymbolEqual(AST_SYMBOL(pbody->left),sym))
-      return FALSE;
-  return isConformingBody (pbody->left,sym,body);
+    case SWAP:
+      if (IS_AST_SYM_VALUE (pbody->left) &&
+          isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+        return FALSE;
+      return isConformingBody (pbody->left, sym, body);
 
-  /*------------------------------------------------------------------*/
+/*------------------------------------------------------------------*/
 
     case AND_OP:
     case OR_OP:
-    case '>' :
-    case '<' :
+    case '>':
+    case '<':
     case LE_OP:
     case GE_OP:
     case EQ_OP:
     case NE_OP:
-    case '?' :
-    case ':' :
-    case SIZEOF:  /* evaluate wihout code generation */
-
-  return isConformingBody(pbody->left,sym,body) &&
-      isConformingBody(pbody->right,sym,body);
-
-  /*------------------------------------------------------------------*/
-    case '=' :
-
-  /* if left has a pointer & right has loop
-     control variable then we cannot */
-  if (astHasPointer(pbody->left) &&
-      astHasSymbol (pbody->right,sym))
-      return FALSE ;
-  if (astHasVolatile(pbody->left))
-      return FALSE ;
+    case '?':
+    case ':':
+    case SIZEOF:                /* evaluate wihout code generation */
+
+      if (IS_AST_SYM_VALUE (pbody->left) &&
+          isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+        return FALSE;
+
+      if (IS_AST_SYM_VALUE (pbody->right) &&
+          isSymbolEqual (AST_SYMBOL (pbody->right), sym))
+        return FALSE;
+
+      return isConformingBody (pbody->left, sym, body) &&
+        isConformingBody (pbody->right, sym, body);
+
+/*------------------------------------------------------------------*/
+    case '=':
+
+      /* if left has a pointer & right has loop
+         control variable then we cannot */
+      if (astHasPointer (pbody->left) &&
+          astHasSymbol (pbody->right, sym))
+        return FALSE;
+      if (astHasVolatile (pbody->left))
+        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 (IS_AST_SYM_VALUE(pbody->left) &&
-      isSymbolEqual(AST_SYMBOL(pbody->left),sym))
-      return FALSE ;
+      if (astHasVolatile (pbody->left))
+        return FALSE;
 
-  if (astHasVolatile(pbody->left))
-      return FALSE;
+      if (astHasDeref(pbody->right))
+        return FALSE;
 
-  return isConformingBody(pbody->left,sym,body) &&
-      isConformingBody(pbody->right,sym,body);
+      return isConformingBody (pbody->left, sym, body) &&
+        isConformingBody (pbody->right, sym, body);
 
     case MUL_ASSIGN:
     case DIV_ASSIGN:
@@ -1426,48 +2023,52 @@ bool isConformingBody (ast *pbody, symbol *sym, ast *body)
     case LEFT_ASSIGN:
     case SUB_ASSIGN:
     case ADD_ASSIGN:
-      assert("Parser should not have generated this\n");
-
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*      comma operator        */
-  /*----------------------------*/
-    case ',' :
-  return isConformingBody(pbody->left,sym,body) &&
-      isConformingBody(pbody->right,sym,body);
-
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*       function call        */
-  /*----------------------------*/
+      assert ("Parser should not have generated this\n");
+
+/*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*      comma operator        */
+      /*----------------------------*/
+    case ',':
+      return isConformingBody (pbody->left, sym, body) &&
+        isConformingBody (pbody->right, sym, body);
+
+/*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*       function call        */
+      /*----------------------------*/
     case CALL:
-  return FALSE;
+        /* if local & not passed as parameter &
+           not used to find the function then ok */
+        if (sym->level && !astHasSymbol (pbody->right, sym) &&
+            !astHasSymbol (pbody->left, sym))
+          {
+            return TRUE;
+          }
+      return FALSE;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*     return statement       */
-  /*----------------------------*/
+/*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*     return statement       */
+      /*----------------------------*/
     case RETURN:
-  return FALSE ;
+      return FALSE;
 
     case GOTO:
-  if (isLabelInAst (AST_SYMBOL(pbody->left),body))
-      return TRUE ;
-  else
-      return FALSE;
+      if (isLabelInAst (AST_SYMBOL (pbody->left), body))
+        return TRUE;
+      else
+        return FALSE;
     case SWITCH:
-  if (astHasSymbol(pbody->left,sym))
-      return FALSE ;
+      if (astHasSymbol (pbody->left, sym))
+        return FALSE;
 
     default:
-  break;
+      break;
     }
 
-    return isConformingBody(pbody->left,sym,body) &&
-  isConformingBody(pbody->right,sym,body);
-
-
-
+  return isConformingBody (pbody->left, sym, body) &&
+    isConformingBody (pbody->right, sym, body);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1475,2379 +2076,5248 @@ bool 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 isLoopReversible (ast *loop, symbol **loopCntrl,
-           ast **init, ast **end )
+static bool
+isLoopReversible (ast * loop, symbol ** loopCntrl,
+                  ast ** init, ast ** end)
 {
-    /* if option says don't do it then don't */
-    if (optimize.noLoopReverse)
-  return 0;
-    /* there are several tests to determine this */
-
-    /* for loop has to be of the form
-       for ( <sym> = <const1> ;
-             [<sym> < <const2>]  ;
-       [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
-       forBody */
-    if (! isLoopCountable (AST_FOR(loop,initExpr),
-         AST_FOR(loop,condExpr),
-         AST_FOR(loop,loopExpr),
-         loopCntrl,init,end))
-  return 0;
+  /* if option says don't do it then don't */
+  if (optimize.noLoopReverse)
+    return 0;
+  /* there are several tests to determine this */
+
+  /* for loop has to be of the form
+     for ( <sym> = <const1> ;
+     [<sym> < <const2>]  ;
+     [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
+     forBody */
+  if (!isLoopCountable (AST_FOR (loop, initExpr),
+                        AST_FOR (loop, condExpr),
+                        AST_FOR (loop, loopExpr),
+                        loopCntrl, init, end))
+    return 0;
 
-    /* now do some serious checking on the body of the loop
-     */
+  /* now do some serious checking on the body of the loop
+   */
 
-    return isConformingBody(loop->left,*loopCntrl,loop->left);
+  return isConformingBody (loop->left, *loopCntrl, loop->left);
 
 }
 
 /*-----------------------------------------------------------------*/
 /* replLoopSym - replace the loop sym by loop sym -1               */
 /*-----------------------------------------------------------------*/
-static void replLoopSym ( ast *body, symbol *sym)
+static void
+replLoopSym (ast * body, symbol * sym)
 {
-    /* reached end */
-    if (!body || IS_AST_LINK(body))
-  return ;
+  /* reached end */
+  if (!body || IS_AST_LINK (body))
+    return;
 
-    if (IS_AST_SYM_VALUE(body)) {
+  if (IS_AST_SYM_VALUE (body))
+    {
 
-  if (isSymbolEqual(AST_SYMBOL(body),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 (constCharVal (1));
 
-  }
+        }
 
-  return;
+      return;
 
     }
 
-    replLoopSym(body->left,sym);
-    replLoopSym(body->right,sym);
+  replLoopSym (body->left, sym);
+  replLoopSym (body->right, sym);
 
 }
 
 /*-----------------------------------------------------------------*/
 /* reverseLoop - do the actual loop reversal                       */
 /*-----------------------------------------------------------------*/
-ast *reverseLoop (ast *loop, symbol *sym, ast *init, ast *end)
+ast *
+reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
 {
-    ast *rloop ;
-
-    /* create the following tree
-    <sym> = loopCount ;
-   for_continue:
-          forbody
-    <sym> -= 1;
-    if (sym) goto for_continue ;
-    <sym> = 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));
-
-    replLoopSym(loop->left, sym);
-
-    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 ))));
-
-    return decorateType(rloop);
+  ast *rloop;
+
+  /* create the following tree
+     <sym> = loopCount ;
+     for_continue:
+     forbody
+     <sym> -= 1;
+     if (sym) goto for_continue ;
+     <sym> = 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));
+
+  replLoopSym (loop->left, sym);
+  setAstFileLine (rloop, init->filename, 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 (constCharVal (1))),
+                                                  rloop))));
+
+  rloop->lineno=init->lineno;
+  return decorateType (rloop, RESULT_TYPE_NONE);
 
 }
 
-#define DEMAND_INTEGER_PROMOTION
-
-#ifdef DEMAND_INTEGER_PROMOTION
-
 /*-----------------------------------------------------------------*/
-/* walk a tree looking for the leaves. Add a typecast to the given */
-/* type to each value leaf node.           */
+/* searchLitOp - search tree (*ops only) for an ast with literal */
 /*-----------------------------------------------------------------*/
-void pushTypeCastToLeaves(sym_link *type, ast *node, ast **parentPtr)
+static ast *
+searchLitOp (ast *tree, ast **parent, const char *ops)
 {
-    if (!node)
-    {
-        /* WTF? We should never get here. */
-        return;
-    }
+  ast *ret;
 
-    if (!node->left && !node->right)
+  if (tree && optimize.global_cse)
     {
-        /* We're at a leaf; if it's a value, apply the typecast */
-        if (node->type == EX_VALUE && IS_INTEGRAL(TTYPE(node)))
+      /* is there a literal operand? */
+      if (tree->right &&
+          IS_AST_OP(tree->right) &&
+          tree->right->right &&
+          (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
         {
-            *parentPtr = decorateType(newNode(CAST,
-                            newAst_LINK(copyLinkChain(type)),
-                            node));
-  }
-    }
-    else
-    {
-      if (node->left)
-      {
-          pushTypeCastToLeaves(type, node->left, &(node->left));
-      }
-      if (node->right)
-      {
-            pushTypeCastToLeaves(type, node->right, &(node->right));
-      }
+          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 == (unsigned)ops[0] || tree->left->opval.op == (unsigned)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;
 }
 
-#endif
-
 /*-----------------------------------------------------------------*/
-/* Given an assignment operation in a tree, determine if the LHS   */
-/* (the result) has a different (integer) type than the RHS.     */
-/* If so, walk the RHS and add a typecast to the type of the LHS   */
-/* to all leaf nodes.              */
+/* getResultFromType                                               */
 /*-----------------------------------------------------------------*/
-void propAsgType(ast *tree)
+RESULT_TYPE
+getResultTypeFromType (sym_link *type)
 {
-#ifdef DEMAND_INTEGER_PROMOTION
-    if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree)))
+  /* type = getSpec (type); */
+  if (IS_BIT (type))
+    return RESULT_TYPE_BIT;
+  if (IS_BITFIELD (type))
     {
-      /* Nothing to do here... */
-      return;
-    }
+      int blen = SPEC_BLEN (type);
 
-    if (getSize(LTYPE(tree)) > getSize(RTYPE(tree)))
-    {
-        pushTypeCastToLeaves(LTYPE(tree), tree->right, &(tree->right));
+      if (blen <= 1)
+        return RESULT_TYPE_BIT;
+      if (blen <= 8)
+        return RESULT_TYPE_CHAR;
+      return RESULT_TYPE_INT;
     }
-#else
-    (void)tree;
-#endif
+  if (IS_CHAR (type))
+    return RESULT_TYPE_CHAR;
+  if (IS_INT (type) && !IS_LONG (type))
+    return RESULT_TYPE_INT;
+  return RESULT_TYPE_OTHER;
 }
 
 /*-----------------------------------------------------------------*/
-/* decorateType - compute type for this tree also does type cheking*/
-/*          this is done bottom up, since type have to flow upwards*/
-/*          it also does constant folding, and paramater checking  */
+/* addCast - adds casts to a type specified by RESULT_TYPE         */
 /*-----------------------------------------------------------------*/
-ast *decorateType (ast *tree)
+static ast *
+addCast (ast *tree, RESULT_TYPE resultType, bool promote)
 {
-    int parmNumber ;
-    sym_link *p;
-
-    if ( ! tree )
-  return tree ;
+  sym_link *newLink;
+  bool upCasted = FALSE;
 
-    /* if already has type then do nothing */
-    if ( tree->decorated )
-  return tree ;
+  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_IFX:
+      case RESULT_TYPE_OTHER:
+        if (!promote ||
+            /* return type is ifx, long, float: promote char to int */
+            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->filename = tree->right->filename;
+  tree->lineno = tree->right->lineno;
+  /* keep unsigned type during cast to smaller type,
+     but not when promoting from char to int */
+  if (!upCasted)
+    SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
+  return decorateType (tree, resultType);
+}
 
-    tree->decorated = 1;
+/*-----------------------------------------------------------------*/
+/* 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:
+      case '!':
+      case '=':
+      case '?':
+      case ':':
+      case '|':
+      case '^':
+      case '~':
+      case LEFT_OP:
+      case LABEL:
+        return resultType;
+      case '*':
+      case '+':
+      case '-':
+        if ((IS_AST_VALUE (tree->left)  && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
+            (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
+          return RESULT_TYPE_NONE;
+        return resultType;
+      case '&':
+        if (!tree->right)
+          /* can be unary */
+          return RESULT_TYPE_NONE;
+        else
+          return resultType;
+      case IFX:
+        return RESULT_TYPE_IFX;
+      default:
+        return RESULT_TYPE_NONE;
+    }
+}
 
-    /* print the line          */
-    /* if not block & function */
-    if ( tree->type == EX_OP &&
-   ( tree->opval.op != FUNCTION  &&
-     tree->opval.op != BLOCK     &&
-     tree->opval.op != NULLOP    )) {
-  filename = tree->filename ;
-  lineno = tree->lineno ;
+/*-----------------------------------------------------------------*/
+/* 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;
     }
+}
 
-    /* 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 ))
-  return tree ;
+/*------------------------------------------------------------------*/
+/* 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;
 
-    /*------------------------------------------------------------------*/
-    /*----------------------------*/
-    /*   leaf has been reached    */
-    /*----------------------------*/
-    /* if this is of type value */
-    /* just get the type        */
-    if ( tree->type == EX_VALUE ) {
+  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;
+    }
 
-  if ( IS_LITERAL(tree->opval.val->etype) ) {
+  gatherImplicitVariables(tree->left, block);
+  gatherImplicitVariables(tree->right, block);
+}
 
-      /* if this is a character array then declare it */
-      if (IS_ARRAY(tree->opval.val->type))
-    tree->opval.val = stringToSymbol(tree->opval.val);
+/*--------------------------------------------------------------------*/
+/* 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;
 
-      /* otherwise just copy the type information */
-      COPYTYPE(TTYPE(tree),TETYPE(tree),tree->opval.val->type);
-      if (funcInChain(tree->opval.val->type)) {
-        tree->hasVargs = tree->opval.val->sym->hasVargs;
-        tree->args = copyValueChain(tree->opval.val->sym->args) ;
-      }
-      return tree ;
-  }
+  if (!tree)
+    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 already has type then do nothing */
+  if (tree->decorated)
+    return tree;
 
-      /* if impilicit i.e. struct/union member then no type */
-      if (tree->opval.val->sym->implicit )
-        TTYPE(tree) = TETYPE(tree) = NULL ;
+  tree->decorated = 1;
 
-      else {
+#if 0
+  /* print the line          */
+  /* if not block & function */
+  if (tree->type == EX_OP &&
+      (tree->opval.op != FUNCTION &&
+       tree->opval.op != BLOCK &&
+       tree->opval.op != NULLOP))
+    {
+      filename = tree->filename;
+      lineno = tree->lineno;
+    }
+#endif
 
-        /* else copy the type */
-        COPYTYPE(TTYPE(tree),TETYPE(tree),tree->opval.val->type);
+  /* 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))
+    return tree;
 
-        /* and mark it as referenced */
-        tree->opval.val->sym->isref = 1;
-        /* if this is of type function or function pointer */
-        if (funcInChain(tree->opval.val->type)) {
-          tree->hasVargs = tree->opval.val->sym->hasVargs;
-          tree->args = copyValueChain(tree->opval.val->sym->args) ;
+/*------------------------------------------------------------------*/
+/*----------------------------*/
+/*   leaf has been reached    */
+/*----------------------------*/
+  filename = tree->filename;
+  lineno = tree->lineno;
+  /* if this is of type value */
+  /* just get the type        */
+  if (tree->type == EX_VALUE)
+    {
+      if (IS_LITERAL (tree->opval.val->etype))
+        {
+          /* if this is a character array then declare it */
+          if (IS_ARRAY (tree->opval.val->type))
+            tree->opval.val = stringToSymbol (tree->opval.val);
 
+          /* otherwise just copy the type information */
+          COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
+          return tree;
         }
-      }
-    }
-  }
 
-  return tree ;
-    }
+      if (tree->opval.val->sym)
+        {
+          /* if the undefined flag is set then give error message */
+          if (tree->opval.val->sym->undefined)
+            {
+              werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
+              /* assume int */
+              TTYPE (tree) = TETYPE (tree) =
+                tree->opval.val->type = tree->opval.val->sym->type =
+                tree->opval.val->etype = tree->opval.val->sym->etype =
+                copyLinkChain (INTTYPE);
+            }
+          else if (tree->opval.val->sym->implicit)
+            {
+              /* if implicit i.e. struct/union member then no type */
+              TTYPE (tree) = TETYPE (tree) = NULL;
+            }
+          else
+            {
+              /* copy the type from the value into the ast */
+              COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
+
+              /* and mark the symbol as referenced */
+              tree->opval.val->sym->isref = 1;
+            }
+        }
+      else
+        wassert(0); /* unreached: all values are literals or symbols */
 
-    /* if type link for the case of cast */
-    if ( tree->type == EX_LINK ) {
-  COPYTYPE(TTYPE(tree),TETYPE(tree),tree->opval.lnk);
-  return tree ;
+      return tree;
     }
 
+  /* if type link for the case of cast */
+  if (tree->type == EX_LINK)
     {
-  ast *dtl, *dtr;
+      COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
+      return tree;
+    }
 
-  dtl = decorateType (tree->left);
-  dtr = decorateType (tree->right);
+  {
+    ast *dtl, *dtr;
 
-  /* this is to take care of situations
-     when the tree gets rewritten */
-  if (dtl != tree->left)
-      tree->left = dtl;
-  if (dtr != tree->right)
-      tree->right = dtr;
-    }
+    #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
 
-    /* depending on type of operator do */
+    /* Before decorating the left branch we've to decide in dependence
+       upon tree->opval.op, if resultType can be propagated */
+    resultTypeProp = resultTypePropagate (tree, resultType);
 
-    switch   (tree->opval.op) {
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*        array node          */
-  /*----------------------------*/
-    case  '['   :
+    if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
+      dtl = decorateType (tree->left, RESULT_TYPE_IFX);
+    else
+      dtl = decorateType (tree->left, resultTypeProp);
 
-  /* determine which is the array & which the index */
-  if ((IS_ARRAY(RTYPE(tree)) || IS_PTR(RTYPE(tree))) && IS_INTEGRAL(LTYPE(tree))) {
+    /* 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;
+          }
+      }
 
-      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);
 
-  /* 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 ;
-  }
+    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;
+        case SIZEOF:
+          /* don't allocate string if it is a sizeof argument */
+          ++noAlloc;
+          dtr = decorateType (tree->right, resultTypeProp);
+          --noAlloc;
+          break;
+        default:
+          dtr = decorateType (tree->right, resultTypeProp);
+          break;
+      }
 
-  /* check if the type of the idx */
-  if (!IS_INTEGRAL(RTYPE(tree))) {
-      werror(E_IDX_NOT_INT);
-      goto errorTreeReturn ;
+    /* this is to take care of situations
+       when the tree gets rewritten */
+    if (dtl != tree->left)
+      tree->left = dtl;
+    if (dtr != tree->right)
+      tree->right = dtr;
+    if ((dtl && dtl->isError) || (dtr && dtr->isError))
+      return tree;
   }
 
-  /* if the left is an rvalue then error */
-  if (LRVAL(tree)) {
-      werror(E_LVALUE_REQUIRED,"array access");
-      goto errorTreeReturn ;
-  }
-  RRVAL(tree) = 1;
-  COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree)->next);
-  return tree;
+  /* depending on type of operator do */
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*      struct/union          */
-  /*----------------------------*/
-    case  '.'   :
-  /* if this is not a structure */
-  if (!IS_STRUCT(LTYPE(tree))) {
-      werror(E_STRUCT_UNION,".");
-      goto errorTreeReturn ;
-  }
-  TTYPE(tree) = structElemType (LTYPE(tree),
-              (tree->right->type == EX_VALUE ?
-               tree->right->opval.val : NULL ),&tree->args);
-  TETYPE(tree) = getSpec(TTYPE(tree));
-  return tree ;
+  switch (tree->opval.op)
+    {
+        /*------------------------------------------------------------------*/
+        /*----------------------------*/
+        /*        array node          */
+        /*----------------------------*/
+    case '[':
+
+      /* first check if this is a array or a pointer */
+      if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
+        {
+          werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
+          goto errorTreeReturn;
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*    struct/union pointer    */
-  /*----------------------------*/
-    case  PTR_OP:
-  /* if not pointer to a structure */
-  if (!IS_PTR(LTYPE(tree)))  {
-      werror(E_PTR_REQD);
-      goto errorTreeReturn ;
-  }
+      /* check if the type of the idx */
+      if (!IS_INTEGRAL (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
+          goto errorTreeReturn;
+        }
 
-  if (!IS_STRUCT(LTYPE(tree)->next))  {
-      werror(E_STRUCT_UNION,"->");
-      goto errorTreeReturn ;
-  }
+      /* if the left is an rvalue then error */
+      if (LRVAL (tree))
+        {
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
+          goto errorTreeReturn;
+        }
 
-  TTYPE(tree) = structElemType (LTYPE(tree)->next,
-              (tree->right->type == EX_VALUE ?
-               tree->right->opval.val : NULL ),&tree->args);
-  TETYPE(tree) = getSpec(TTYPE(tree));
-  return tree ;
+      if (IS_LITERAL (RTYPE (tree)))
+        {
+          int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
+          int arraySize = DCL_ELEM (LTYPE (tree));
+          if (arraySize && arrayIndex >= arraySize)
+            {
+              werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
+            }
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*  ++/-- operation           */
-  /*----------------------------*/
-    case  INC_OP:  /* incerement operator unary so left only */
-    case  DEC_OP:
-  {
-      sym_link *ltc = (tree->right ? RTYPE(tree) : LTYPE(tree) );
-      COPYTYPE(TTYPE(tree),TETYPE(tree),ltc);
-      if (!tree->initMode && IS_CONSTANT(TETYPE(tree)))
-    werror(E_CODE_WRITE,"++/--");
+      RRVAL (tree) = 1;
+      COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
+      SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
+      return tree;
 
-      if (tree->right)
-    RLVAL(tree) = 1;
-      else
-    LLVAL(tree) = 1;
-      return tree ;
-  }
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*      struct/union          */
+      /*----------------------------*/
+    case '.':
+      /* if this is not a structure */
+      if (!IS_STRUCT (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
+          goto errorTreeReturn;
+        }
+      TTYPE (tree) = structElemType (LTYPE (tree),
+                                     (tree->right->type == EX_VALUE ?
+                               tree->right->opval.val : NULL));
+      TETYPE (tree) = getSpec (TTYPE (tree));
+      return tree;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*  bitwise and               */
-  /*----------------------------*/
-    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(E_CONTINUE,"left & right types are ");
-    printTypeChain(LTYPE(tree),stderr);
-    fprintf(stderr,",");
-    printTypeChain(RTYPE(tree),stderr);
-    fprintf(stderr,"\n");
-    goto errorTreeReturn ;
-      }
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*    struct/union pointer    */
+      /*----------------------------*/
+    case PTR_OP:
+      /* if not pointer to a structure */
+      if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
+          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)),'&');
+      if (!IS_STRUCT (LTYPE (tree)->next))
+        {
+          werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
+          goto errorTreeReturn;
+        }
 
-    tree->right = tree->left = NULL;
-    TETYPE(tree) = tree->opval.val->etype ;
-    TTYPE(tree) =  tree->opval.val->type;
-    return tree ;
+      TTYPE (tree) = structElemType (LTYPE (tree)->next,
+                                     (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;
+      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;
       }
 
-      /* see if this is a GETHBIT operation if yes
-         then return that */
+      /* 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                    */
+      #if 0
+      if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
+          && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
+        {
+            /* If defined    struct type at addr var
+               then rewrite  (&struct var)->member
+               as            temp
+               and define    membertype at (addr+offsetof(struct var,member)) temp
+            */
+            symbol *sym;
+            symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
+                                                AST_SYMBOL(tree->right));
+
+            sym = newSymbol(genSymName (0), 0);
+            sym->type = TTYPE (tree);
+            sym->etype = getSpec(sym->type);
+            sym->lineDef = tree->lineno;
+            sym->cdef = 1;
+            sym->isref = 1;
+            SPEC_STAT (sym->etype) = 1;
+            SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
+                                     + element->offset;
+            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;
+            tree->type = EX_VALUE;
+            tree->left = NULL;
+            tree->right = NULL;
+        }
+      #endif
+
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*  ++/-- operation           */
+      /*----------------------------*/
+    case INC_OP:
+    case DEC_OP:
       {
-    ast *otree = optimizeGetHbit(tree);
+        sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
+        COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
+        if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
+          werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
 
-    if (otree != tree)
-        return decorateType(otree);
+        if (tree->right)
+          RLVAL (tree) = 1;
+        else
+          LLVAL (tree) = 1;
+        return tree;
       }
 
-      /* if right or left is literal then result of that type*/
-      if (IS_LITERAL(RTYPE(tree))) {
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*  bitwise and               */
+      /*----------------------------*/
+    case '&':                   /* can be unary   */
+      /* if right is NULL then unary operation  */
+      if (tree->right)          /* not an unary operation */
+        {
 
-    TTYPE(tree) = copyLinkChain(RTYPE(tree));
-    TETYPE(tree) = getSpec(TTYPE(tree));
-    SPEC_SCLS(TETYPE(tree)) = S_AUTO;
-      }
-      else {
-    if (IS_LITERAL(LTYPE(tree))) {
-        TTYPE(tree) = copyLinkChain(LTYPE(tree));
-        TETYPE(tree) = getSpec(TTYPE(tree));
-        SPEC_SCLS(TETYPE(tree)) = S_AUTO;
+          if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
+            {
+              werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
+              werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
+              printTypeChain (LTYPE (tree), stderr);
+              fprintf (stderr, ",");
+              printTypeChain (RTYPE (tree), stderr);
+              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 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;
+        }
 
-    }
-    else {
-        TTYPE(tree) =
-      computeType (LTYPE(tree), RTYPE(tree));
-        TETYPE(tree) = getSpec(TTYPE(tree));
-    }
-      }
-      LRVAL(tree) = RRVAL(tree) = 1;
-      return tree ;
-  }
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*  address of                */
+      /*----------------------------*/
+      p = newLink (DECLARATOR);
+      /* if bit field then error */
+      if (IS_BITVAR (tree->left->etype))
+        {
+          werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
+          goto errorTreeReturn;
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*  address of                */
-  /*----------------------------*/
-  p = newLink();
-  p->class = DECLARATOR;
-  /* if bit field then error */
-  if (IS_BITVAR(tree->left->etype)) {
-      werror (E_ILLEGAL_ADDR,"addrress of bit variable");
-      goto errorTreeReturn ;
-  }
+      if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
+        {
+          werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
+          goto errorTreeReturn;
+        }
 
-  if (SPEC_SCLS(tree->left->etype)== S_REGISTER ) {
-      werror (E_ILLEGAL_ADDR,"address of register variable");
-      goto errorTreeReturn;
-  }
+      if (IS_FUNC (LTYPE (tree)))
+        {
+          // this ought to be ignored
+          return (tree->left);
+        }
 
-  if (IS_FUNC(LTYPE(tree))) {
-      werror(E_ILLEGAL_ADDR,"address of function");
-      goto errorTreeReturn ;
-  }
+      if (IS_LITERAL(LTYPE(tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
+          goto errorTreeReturn;
+        }
 
-  if (LRVAL(tree)) {
-      werror(E_LVALUE_REQUIRED,"address of");
-      goto errorTreeReturn ;
-  }
-  if (SPEC_SCLS(tree->left->etype) == S_CODE) {
-      DCL_TYPE(p) = CPOINTER ;
-      DCL_PTR_CONST(p) = port->mem.code_ro;
-  }
-  else
-      if (SPEC_SCLS(tree->left->etype) == S_XDATA)
-    DCL_TYPE(p) = FPOINTER;
-      else
-    if (SPEC_SCLS(tree->left->etype) == S_XSTACK )
-        DCL_TYPE(p) = PPOINTER ;
-    else
-        if (SPEC_SCLS(tree->left->etype) == S_IDATA)
-      DCL_TYPE(p) = IPOINTER ;
-        else
-      if (SPEC_SCLS(tree->left->etype) == S_EEPROM)
-          DCL_TYPE(p) = EEPPOINTER ;
+     if (LRVAL (tree))
+        {
+          werrorfl (tree->filename, tree->lineno, 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;
+      else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
+        DCL_TYPE (p) = FPOINTER;
+      else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
+        DCL_TYPE (p) = PPOINTER;
+      else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
+        DCL_TYPE (p) = IPOINTER;
+      else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
+        DCL_TYPE (p) = EEPPOINTER;
+      else if (SPEC_OCLS(tree->left->etype))
+          DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
       else
-          DCL_TYPE(p) = POINTER ;
-
-  if (IS_AST_SYM_VALUE(tree->left)) {
-      AST_SYMBOL(tree->left)->addrtaken = 1;
-      AST_SYMBOL(tree->left)->allocreq = 1;
-  }
+          DCL_TYPE (p) = POINTER;
 
-  p->next = LTYPE(tree);
-  TTYPE(tree) = p;
-  TETYPE(tree) = getSpec(TTYPE(tree));
-  DCL_PTR_CONST(p) = SPEC_CONST(TETYPE(tree));
-  DCL_PTR_VOLATILE(p) = SPEC_VOLATILE(TETYPE(tree));
-  LLVAL(tree) = 1;
-  TLVAL(tree) = 1;
-  return tree ;
+      if (IS_AST_SYM_VALUE (tree->left))
+        {
+          AST_SYMBOL (tree->left)->addrtaken = 1;
+          AST_SYMBOL (tree->left)->allocreq = 1;
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*  bitwise or                */
-  /*----------------------------*/
-    case  '|':
-  /* if the rewrite succeeds then don't go any furthur */
-  {
-      ast *wtree = optimizeRRCRLC ( tree );
-      if (wtree != tree)
-    return decorateType(wtree) ;
-  }
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*  bitwise xor               */
-  /*----------------------------*/
-    case  '^':
-  if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree))) {
-      werror(E_BITWISE_OP);
-      werror(E_CONTINUE,"left & right types are ");
-      printTypeChain(LTYPE(tree),stderr);
-      fprintf(stderr,",");
-      printTypeChain(RTYPE(tree),stderr);
-      fprintf(stderr,"\n");
-      goto errorTreeReturn ;
-  }
+      p->next = LTYPE (tree);
+      TTYPE (tree) = p;
+      TETYPE (tree) = getSpec (TTYPE (tree));
+      LLVAL (tree) = 1;
+      TLVAL (tree) = 1;
 
-  /* 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 ;
-  }
-  LRVAL(tree) = RRVAL(tree) = 1;
-  TETYPE(tree) = getSpec (TTYPE(tree) =
-        computeType(LTYPE(tree),
-              RTYPE(tree)));
+      #if 0
+      if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
+          && 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),
+                                    valueFromLit(element->offset));
+          tree->left = NULL;
+          tree->right = NULL;
+          tree->type = EX_VALUE;
+          tree->values.literalFromCast = 1;
+        }
+      #endif
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*  division                  */
-  /*----------------------------*/
-    case  '/':
-  if (!IS_ARITHMETIC(LTYPE(tree)) || !IS_ARITHMETIC(RTYPE(tree))) {
-      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 ;
-  }
-  LRVAL(tree) = RRVAL(tree) = 1;
-  TETYPE(tree) = getSpec (TTYPE(tree) =
-        computeType(LTYPE(tree),
-              RTYPE(tree)));
-  return tree;
+      return tree;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*            modulus         */
-  /*----------------------------*/
-    case  '%':
-  if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree))) {
-      werror(E_BITWISE_OP);
-      werror(E_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 ;
-  }
-  LRVAL(tree) = RRVAL(tree) = 1;
-  TETYPE(tree) = getSpec (TTYPE(tree) =
-        computeType(LTYPE(tree),
-              RTYPE(tree)));
-  return tree;
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*  bitwise or                */
+      /*----------------------------*/
+    case '|':
+      /* if the rewrite succeeds then don't go any further */
+      {
+        ast *wtree = optimizeRRCRLC (tree);
+        if (wtree != tree)
+          return decorateType (wtree, RESULT_TYPE_NONE);
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*  address dereference       */
-  /*----------------------------*/
-    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 ;
+        wtree = optimizeSWAP (tree);
+        if (wtree != tree)
+          return decorateType (wtree, RESULT_TYPE_NONE);
       }
 
-      if (LRVAL(tree)) {
-    werror(E_LVALUE_REQUIRED,"pointer deref");
-    goto errorTreeReturn ;
-      }
-      TTYPE(tree) = copyLinkChain ((IS_PTR(LTYPE(tree)) || IS_ARRAY(LTYPE(tree))) ?
-           LTYPE(tree)->next : NULL );
-      TETYPE(tree) = getSpec(TTYPE(tree));
-      tree->args = tree->left->args ;
-      tree->hasVargs = tree->left->hasVargs ;
-      SPEC_CONST(TETYPE(tree)) = DCL_PTR_CONST(LTYPE(tree));
-      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;
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*      multiplication        */
-  /*----------------------------*/
-  if (!IS_ARITHMETIC(LTYPE(tree)) || !IS_ARITHMETIC(RTYPE(tree))) {
-      werror(E_INVALID_OP,"multiplication");
-      goto errorTreeReturn ;
-  }
+      /* if right is a literal and */
+      /* 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)
+            {
+              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)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
+          werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
+          printTypeChain (LTYPE (tree), stderr);
+          fprintf (stderr, ",");
+          printTypeChain (RTYPE (tree), stderr);
+          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 = valMult (valFromType(LETYPE(tree)),
-               valFromType(RETYPE(tree)));
-      tree->right = tree->left = NULL;
-      TETYPE(tree) = getSpec(TTYPE(tree) =
-           tree->opval.val->type);
-      return 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;
+        }
 
-  /* 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 left is a literal exchange left & right */
+      if (IS_LITERAL (LTYPE (tree)))
+        {
+          ast *tTree = tree->left;
+          tree->left = tree->right;
+          tree->right = tTree;
+        }
 
-  LRVAL(tree) = RRVAL(tree) = 1;
-  TETYPE(tree) = getSpec (TTYPE(tree) =
-        computeType(LTYPE(tree),
-              RTYPE(tree)));
-  return tree ;
+      /* 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)) &&
+          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);
+            }
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*    unary '+' operator      */
-  /*----------------------------*/
-    case '+' :
-  /* if unary plus */
-  if ( ! tree->right ) {
-      if (!IS_INTEGRAL(LTYPE(tree))) {
-    werror(E_UNARY_OP,'+');
-    goto errorTreeReturn ;
-      }
+      LRVAL (tree) = RRVAL (tree) = 1;
 
-      /* 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 ;
-  }
+      TTYPE (tree) = computeType (LTYPE (tree),
+                                  RTYPE (tree),
+                                  resultType,
+                                  tree->opval.op);
+      TETYPE (tree) = getSpec (TTYPE (tree));
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*      addition              */
-  /*----------------------------*/
+      return 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 ;
-  }
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*  division                  */
+      /*----------------------------*/
+    case '/':
+      if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, 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;
+        }
 
-  if (!IS_ARITHMETIC(LTYPE(tree)) &&
-      !IS_PTR(LTYPE(tree)) && !IS_ARRAY(LTYPE(tree))) {
-      werror(E_PLUS_INVALID,"+");
-      goto errorTreeReturn ;
-  }
+      LRVAL (tree) = RRVAL (tree) = 1;
 
-  if (!IS_ARITHMETIC(RTYPE(tree)) &&
-      !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 ;
-  }
+      TETYPE (tree) = getSpec (TTYPE (tree) =
+                               computeType (LTYPE (tree),
+                                            RTYPE (tree),
+                                            resultType,
+                                            tree->opval.op));
 
-  /* 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 ;
-  }
+      /* 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_TARGET_ULONG) ulFromVal (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->filename = tree->filename;
+                  litTree->right->lineno = tree->lineno;
+
+                  tree->right->opval.val = constCharVal (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);
+                }
+            }
+        }
 
-  LRVAL(tree) = RRVAL(tree) = 1;
-  /* if the left is a pointer */
-  if (IS_PTR(LTYPE(tree)))
-      TETYPE(tree) = getSpec(TTYPE(tree) =
-           LTYPE(tree));
-  else
-      TETYPE(tree) = getSpec(TTYPE(tree) =
-           computeType(LTYPE(tree),
-                 RTYPE(tree)));
-  return tree ;
+      return tree;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*      unary '-'             */
-  /*----------------------------*/
-    case '-' :  /* can be unary   */
-  /* if right is null then unary */
-  if ( ! tree->right ) {
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*            modulus         */
+      /*----------------------------*/
+    case '%':
+      if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
+          werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
+          printTypeChain (LTYPE (tree), stderr);
+          fprintf (stderr, ",");
+          printTypeChain (RTYPE (tree), stderr);
+          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;
+        }
+      LRVAL (tree) = RRVAL (tree) = 1;
+      TETYPE (tree) = getSpec (TTYPE (tree) =
+                               computeType (LTYPE (tree),
+                                            RTYPE (tree),
+                                            resultType,
+                                            tree->opval.op));
+      return tree;
 
-      if (!IS_ARITHMETIC(LTYPE(tree))) {
-    werror(E_UNARY_OP,tree->opval.op);
-    goto errorTreeReturn ;
-      }
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*  address dereference       */
+      /*----------------------------*/
+    case '*':                   /* can be unary  : if right is null then unary operation */
+      if (!tree->right)
+        {
+          if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
+            {
+              werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
+              goto errorTreeReturn;
+            }
+
+          if (LRVAL (tree))
+            {
+              werrorfl (tree->filename, tree->lineno, 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;
+              break;
+            case ARRAY:
+            case FUNCTION:
+              break;
+          }
+          return tree;
+        }
 
-      /* 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 ;
-      }
-      LRVAL(tree) = 1;
-      TTYPE(tree) =  LTYPE(tree);
-      return tree ;
-  }
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*      multiplication        */
+      /*----------------------------*/
+      if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
+          goto errorTreeReturn;
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*    subtraction             */
-  /*----------------------------*/
+      /* 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;
+        }
 
-  if (!(IS_PTR(LTYPE(tree)) ||
-        IS_ARRAY(LTYPE(tree)) ||
-        IS_ARITHMETIC(LTYPE(tree)))) {
-      werror(E_PLUS_INVALID,"-");
-      goto errorTreeReturn ;
-  }
+      /* 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 (!(IS_PTR(RTYPE(tree)) ||
-        IS_ARRAY(RTYPE(tree)) ||
-        IS_ARITHMETIC(RTYPE(tree)))) {
-      werror(E_PLUS_INVALID,"-");
-      goto errorTreeReturn ;
-  }
+      /* 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)
+            {
+              DEBUG_CF("mul")
+              ast *tTree = litTree->left;
+              litTree->left = tree->right;
+              tree->right = tTree;
+              /* both operands in litTree are literal now */
+              decorateType (parent, resultType);
+            }
+        }
 
-  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 ;
-  }
+      LRVAL (tree) = RRVAL (tree) = 1;
+      tree->left  = addCast (tree->left,  resultTypeProp, FALSE);
+      tree->right = addCast (tree->right, resultTypeProp, FALSE);
+      TETYPE (tree) = getSpec (TTYPE (tree) =
+                                   computeType (LTYPE (tree),
+                                                RTYPE (tree),
+                                                resultType,
+                                                tree->opval.op));
 
-  /* 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 ;
-  }
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*    unary '+' operator      */
+      /*----------------------------*/
+    case '+':
+      /* if unary plus */
+      if (!tree->right)
+        {
+          if (!IS_ARITHMETIC (LTYPE (tree)))
+            {
+              werrorfl (tree->filename, tree->lineno, 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;
+        }
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*      addition              */
+      /*----------------------------*/
+
+      /* 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))))
+        {
+          werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
+          goto errorTreeReturn;
+        }
+
+      if (!IS_ARITHMETIC (LTYPE (tree)) &&
+          !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
+          goto errorTreeReturn;
+        }
+
+      if (!IS_ARITHMETIC (RTYPE (tree)) &&
+          !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, 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->left  = addCast (tree->left,  resultTypeProp, TRUE);
+          tree->right = addCast (tree->right, resultTypeProp, TRUE);
+          tree->opval.val = valPlus (valFromType (LETYPE (tree)),
+                                     valFromType (RETYPE (tree)));
+          tree->right = tree->left = NULL;
+          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;
+        }
+
+      /* 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 */
+                  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));
+      else
+        {
+          tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
+          tree->right = addCast (tree->right, resultTypeProp, TRUE);
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                     computeType (LTYPE (tree),
+                                                  RTYPE (tree),
+                                                  resultType,
+                                                  tree->opval.op));
+        }
 
-  /* 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;
-  }
 
-  /* 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();
-  else
-      /* 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));
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*      unary '-'             */
+      /*----------------------------*/
+    case '-':                   /* can be unary   */
+      /* if right is null then unary */
+      if (!tree->right)
+        {
+
+          if (!IS_ARITHMETIC (LTYPE (tree)))
+            {
+              werrorfl (tree->filename, tree->lineno, 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, resultTypeProp, TRUE);
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                     computeType (LTYPE (tree),
+                                                  NULL,
+                                                  resultType,
+                                                  tree->opval.op));
+          LRVAL (tree) = 1;
+          return tree;
+        }
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*    subtraction             */
+      /*----------------------------*/
+
+      if (!(IS_PTR (LTYPE (tree)) ||
+            IS_ARRAY (LTYPE (tree)) ||
+            IS_ARITHMETIC (LTYPE (tree))))
+        {
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
+          goto errorTreeReturn;
+        }
+
+      if (!(IS_PTR (RTYPE (tree)) ||
+            IS_ARRAY (RTYPE (tree)) ||
+            IS_ARITHMETIC (RTYPE (tree))))
+        {
+          werrorfl (tree->filename, tree->lineno, 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))))
+        {
+          werrorfl (tree->filename, tree->lineno, 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->left  = addCast (tree->left,  resultTypeProp, TRUE);
+          tree->right = addCast (tree->right, resultTypeProp, TRUE);
+          tree->opval.val = valMinus (valFromType (LETYPE (tree)),
+                                      valFromType (RETYPE (tree)));
+          tree->right = tree->left = NULL;
+          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 = constCharVal (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 ();
+      else
+        /* 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));
       else
-    TETYPE(tree) = getSpec (TTYPE(tree) =
-          computeType(LTYPE(tree),
-                RTYPE(tree)));
-  LRVAL(tree) = RRVAL(tree) = 1;
-  return tree ;
+        {
+          tree->left  = addCast (tree->left,  resultTypeProp, TRUE);
+          tree->right = addCast (tree->right, resultTypeProp, TRUE);
+
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                     computeType (LTYPE (tree),
+                                                  RTYPE (tree),
+                                                  resultType,
+                                                  tree->opval.op));
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*    compliment              */
-  /*----------------------------*/
-    case '~' :
-  /* can be only integral type */
-  if (!IS_INTEGRAL(LTYPE(tree))) {
-      werror(E_UNARY_OP,tree->opval.op);
-      goto errorTreeReturn ;
-  }
+      LRVAL (tree) = RRVAL (tree) = 1;
 
-  /* 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 ;
-  }
-  LRVAL(tree) = 1;
-  COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree));
-  return tree ;
+      /* if right is a literal and */
+      /* left is also an addition/subtraction with a literal then */
+      /* rearrange the tree */
+      if (IS_LITERAL (RTYPE (tree))
+          /* avoid infinite loop */
+          && (TYPE_TARGET_ULONG) ulFromVal (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;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*           not              */
-  /*----------------------------*/
-    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 ;
-  }
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*    complement              */
+      /*----------------------------*/
+    case '~':
+      /* can be only integral type */
+      if (!IS_INTEGRAL (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, 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 = 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();
-  return tree ;
+      /* 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 addCast (tree, resultTypeProp, TRUE);
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*           shift            */
-  /*----------------------------*/
+      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
+          */
+          werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
+
+          /* optimize bit-result, even if we optimize a buggy source */
+          tree->type = EX_VALUE;
+          tree->opval.val = constCharVal (1);
+        }
+      else
+        tree->left = addCast (tree->left, resultTypeProp, TRUE);
+      LRVAL (tree) = 1;
+      COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*           not              */
+      /*----------------------------*/
+    case '!':
+      /* can be pointer */
+      if (!IS_ARITHMETIC (LTYPE (tree)) &&
+          !IS_PTR (LTYPE (tree)) &&
+          !IS_ARRAY (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
+          goto errorTreeReturn;
+        }
+
+      /* if left is another '!' */
+      if (IS_AST_NOT_OPER (tree->left))
+        {
+          if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
+            {
+              /* replace double '!!X' by 'X' */
+              return tree->left->left;
+            }
+          /* remove double '!!X' by 'X ? 1 : 0' */
+          tree->opval.op = '?';
+          tree->left  = tree->left->left;
+          tree->right = newNode (':',
+                                  newAst_VALUE (constCharVal (1)),
+                                  newAst_VALUE (constCharVal (0)));
+          tree->right->filename = tree->filename;
+          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;
+        }
+      LRVAL (tree) = 1;
+      TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*           shift            */
+      /*----------------------------*/
     case RRC:
     case RLC:
-  TTYPE(tree) = LTYPE(tree);
-  TETYPE(tree) = LETYPE(tree);
-  return tree ;
+    case SWAP:
+      TTYPE (tree) = LTYPE (tree);
+      TETYPE (tree) = LETYPE (tree);
+      return tree;
 
     case GETHBIT:
-  TTYPE(tree) = TETYPE(tree) = newCharLink();
-  return tree;
+    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(E_CONTINUE,"left & right types are ");
-      printTypeChain(LTYPE(tree),stderr);
-      fprintf(stderr,",");
-      printTypeChain(RTYPE(tree),stderr);
-      fprintf(stderr,"\n");
-      goto errorTreeReturn ;
-  }
+      if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
+        {
+          werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
+          werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
+          printTypeChain (LTYPE (tree), stderr);
+          fprintf (stderr, ",");
+          printTypeChain (RTYPE (tree), stderr);
+          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 = 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 ;
-  }
-  /* 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)) {
-      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;
-  if (IS_LITERAL(LTYPE(tree)) && !IS_LITERAL(RTYPE(tree))) {
-      COPYTYPE(TTYPE(tree),TETYPE(tree),RTYPE(tree));
-  } else {
-      COPYTYPE(TTYPE(tree),TETYPE(tree),LTYPE(tree));
-  }
-  return tree ;
+      /* make smaller type only if it's a LEFT_OP */
+      if (tree->opval.op == LEFT_OP)
+        tree->left = addCast (tree->left, resultTypeProp, TRUE);
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*         casting            */
-  /*----------------------------*/
-    case CAST:  /* change the type   */
-  /* cannot cast to an aggregate type */
-  if (IS_AGGREGATE(LTYPE(tree))) {
-      werror(E_CAST_ILLEGAL);
-      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 = 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;
+        }
 
-  /* if the right is a literal replace the tree */
-  if (IS_LITERAL(RETYPE(tree)) && !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 {
-      TTYPE(tree) = LTYPE(tree);
-      LRVAL(tree) = 1;
-  }
+      /* see if this is a GETBYTE operation if yes
+         then return that */
+      {
+        ast *otree = optimizeGetByte (tree, resultType);
 
-  TETYPE(tree) = getSpec(TTYPE(tree));
+        if (otree != tree)
+          return decorateType (otree, RESULT_TYPE_NONE);
+      }
 
-  return tree;
+      /* see if this is a GETWORD operation if yes
+         then return that */
+      {
+        ast *otree = optimizeGetWord (tree, resultType);
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*       logical &&, ||       */
-  /*----------------------------*/
-    case AND_OP:
-    case OR_OP:
-  /* each must me 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 ;
-  }
+        if (otree != tree)
+          return decorateType (otree, RESULT_TYPE_NONE);
+      }
 
-  if (!IS_PTR(RTYPE(tree)) &&
-      !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 ;
-  }
-  LRVAL(tree) = RRVAL(tree) = 1;
-  TTYPE(tree) = TETYPE(tree) = newCharLink();
-  return tree ;
+      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;
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*     comparison operators   */
-  /*----------------------------*/
-    case '>' :
-    case '<' :
-    case LE_OP :
-    case GE_OP :
-    case EQ_OP :
-    case NE_OP :
-  {
-      ast *lt = optimizeCompare(tree);
+      /* if only the right side is a literal & we are
+         shifting more than size of the left operand then zero */
+      if (IS_LITERAL (RTYPE (tree)) &&
+          ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
+          (getSize (TETYPE (tree)) * 8))
+        {
+          if (tree->opval.op==LEFT_OP ||
+              (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
+            {
+              werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
+                      (tree->opval.op == LEFT_OP ? "left" : "right"));
+              tree->type = EX_VALUE;
+              tree->left = tree->right = NULL;
+              tree->opval.val = constCharVal (0);
+              TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+              return tree;
+            }
+        }
 
-      if ( tree != lt )
-    return lt;
-  }
+      return tree;
 
-  /* if they are pointers they must be castable */
-  if ( IS_PTR(LTYPE(tree)) && IS_PTR(RTYPE(tree))) {
-      if (checkType(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 (checkType (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 ;
-    }
-  }
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*         casting            */
+      /*----------------------------*/
+    case CAST:                  /* change the type   */
+      /* cannot cast to an aggregate type */
+      if (IS_AGGREGATE (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
+          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 = 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 ;
-  }
-  LRVAL(tree) = RRVAL(tree) = 1;
-  TTYPE(tree) = TETYPE(tree) = newCharLink();
-  return tree ;
+      /* make sure the type is complete and sane */
+      changePointer(LTYPE(tree));
+      checkTypeSanity(LETYPE(tree), "(cast)");
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*             sizeof         */
-  /*----------------------------*/
-    case SIZEOF :  /* evaluate wihout code generation */
-  /* change the type to a integer */
-  tree->type = EX_VALUE;
-  sprintf(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);
-  return tree;
+      /* if 'from' and 'to' are the same remove the superfluous cast,
+       * this helps other optimizations */
+      if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
+        {
+          /* mark that the explicit cast has been removed,
+           * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
+          tree->right->values.removedCast = 1;
+          return tree->right;
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /* conditional operator  '?'  */
-  /*----------------------------*/
-    case '?' :
-  /* the type is one on the left */
-  TTYPE(tree) = LTYPE(tree);
-  TETYPE(tree)= getSpec (TTYPE(tree));
-  return tree ;
-
-    case ':' :
-  /* if they don't match we have a problem */
-  if (checkType( LTYPE(tree), RTYPE(tree)) == 0) {
-      werror(E_TYPE_MISMATCH,"conditional operator"," ");
-      goto errorTreeReturn ;
-  }
+      /* 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) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */
+            {
+              sym_link *rest = LTYPE(tree)->next;
+              werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
+              TTYPE(tree) = newLink(DECLARATOR);
+              DCL_TYPE(TTYPE(tree)) = FPOINTER;
+              TTYPE(tree)->next = rest;
+              tree->left->opval.lnk = TTYPE(tree);
+              LRVAL (tree) = 1;
+            }
+          else
+            {
+              TTYPE (tree) = LTYPE (tree);
+              LRVAL (tree) = 1;
+            }
+        }
+      else
+        {
+          TTYPE (tree) = LTYPE (tree);
+          LRVAL (tree) = 1;
+        }
+#else
+#if 0 // this is already checked, now this could be explicit
+      /* if pointer to struct then check names */
+      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))
+        {
+          werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
+                 SPEC_STRUCT(LETYPE(tree))->tag);
+        }
+#endif
+      if (IS_ADDRESS_OF_OP(tree->right)
+          && IS_AST_SYM_VALUE (tree->right->left)
+          && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype))
+        {
+          symbol * sym = AST_SYMBOL (tree->right->left);
+          unsigned int gptype = 0;
+          unsigned int addr = SPEC_ADDR (sym->etype);
+
+          if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE) || 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), addr);
+          TTYPE (tree) = tree->opval.val->type;
+          TETYPE (tree) = getSpec (TTYPE (tree));
+          tree->left = NULL;
+          tree->right = NULL;
+          tree->values.literalFromCast = 1;
+          return tree;
+        }
 
-  TTYPE(tree) = computeType(LTYPE(tree),RTYPE(tree));
-  TETYPE(tree)= getSpec(TTYPE(tree));
-  return tree ;
+      /* handle offsetof macro:            */
+      /* #define offsetof(TYPE, MEMBER) \  */
+      /* ((unsigned) &((TYPE *)0)->MEMBER) */
+      if (IS_ADDRESS_OF_OP(tree->right)
+          && IS_AST_OP (tree->right->left)
+          && tree->right->left->opval.op == PTR_OP
+          && IS_AST_OP (tree->right->left->left)
+          && tree->right->left->left->opval.op == CAST
+          && IS_AST_LIT_VALUE(tree->right->left->left->right))
+        {
+          symbol *element = getStructElement (
+            SPEC_STRUCT (LETYPE(tree->right->left)),
+            AST_SYMBOL(tree->right->left->right)
+          );
+
+          if (element)
+            {
+              tree->type = EX_VALUE;
+              tree->opval.val = valCastLiteral (
+                LTYPE (tree),
+                element->offset
+                + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
+              );
+
+            TTYPE (tree) = tree->opval.val->type;
+            TETYPE (tree) = getSpec (TTYPE (tree));
+            tree->left = NULL;
+            tree->right = NULL;
+            return tree;
+          }
+      }
 
+      /* if the right is a literal replace the tree */
+      if (IS_LITERAL (RETYPE (tree)))
+        {
+          #if 0
+          if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) )
+            {
+              /* rewrite      (type *)litaddr
+                 as           &temp
+                 and define   type at litaddr temp
+                 (but only if type's storage class is not generic)
+              */
+              ast *newTree = newNode ('&', NULL, NULL);
+              symbol *sym;
+
+              TTYPE (newTree) = LTYPE (tree);
+              TETYPE (newTree) = getSpec(LTYPE (tree));
+
+              /* define a global symbol at the casted address*/
+              sym = newSymbol(genSymName (0), 0);
+              sym->type = LTYPE (tree)->next;
+              if (!sym->type)
+                sym->type = newLink (V_VOID);
+              sym->etype = getSpec(sym->type);
+              SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
+              sym->lineDef = tree->lineno;
+              sym->cdef = 1;
+              sym->isref = 1;
+              SPEC_STAT (sym->etype) = 1;
+              SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
+              SPEC_ABSA(sym->etype) = 1;
+              addSym (SymbolTab, sym, sym->name, 0, 0, 0);
+              allocGlobal (sym);
+
+              newTree->left = newAst_VALUE(symbolVal(sym));
+              newTree->left->filename = tree->filename;
+              newTree->left->lineno = tree->lineno;
+              LTYPE (newTree) = sym->type;
+              LETYPE (newTree) = sym->etype;
+              LLVAL (newTree) = 1;
+              LRVAL (newTree) = 0;
+              TLVAL (newTree) = 1;
+              return newTree;
+            }
+          #endif
+          if (!IS_PTR (LTYPE (tree)))
+            {
+              tree->type = EX_VALUE;
+              tree->opval.val =
+                valCastLiteral (LTYPE (tree), floatFromVal (valFromType (RTYPE (tree))));
+              TTYPE (tree) = tree->opval.val->type;
+              tree->left = NULL;
+              tree->right = NULL;
+              tree->values.literalFromCast = 1;
+              TETYPE (tree) = getSpec (TTYPE (tree));
+              return tree;
+            }
+        }
+      if (IS_GENPTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)) && !IS_GENPTR (RTYPE (tree)) && (resultType != RESULT_TYPE_GPTR))
+        {
+          DCL_TYPE (LTYPE (tree)) = DCL_TYPE (RTYPE (tree));
+        }
+      TTYPE (tree) = LTYPE (tree);
+      LRVAL (tree) = 1;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*    assignment operators    */
-  /*----------------------------*/
-    case MUL_ASSIGN:
-    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 ;
-  }
-        RRVAL(tree) = 1;
-  TETYPE(tree) = getSpec(TTYPE(tree) = LTYPE(tree));
+#endif
+      TETYPE (tree) = getSpec (TTYPE (tree));
 
-  if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
-      werror(E_CODE_WRITE," ");
+      return tree;
 
-  if (LRVAL(tree)) {
-      werror(E_LVALUE_REQUIRED,"*= or /=");
-      goto errorTreeReturn ;
-  }
-  LLVAL(tree) = 1;
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*       logical &&, ||       */
+      /*----------------------------*/
+    case AND_OP:
+    case OR_OP:
+      /* each must be arithmetic type or be a pointer */
+      if (!IS_PTR (LTYPE (tree)) &&
+          !IS_ARRAY (LTYPE (tree)) &&
+          !IS_INTEGRAL (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
+          goto errorTreeReturn;
+        }
 
-  propAsgType(tree);
+      if (!IS_PTR (RTYPE (tree)) &&
+          !IS_ARRAY (RTYPE (tree)) &&
+          !IS_INTEGRAL (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, 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 (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) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
+      return tree;
 
-  return tree ;
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*     comparison operators   */
+      /*----------------------------*/
+    case '>':
+    case '<':
+    case LE_OP:
+    case GE_OP:
+    case EQ_OP:
+    case NE_OP:
+      {
+        ast *lt = optimizeCompare (tree);
 
-    case AND_ASSIGN:
-    case OR_ASSIGN:
-    case XOR_ASSIGN:
-    case RIGHT_ASSIGN:
-    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 ;
-  }
-        RRVAL(tree) = 1;
-  TETYPE(tree) = getSpec(TTYPE(tree) = LTYPE(tree));
+        if (tree != lt)
+          return lt;
+      }
 
-  if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
-      werror(E_CODE_WRITE," ");
+      /* 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)
+            {
+              werrorfl (tree->filename, tree->lineno, 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)
+              {
+                werrorfl (tree->filename, tree->lineno, 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 (LRVAL(tree)) {
-      werror(E_LVALUE_REQUIRED,"&= or |= or ^= or >>= or <<=");
-      goto errorTreeReturn ;
-  }
-  LLVAL(tree) = 1;
+      {
+        CCR_RESULT ccr_result = CCR_OK;
+
+        /* if left is integral and right is literal
+           then check constant range */
+        if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
+          ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
+                                           tree->opval.op, FALSE);
+        if (ccr_result == CCR_OK &&
+            IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
+          ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
+                                           tree->opval.op, TRUE);
+        switch (ccr_result)
+            {
+              case CCR_ALWAYS_TRUE:
+              case CCR_ALWAYS_FALSE:
+                if (!options.lessPedantic)
+                  werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
+                          ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
+                return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
+              case CCR_OK:
+              default:
+                break;
+            }
+      }
 
-  propAsgType(tree);
+      /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
+      if (tree->opval.op == '>' &&
+          SPEC_USIGN(LETYPE(tree)) &&
+          IS_LITERAL(RTYPE(tree))  &&
+          ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
+        {
+          if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
+            {
+              /* the parent is an ifx: */
+              /* if (unsigned value) */
+              return tree->left;
+            }
+
+          /* (unsigned value) ? 1 : 0 */
+          tree->opval.op = '?';
+          tree->right = newNode (':',
+                                  newAst_VALUE (constCharVal (1)),
+                                  tree->right); /* val 0 */
+          tree->right->filename = tree->filename;
+          tree->right->lineno = tree->lineno;
+          tree->right->left->filename = tree->filename;
+          tree->right->left->lineno = tree->lineno;
+          tree->decorated = 0;
+          return decorateType (tree, resultType);
+        }
 
-  return tree ;
+      /* 'ifx (op == 0)' -> 'ifx (!(op))' */
+      if (IS_LITERAL(RTYPE(tree))  &&
+          floatFromVal (valFromType (RETYPE (tree))) == 0 &&
+          tree->opval.op == EQ_OP &&
+          (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
+        {
+          tree->opval.op = '!';
+          tree->right = NULL;
+          tree->decorated = 0;
+          return decorateType (tree, resultType);
+        }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*    -= operator             */
-  /*----------------------------*/
-    case SUB_ASSIGN:
-  if (!(IS_PTR(LTYPE(tree))   ||
-        IS_ARITHMETIC(LTYPE(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 = 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 (!(IS_PTR(RTYPE(tree))   ||
-        IS_ARITHMETIC(RTYPE(tree)))) {
-      werror(E_PLUS_INVALID,"-=");
-      goto errorTreeReturn ;
-  }
-  RRVAL(tree) = 1;
-  TETYPE(tree) = getSpec (TTYPE(tree) =
-        computeType(LTYPE(tree),
-              RTYPE(tree)));
+      /* if one is 'signed char ' and the other one is 'unsigned char' */
+      /* it's necessary to promote to int */
+      if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
+          (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
+        {
+          /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
+             if it's possible to use a 'signed char' */
+
+              /* is left a 'unsigned char'? */
+          if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
+              /* the value range of a 'unsigned char' is 0...255;
+                 if the actual value is < 128 it can be changed to signed */
+              (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
+            {
+              /* now we've got 2 'signed char'! */
+              SPEC_USIGN (RETYPE (tree)) = 0;
+            }
+                   /* same test for the left operand: */
+          else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
+              (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
+            {
+              SPEC_USIGN (LETYPE (tree)) = 0;
+            }
+          else
+            {
+              werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
+              tree->left  = addCast (tree->left , RESULT_TYPE_INT, TRUE);
+              tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
+            }
+        }
 
-  if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
-      werror(E_CODE_WRITE," ");
+      LRVAL (tree) = RRVAL (tree) = 1;
+      TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
 
-  if (LRVAL(tree)) {
-      werror(E_LVALUE_REQUIRED,"-=");
-      goto errorTreeReturn ;
-  }
-  LLVAL(tree) = 1;
+      /* 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->filename = tree->left->filename;
+            tree->lineno = tree->left->lineno;
+            return decorateType (tree, resultType);
+          }
+      }
 
-  propAsgType(tree);
+      return tree;
 
-  return tree;
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*             sizeof         */
+      /*----------------------------*/
+    case SIZEOF:                /* evaluate wihout code generation */
+      /* change the type to a integer */
+      {
+        int size = getSize (tree->right->ftype);
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*          += operator       */
-  /*----------------------------*/
-    case ADD_ASSIGN:
-  /* 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 ;
-  }
+        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;
+      tree->opval.val = constVal (buffer);
+      tree->right = tree->left = NULL;
+      TETYPE (tree) = getSpec (TTYPE (tree) =
+                               tree->opval.val->type);
 
-  if (!IS_ARITHMETIC(LTYPE(tree)) && !IS_PTR(LTYPE(tree)))  {
-      werror(E_PLUS_INVALID,"+=");
-      goto errorTreeReturn ;
-  }
+      return 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_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));
+
+      /* If already known then replace the tree : optimizer will do it
+         but faster to do it here. If done before decorating tree->right
+         this can save generating unused const strings. */
+      if (IS_LITERAL (LTYPE (tree)))
+        {
+          if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
+            return decorateType (tree->right->left, resultTypeProp);
+          else
+            return decorateType (tree->right->right, resultTypeProp);
+        }
+
+      tree->right = decorateType (tree->right,  resultTypeProp);
+
+      if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
+          ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
+        {
+          double valTrue = AST_FLOAT_VALUE (tree->right->left);
+          double valFalse = AST_FLOAT_VALUE (tree->right->right);
+
+          if ((valTrue != 0) && (valFalse == 0))
+            {
+              /* assign cond to result */
+              tree->left->decorated = 0;
+              return decorateType (tree->left, resultTypeProp);
+            }
+          else if ((valTrue == 0) && (valFalse != 0))
+            {
+              /* assign !cond to result */
+              tree->opval.op = '!';
+              tree->decorated = 0;
+              tree->right = NULL;
+              return decorateType (tree, resultTypeProp);
+            }
+          else
+            {
+              /* they have the same boolean value, make them equal */
+              tree->right->left = tree->right->right;
+            }
+        }
+
+      /* if they are equal then replace the tree */
+      if (isAstEqual (tree->right->left, tree->right->right))
+        {
+          return tree->right->left;
+        }
+
+      TTYPE (tree) = RTYPE (tree);
+      TETYPE (tree) = getSpec (TTYPE (tree));
+      return tree;
+
+    case ':':
+      /* if they don't match we have a problem */
+      if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
+          (compareType (RTYPE (tree), LTYPE (tree)) == 0))
+        {
+          werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
+          goto errorTreeReturn;
+        }
+
+      TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
+                                  resultType, tree->opval.op);
+      TETYPE (tree) = getSpec (TTYPE (tree));
+      return tree;
+
+
+#if 0 // assignment operators are converted by the parser
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*    assignment operators    */
+      /*----------------------------*/
+    case MUL_ASSIGN:
+    case DIV_ASSIGN:
+      /* for these it must be both must be integral */
+      if (!IS_ARITHMETIC (LTYPE (tree)) ||
+          !IS_ARITHMETIC (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
+          goto errorTreeReturn;
+        }
+      RRVAL (tree) = 1;
+      TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
+
+      if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
+        werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+
+      if (LRVAL (tree))
+        {
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
+          goto errorTreeReturn;
+        }
+      LLVAL (tree) = 1;
+
+      return tree;
+
+    case AND_ASSIGN:
+    case OR_ASSIGN:
+    case XOR_ASSIGN:
+    case RIGHT_ASSIGN:
+    case LEFT_ASSIGN:
+      /* for these it must be both must be integral */
+      if (!IS_INTEGRAL (LTYPE (tree)) ||
+          !IS_INTEGRAL (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
+          goto errorTreeReturn;
+        }
+      RRVAL (tree) = 1;
+      TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
+
+      if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
+        werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
+
+      if (LRVAL (tree))
+        {
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
+          goto errorTreeReturn;
+        }
+      LLVAL (tree) = 1;
+
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*    -= operator             */
+      /*----------------------------*/
+    case SUB_ASSIGN:
+      if (!(IS_PTR (LTYPE (tree)) ||
+            IS_ARITHMETIC (LTYPE (tree))))
+        {
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
+          goto errorTreeReturn;
+        }
+
+      if (!(IS_PTR (RTYPE (tree)) ||
+            IS_ARITHMETIC (RTYPE (tree))))
+        {
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
+          goto errorTreeReturn;
+        }
+      RRVAL (tree) = 1;
+      TETYPE (tree) = getSpec (TTYPE (tree) =
+                               computeType (LTYPE (tree),
+                                            RTYPE (tree),
+                                            RESULT_TYPE_NOPROM,
+                                            tree->opval.op));
+
+      if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
+        werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
+
+      if (LRVAL (tree))
+        {
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
+          goto errorTreeReturn;
+        }
+      LLVAL (tree) = 1;
+
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*          += operator       */
+      /*----------------------------*/
+    case ADD_ASSIGN:
+      /* this is not a unary operation */
+      /* if both pointers then problem */
+      if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
+          goto errorTreeReturn;
+        }
+
+      if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
+          goto errorTreeReturn;
+        }
+
+      if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
+          goto errorTreeReturn;
+        }
+      RRVAL (tree) = 1;
+      TETYPE (tree) = getSpec (TTYPE (tree) =
+                               computeType (LTYPE (tree),
+                                            RTYPE (tree),
+                                            RESULT_TYPE_NOPROM,
+                                            tree->opval.op));
+
+      if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
+        werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
+
+      if (LRVAL (tree))
+        {
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
+          goto errorTreeReturn;
+        }
+
+      tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
+      tree->opval.op = '=';
+
+      return tree;
+#endif
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*      straight assignemnt   */
+      /*----------------------------*/
+    case '=':
+      /* cannot be an aggregate */
+      if (IS_AGGREGATE (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
+          goto errorTreeReturn;
+        }
+
+      /* they should either match or be castable */
+      if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
+        {
+          werrorfl (tree->filename, tree->lineno, 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)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
+          printFromToType(RTYPE(tree), LTYPE(tree));
+        }
+
+      TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
+      RRVAL (tree) = 1;
+      LLVAL (tree) = 1;
+      if (!tree->initMode ) {
+        if (IS_CONSTANT(LTYPE(tree)))
+          werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
+      }
+      if (LRVAL (tree))
+        {
+          werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
+          goto errorTreeReturn;
+        }
+
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*      comma operator        */
+      /*----------------------------*/
+    case ',':
+      TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*       function call        */
+      /*----------------------------*/
+    case CALL:
+
+      /* 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;
+        }
+
+      /* 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 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;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*     return statement       */
+      /*----------------------------*/
+    case RETURN:
+      if (!tree->right)
+        goto voidcheck;
+
+      if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
+        {
+          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)))
+        {
+          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),
+                          IS_GENPTR (currFunc->type->next) ? RESULT_TYPE_GPTR : RESULT_TYPE_NONE);
+        }
+
+      RRVAL (tree) = 1;
+      return tree;
+
+    voidcheck:
+
+      if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
+        {
+          werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
+          goto errorTreeReturn;
+        }
+
+      TTYPE (tree) = TETYPE (tree) = NULL;
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /*     switch statement       */
+      /*----------------------------*/
+    case SWITCH:
+      /* the switch value must be an integer */
+      if (!IS_INTEGRAL (LTYPE (tree)))
+        {
+          werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
+          goto errorTreeReturn;
+        }
+      LRVAL (tree) = 1;
+      TTYPE (tree) = TETYPE (tree) = NULL;
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /* ifx Statement              */
+      /*----------------------------*/
+    case IFX:
+      tree->left = backPatchLabels (tree->left,
+                                    tree->trueLabel,
+                                    tree->falseLabel);
+      TTYPE (tree) = TETYPE (tree) = NULL;
+      return tree;
+
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
+      /* for Statement              */
+      /*----------------------------*/
+    case FOR:
+
+      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), RESULT_TYPE_NONE);
+      }
+    case PARAM:
+      werrorfl (tree->filename, tree->lineno, 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;
+    }
+
+  /* some error found this tree will be killed */
+errorTreeReturn:
+  TTYPE (tree) = TETYPE (tree) = newCharLink ();
+  tree->opval.op = NULLOP;
+  tree->isError = 1;
+
+  return tree;
+}
+
+/*-----------------------------------------------------------------*/
+/* sizeofOp - processes size of operation                          */
+/*-----------------------------------------------------------------*/
+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", size = getSize (type));
+  if (!size && !IS_VOID(type))
+    werror (E_SIZEOF_INCOMPLETE_TYPE);
+
+  /* now convert into value  */
+  return constVal (buff);
+}
+
+
+#define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
+#define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
+#define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
+#define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
+#define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
+#define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
+#define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
+
+/*-----------------------------------------------------------------*/
+/* backPatchLabels - change and or not operators to flow control    */
+/*-----------------------------------------------------------------*/
+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;
+
+  /* if this an and */
+  if (IS_AND (tree))
+    {
+      static int localLbl = 0;
+      symbol *localLabel;
+
+      SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
+      localLabel = newSymbol (buffer, NestLevel);
+
+      tree->left = backPatchLabels (tree->left, localLabel, 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->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));
+
+      tree->right = createLabel (localLabel, tree->right);
+      tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
+
+      return newNode (NULLOP, tree->left, tree->right);
+    }
+
+  /* if this is an or operation */
+  if (IS_OR (tree))
+    {
+      static int localLbl = 0;
+      symbol *localLabel;
+
+      SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
+      localLabel = newSymbol (buffer, NestLevel);
+
+      tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
+
+      /* 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->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));
+
+      tree->right = createLabel (localLabel, tree->right);
+      tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
+
+      return newNode (NULLOP, tree->left, tree->right);
+    }
+
+  /* change not */
+  if (IS_NOT (tree))
+    {
+      /* call with exchanged labels */
+      tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
+
+      /* if left isn't already a IFX */
+      if (!IS_IFX (tree->left))
+        {
+          tree->left = newNode (IFX, tree->left, NULL);
+          tree->left->trueLabel = falseLabel;
+          tree->left->falseLabel = trueLabel;
+        }
+      return tree->left;
+     }
+
+  if (IS_IFX (tree))
+    {
+      tree->trueLabel = trueLabel;
+      tree->falseLabel = falseLabel;
+    }
+
+  return tree;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* createBlock - create expression tree for block                  */
+/*-----------------------------------------------------------------*/
+ast *
+createBlock (symbol * decl, ast * body)
+{
+  ast *ex;
+
+  /* if the block has nothing */
+  if (!body && !decl)
+    return NULL;
+
+  ex = newNode (BLOCK, NULL, body);
+  ex->values.sym = decl;
+
+  ex->level++;
+  ex->filename = NULL;
+  ex->lineno = 0;
+  return ex;
+}
+
+/*-----------------------------------------------------------------*/
+/* createLabel - creates the expression tree for labels            */
+/*-----------------------------------------------------------------*/
+ast *
+createLabel (symbol * label, ast * stmnt)
+{
+  symbol *csym;
+  char name[SDCC_NAME_MAX + 1];
+  ast *rValue;
+
+  /* must create fresh symbol if the symbol name  */
+  /* exists in the symbol table, since there can  */
+  /* be a variable with the same name as the labl */
+  if ((csym = findSym (SymbolTab, NULL, label->name)) &&
+      (csym->level == label->level))
+    label = newSymbol (label->name, label->level);
+
+  /* change the name before putting it in add _ */
+  SNPRINTF(name, sizeof(name), "%s", label->name);
+
+  /* put the label in the LabelSymbol table    */
+  /* but first check if a label of the same    */
+  /* name exists                               */
+  if ((csym = findSym (LabelTab, NULL, name)))
+    werror (E_DUPLICATE_LABEL, label->name);
+  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);
+  rValue->filename = NULL;
+  rValue->lineno = 0;
+
+  return rValue;
+}
+
+/*-----------------------------------------------------------------*/
+/* createCase - generates the parsetree for a case statement       */
+/*-----------------------------------------------------------------*/
+ast *
+createCase (ast * swStat, ast * caseVal, ast * stmnt)
+{
+  char caseLbl[SDCC_NAME_MAX + 1];
+  ast *rexpr;
+  value *val;
+
+  /* if the switch statement does not exist */
+  /* then case is out of context            */
+  if (!swStat)
+    {
+      werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
+      return NULL;
+    }
+
+  caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
+  /* if not a constant then error  */
+  if (!IS_LITERAL (caseVal->ftype))
+    {
+      werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
+      return NULL;
+    }
+
+  /* if not a integer than error */
+  if (!IS_INTEGRAL (caseVal->ftype))
+    {
+      werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
+      return NULL;
+    }
+
+  /* find the end of the switch values chain   */
+  if (!(val = swStat->values.switchVals.swVals))
+    swStat->values.switchVals.swVals = caseVal->opval.val;
+  else
+    {
+      /* also order the cases according to value */
+      value *pval = NULL;
+      int cVal = (int) ulFromVal (caseVal->opval.val);
+      while (val && (int) ulFromVal (val) < cVal)
+        {
+          pval = val;
+          val = val->next;
+        }
+
+      /* if we reached the end then */
+      if (!val)
+        {
+          pval->next = caseVal->opval.val;
+        }
+      else if ((int) ulFromVal (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;
+        }
+
+    }
+
+  /* create the case label   */
+  SNPRINTF(caseLbl, sizeof(caseLbl),
+           "_case_%d_%d",
+           swStat->values.switchVals.swNum,
+           (int) ulFromVal (caseVal->opval.val));
+
+  rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
+  rexpr->filename = 0;
+  rexpr->lineno = 0;
+  return rexpr;
+}
+
+/*-----------------------------------------------------------------*/
+/* createDefault - creates the parse tree for the default statement */
+/*-----------------------------------------------------------------*/
+ast *
+createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
+{
+  char defLbl[SDCC_NAME_MAX + 1];
+
+  /* if the switch statement does not exist */
+  /* then case is out of context            */
+  if (!swStat)
+    {
+      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;
+    }
+
+  /* turn on the default flag   */
+  swStat->values.switchVals.swDefault = 1;
+
+  /* create the label  */
+  SNPRINTF (defLbl, sizeof(defLbl),
+            "_default_%d", swStat->values.switchVals.swNum);
+  return createLabel (newSymbol (defLbl, 0), stmnt);
+}
+
+/*-----------------------------------------------------------------*/
+/* createIf - creates the parsetree for the if statement           */
+/*-----------------------------------------------------------------*/
+ast *
+createIf (ast * condAst, ast * ifBody, ast * elseBody)
+{
+  static int Lblnum = 0;
+  ast *ifTree;
+  symbol *ifTrue, *ifFalse, *ifEnd;
+
+  /* if neither exists */
+  if (!elseBody && !ifBody) {
+    // if there are no side effects (i++, j() etc)
+    if (!hasSEFcalls(condAst)) {
+      return condAst;
+    }
+  }
+
+  /* create the labels */
+  SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
+  ifFalse = newSymbol (buffer, NestLevel);
+  /* if no else body then end == false */
+  if (!elseBody)
+    ifEnd = ifFalse;
+  else
+    {
+      SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
+      ifEnd = newSymbol (buffer, NestLevel);
+    }
+
+  SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
+  ifTrue = newSymbol (buffer, NestLevel);
+
+  Lblnum++;
+
+  /* attach the ifTrue label to the top of it body */
+  ifBody = createLabel (ifTrue, ifBody);
+  /* attach a goto end to the ifBody if else is present */
+  if (elseBody)
+    {
+      ifBody = newNode (NULLOP, ifBody,
+                        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));
+    }
+  else
+    {
+      ifBody = newNode (NULLOP, ifBody,
+                        createLabel (ifFalse, NULL));
+    }
+  condAst = backPatchLabels (condAst, ifTrue, ifFalse);
+  if (IS_IFX (condAst))
+    ifTree = condAst;
+  else
+    ifTree = newIfxNode (condAst, ifTrue, ifFalse);
+
+  return newNode (NULLOP, ifTree,
+                  newNode (NULLOP, ifBody, elseBody));
+
+}
+
+/*-----------------------------------------------------------------*/
+/* createDo - creates parse tree for do                            */
+/*        _dobody_n:                                               */
+/*            statements                                           */
+/*        _docontinue_n:                                           */
+/*            condition_expression +-> trueLabel -> _dobody_n      */
+/*                                 |                               */
+/*                                 +-> falseLabel-> _dobreak_n     */
+/*        _dobreak_n:                                              */
+/*-----------------------------------------------------------------*/
+ast *
+createDo (symbol * trueLabel, symbol * continueLabel,
+          symbol * falseLabel, ast * condAst, ast * doBody)
+{
+  ast *doTree;
+
+
+  /* if the body does not exist then it is simple */
+  if (!doBody)
+    {
+      condAst = backPatchLabels (condAst, continueLabel, falseLabel);
+      doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
+                : newNode (IFX, createLabel (continueLabel, condAst), NULL));
+      doTree->trueLabel = continueLabel;
+      doTree->falseLabel = NULL;
+
+      doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
+      return doTree;
+    }
+
+  /* otherwise we have a body */
+  condAst = backPatchLabels (condAst, trueLabel, falseLabel);
+
+  /* attach the body label to the top */
+  doBody = createLabel (trueLabel, doBody);
+  /* attach the continue label to end of body */
+  doBody = newNode (NULLOP, doBody,
+                    createLabel (continueLabel, NULL));
+
+  /* now put the break label at the end */
+  if (IS_IFX (condAst))
+    doTree = condAst;
+  else
+    doTree = newIfxNode (condAst, trueLabel, falseLabel);
+
+  doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
+
+  /* putting it together */
+  return newNode (NULLOP, doBody, doTree);
+}
+
+/*-----------------------------------------------------------------*/
+/* createFor - creates parse tree for 'for' statement              */
+/*        initExpr                                                 */
+/*   _forcond_n:                                                   */
+/*        condExpr  +-> trueLabel -> _forbody_n                    */
+/*                  |                                              */
+/*                  +-> falseLabel-> _forbreak_n                   */
+/*   _forbody_n:                                                   */
+/*        statements                                               */
+/*   _forcontinue_n:                                               */
+/*        loopExpr                                                 */
+/*        goto _forcond_n ;                                        */
+/*   _forbreak_n:                                                  */
+/*-----------------------------------------------------------------*/
+ast *
+createFor (symbol * trueLabel, symbol * continueLabel,
+           symbol * falseLabel, symbol * condLabel,
+           ast * initExpr, ast * condExpr, ast * loopExpr,
+           ast * forBody)
+{
+  ast *forTree;
+
+  /* if loopexpression not present then we can generate it */
+  /* the same way as a while */
+  if (!loopExpr)
+    return newNode (NULLOP, initExpr,
+                    createWhile (trueLabel, continueLabel,
+                                 falseLabel, condExpr, forBody));
+  /* vanilla for statement */
+  condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
+
+  if (condExpr && !IS_IFX (condExpr))
+    condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
+
+
+  /* attach condition label to condition */
+  condExpr = createLabel (condLabel, condExpr);
+
+  /* attach body label to body */
+  forBody = createLabel (trueLabel, forBody);
+
+  /* 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)));
+  /* 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));
+  return forTree;
+}
+
+/*-----------------------------------------------------------------*/
+/* createWhile - creates parse tree for while statement            */
+/*               the while statement will be created as follows    */
+/*                                                                 */
+/*      _while_continue_n:                                         */
+/*            condition_expression +-> trueLabel -> _while_boby_n  */
+/*                                 |                               */
+/*                                 +-> falseLabel -> _while_break_n */
+/*      _while_body_n:                                             */
+/*            statements                                           */
+/*            goto _while_continue_n                               */
+/*      _while_break_n:                                            */
+/*-----------------------------------------------------------------*/
+ast *
+createWhile (symbol * trueLabel, symbol * continueLabel,
+             symbol * falseLabel, ast * condExpr, ast * whileBody)
+{
+  ast *whileTree;
+
+  /* put the continue label */
+  condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
+  condExpr = createLabel (continueLabel, condExpr);
+  condExpr->filename = NULL;
+  condExpr->lineno = 0;
+
+  /* put the body label in front of the body */
+  whileBody = createLabel (trueLabel, whileBody);
+  whileBody->filename = NULL;
+  whileBody->lineno = 0;
+  /* put a jump to continue at the end of the body */
+  /* and put break label at the end of the body */
+  whileBody = newNode (NULLOP,
+                       whileBody,
+                       newNode (GOTO,
+                                newAst_VALUE (symbolVal (continueLabel)),
+                                createLabel (falseLabel, NULL)));
+
+  /* put it all together */
+  if (IS_IFX (condExpr))
+    whileTree = condExpr;
+  else
+    {
+      whileTree = newNode (IFX, condExpr, NULL);
+      /* put the true & false labels in place */
+      whileTree->trueLabel = trueLabel;
+      whileTree->falseLabel = falseLabel;
+    }
+
+  return newNode (NULLOP, whileTree, whileBody);
+}
+
+/*-----------------------------------------------------------------*/
+/* isShiftRightLitVal _BitAndLitVal - helper function              */
+/*-----------------------------------------------------------------*/
+static ast *
+isShiftRightLitVal_BitAndLitVal (ast * tree)
+{
+  /* if this is not a bit and */
+  if (!IS_BITAND (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 & (1 << litval) */
+  if (!IS_AST_LIT_VALUE (tree->right))
+    return -1;
+
+  return powof2 (AST_ULONG_VALUE (tree->right));
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetHbit - get highest order bit of the expression       */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
+{
+  unsigned int i, j;
+  ast * expr;
+
+  expr = isShiftRightLitVal_BitAndLitVal(tree);
+  if (expr)
+    {
+      if ((AST_ULONG_VALUE (tree->right) != 1) ||
+          ((i = AST_ULONG_VALUE (tree->left->right)) !=
+          (j = (getSize (TTYPE (expr)) * 8 - 1))))
+        expr = NULL;
+    }
+  if (!expr && (resultType == RESULT_TYPE_BIT))
+    {
+      expr = tree->left;
+      if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
+        expr = NULL;
+    }
+  if (!expr)
+    return tree;
+
+  /* make sure the port supports GETHBIT */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
+    return tree;
+
+  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_ULONG_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;
+
+  /* make sure the port supports GETABIT */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
+    return tree;
+
+  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 = AST_ULONG_VALUE (tree->left->right);
+      count = tree->left->right;
+      if (AST_ULONG_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 = AST_ULONG_VALUE (tree->right);
+          count = tree->right;
+            expr = tree->left;
+        }
+    }
+  if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
+    return tree;
 
-  if (!IS_ARITHMETIC(RTYPE(tree)) && !IS_PTR(RTYPE(tree)))  {
-      werror(E_PLUS_INVALID,"+=");
-      goto errorTreeReturn;
-  }
-  RRVAL(tree) = 1;
-  TETYPE(tree) = getSpec (TTYPE(tree) =
-        computeType(LTYPE(tree),
-              RTYPE(tree)));
+  /* make sure the port supports GETBYTE */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
+    return tree;
 
-  if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
-      werror(E_CODE_WRITE," ");
+  return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
+}
 
-  if (LRVAL(tree)) {
-      werror(E_LVALUE_REQUIRED,"+=");
-      goto errorTreeReturn ;
-  }
+/*-----------------------------------------------------------------*/
+/* optimizeGetWord - get two bytes of the expression               */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetWord (ast * tree, RESULT_TYPE resultType)
+{
+  unsigned int i = 0;
+  ast * expr;
+  ast * count = NULL;
 
-  tree->right = decorateType(newNode('+',copyAst(tree->left),tree->right));
-  tree->opval.op = '=';
+  expr = isShiftRightLitVal_BitAndLitVal(tree);
+  if (expr)
+    {
+      i = AST_ULONG_VALUE (tree->left->right);
+      count = tree->left->right;
+      if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
+        expr = NULL;
+    }
+  if (!expr && resultType == RESULT_TYPE_INT)
+    {
+      /* if this is a right shift over a multiple of 8 */
+      if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
+        {
+          i = AST_ULONG_VALUE (tree->right);
+          count = tree->right;
+            expr = tree->left;
+        }
+    }
+  if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
+    return tree;
 
-  propAsgType(tree);
+  /* make sure the port supports GETWORD */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
+    return tree;
 
-  return tree;
+  return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
+}
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*      straight assignemnt   */
-  /*----------------------------*/
-    case '=' :
-  /* cannot be an aggregate */
-  if (IS_AGGREGATE(LTYPE(tree))) {
-      werror(E_AGGR_ASSIGN);
-      goto errorTreeReturn;
-  }
+/*-----------------------------------------------------------------*/
+/* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeRRCRLC (ast * root)
+{
+  /* will look for trees of the form
+     (?expr << 1) | (?expr >> 7) or
+     (?expr >> 7) | (?expr << 1) will make that
+     into a RLC : operation ..
+     Will also look for
+     (?expr >> 1) | (?expr << 7) or
+     (?expr << 7) | (?expr >> 1) will make that
+     into a RRC operation
+     note : by 7 I mean (number of bits required to hold the
+     variable -1 ) */
+  /* if the root operation is not a | operation then not */
+  if (!IS_BITOR (root))
+    return root;
 
-  /* they should either match or be castable */
-  if (checkType (LTYPE(tree),RTYPE(tree)) == 0) {
-      werror(E_TYPE_MISMATCH,"assignment"," ");
-      fprintf(stderr,"type --> '");
-      printTypeChain (RTYPE(tree),stderr); fprintf(stderr,"' ");
-      fprintf(stderr,"assigned to type --> '");
-      printTypeChain (LTYPE(tree),stderr); fprintf(stderr,"'\n");
-      goto errorTreeReturn ;
-  }
+  /* I have to think of a better way to match patterns this sucks */
+  /* 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) &&
+      IS_RIGHT_OP (root->right))
+    {
 
-  /* if the left side of the tree is of type void
-     then report error */
-  if (IS_VOID(LTYPE(tree))) {
-      werror(E_CAST_ZERO);
-      fprintf(stderr,"type --> '");
-      printTypeChain (RTYPE(tree),stderr); fprintf(stderr,"' ");
-      fprintf(stderr,"assigned to type --> '");
-      printTypeChain (LTYPE(tree),stderr); fprintf(stderr,"'\n");
-  }
+      if (!SPEC_USIGN (TETYPE (root->left->left)))
+        return root;
 
-  /* extra checks for pointer types */
-  if (IS_PTR(LTYPE(tree)) && IS_PTR(RTYPE(tree)) &&
-      !IS_GENPTR(LTYPE(tree))) {
-    if (DCL_TYPE(LTYPE(tree)) != DCL_TYPE(RTYPE(tree)))
-      werror(W_PTR_ASSIGN);
-  }
+      if (!IS_AST_LIT_VALUE (root->left->right) ||
+          !IS_AST_LIT_VALUE (root->right->right))
+        goto tryNext0;
 
-  TETYPE(tree) = getSpec(TTYPE(tree) =
-             LTYPE(tree));
-  RRVAL(tree) = 1;
-  LLVAL(tree) = 1;
-  if (!tree->initMode && IS_CONSTANT(LETYPE(tree)))
-      werror(E_CODE_WRITE," ");
+      /* make sure it is the same expression */
+      if (!isAstEqual (root->left->left,
+                       root->right->left))
+        goto tryNext0;
 
-  if (LRVAL(tree)) {
-      werror(E_LVALUE_REQUIRED,"=");
-      goto errorTreeReturn ;
-  }
+      if (AST_ULONG_VALUE (root->left->right) != 1)
+        goto tryNext0;
 
-        propAsgType(tree);
+      if (AST_ULONG_VALUE (root->right->right) !=
+          (getSize (TTYPE (root->left->left)) * 8 - 1))
+        goto tryNext0;
 
-  return tree ;
+      /* make sure the port supports RLC */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+        return root;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*      comma operator        */
-  /*----------------------------*/
-    case ',' :
-  TETYPE(tree) = getSpec(TTYPE(tree) =  RTYPE(tree));
-  return tree ;
+      /* whew got the first case : create the AST */
+      return newNode (RLC, root->left->left, NULL);
+    }
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*       function call        */
-  /*----------------------------*/
-    case CALL   :
-  parmNumber = 1;
+tryNext0:
+  /* check for second case */
+  /* (?expr >> 7) | (?expr << 1) */
+  if (IS_LEFT_OP (root->right) &&
+      IS_RIGHT_OP (root->left))
+    {
 
-  if (processParms (tree->left,
-        tree->left->args,
-        tree->right,&parmNumber,TRUE))
-      goto errorTreeReturn ;
+      if (!SPEC_USIGN (TETYPE (root->left->left)))
+        return root;
 
-  if (options.stackAuto || IS_RENT(LETYPE(tree))) {
-    tree->left->args = reverseVal(tree->left->args);
-    reverseParms(tree->right);
-  }
+      if (!IS_AST_LIT_VALUE (root->left->right) ||
+          !IS_AST_LIT_VALUE (root->right->right))
+        goto tryNext1;
 
-  tree->args = tree->left->args ;
-  TETYPE(tree) = getSpec (TTYPE(tree) = LTYPE(tree)->next);
-  return tree;
+      /* make sure it is the same symbol */
+      if (!isAstEqual (root->left->left,
+                       root->right->left))
+        goto tryNext1;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*     return statement       */
-  /*----------------------------*/
-    case RETURN :
-  if (!tree->right)
-      goto voidcheck ;
+      if (AST_ULONG_VALUE (root->right->right) != 1)
+        goto tryNext1;
 
-  if (checkType(currFunc->type->next,RTYPE(tree)) == 0) {
-      werror(E_RETURN_MISMATCH);
-      goto errorTreeReturn ;
-  }
+      if (AST_ULONG_VALUE (root->left->right) !=
+          (getSize (TTYPE (root->left->left)) * 8 - 1))
+        goto tryNext1;
 
-  if (IS_VOID(currFunc->type->next)
-      && tree->right &&
-      !IS_VOID(RTYPE(tree))) {
-      werror(E_FUNC_VOID);
-      goto errorTreeReturn ;
-  }
+      /* make sure the port supports RLC */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+        return root;
 
-  /* if there is going to be a casing required then add it */
-  if (checkType(currFunc->type->next,RTYPE(tree)) < 0 )
-  {
-#if 0 && defined DEMAND_INTEGER_PROMOTION
-      if (IS_INTEGRAL(currFunc->type->next))
-      {
-        pushTypeCastToLeaves(currFunc->type->next, tree->right, &(tree->right));
-      }
-      else
-#endif
-      {
-        tree->right =
-    decorateType(newNode(CAST,
-             newAst_LINK(copyLinkChain(currFunc->type->next)),
-             tree->right));
-      }
-  }
+      /* whew got the first case : create the AST */
+      return newNode (RLC, root->left->left, NULL);
 
-  RRVAL(tree) = 1;
-  return tree;
+    }
 
-  voidcheck :
+tryNext1:
+  /* third case for RRC */
+  /*  (?symbol >> 1) | (?symbol << 7) */
+  if (IS_LEFT_OP (root->right) &&
+      IS_RIGHT_OP (root->left))
+    {
 
-  if (!IS_VOID(currFunc->type->next) && tree->right == NULL ) {
-      werror(E_VOID_FUNC,currFunc->name);
-      goto errorTreeReturn ;
-  }
+      if (!SPEC_USIGN (TETYPE (root->left->left)))
+        return root;
 
-  TTYPE(tree) = TETYPE(tree) = NULL ;
-  return tree ;
+      if (!IS_AST_LIT_VALUE (root->left->right) ||
+          !IS_AST_LIT_VALUE (root->right->right))
+        goto tryNext2;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /*     switch statement       */
-  /*----------------------------*/
-    case SWITCH:
-  /* the switch value must be an integer */
-  if (!IS_INTEGRAL(LTYPE(tree))) {
-      werror (E_SWITCH_NON_INTEGER);
-      goto errorTreeReturn ;
-  }
-  LRVAL(tree) = 1;
-  TTYPE(tree) = TETYPE(tree) = NULL ;
-  return tree ;
+      /* make sure it is the same symbol */
+      if (!isAstEqual (root->left->left,
+                       root->right->left))
+        goto tryNext2;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /* ifx Statement              */
-  /*----------------------------*/
-    case IFX:
-  tree->left = backPatchLabels(tree->left,
-             tree->trueLabel,
-             tree->falseLabel);
-  TTYPE(tree) = TETYPE(tree) = NULL;
-  return tree;
+      if (AST_ULONG_VALUE (root->left->right) != 1)
+        goto tryNext2;
 
-  /*------------------------------------------------------------------*/
-  /*----------------------------*/
-  /* for Statement              */
-  /*----------------------------*/
-    case FOR:
+      if (AST_ULONG_VALUE (root->right->right) !=
+          (getSize (TTYPE (root->left->left)) * 8 - 1))
+        goto tryNext2;
 
-  decorateType(resolveSymbols(AST_FOR(tree,initExpr)));
-  decorateType(resolveSymbols(AST_FOR(tree,condExpr)));
-  decorateType(resolveSymbols(AST_FOR(tree,loopExpr)));
+      /* make sure the port supports RRC */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+        return root;
 
-  /* if the for loop is reversible then
-     reverse it otherwise do what we normally
-     do */
-  {
-      symbol *sym ;
-      ast *init, *end;
+      /* whew got the first case : create the AST */
+      return newNode (RRC, root->left->left, NULL);
 
-      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 ) );
-  }
-    default :
-  TTYPE(tree) = TETYPE(tree) = NULL ;
-  return tree ;
     }
+tryNext2:
+  /* fourth and last case for now */
+  /* (?symbol << 7) | (?symbol >> 1) */
+  if (IS_RIGHT_OP (root->right) &&
+      IS_LEFT_OP (root->left))
+    {
 
-    /* some error found this tree will be killed */
-    errorTreeReturn :
-  TTYPE(tree) = TETYPE(tree) = newCharLink();
-    tree->opval.op = NULLOP ;
-    tree->isError = 1;
+      if (!SPEC_USIGN (TETYPE (root->left->left)))
+        return root;
 
-    return tree ;
-}
+      if (!IS_AST_LIT_VALUE (root->left->right) ||
+          !IS_AST_LIT_VALUE (root->right->right))
+        return root;
 
-/*-----------------------------------------------------------------*/
-/* sizeofOp - processes size of operation                          */
-/*-----------------------------------------------------------------*/
-value  *sizeofOp( sym_link  *type)
-{
-  char buff[10];
+      /* make sure it is the same symbol */
+      if (!isAstEqual (root->left->left,
+                       root->right->left))
+        return root;
 
-  /* get the size and convert it to character  */
-  sprintf (buff,"%d", getSize(type));
+      if (AST_ULONG_VALUE (root->right->right) != 1)
+        return root;
 
-  /* now convert into value  */
-  return  constVal (buff);
-}
+      if (AST_ULONG_VALUE (root->left->right) !=
+          (getSize (TTYPE (root->left->left)) * 8 - 1))
+        return root;
 
+      /* make sure the port supports RRC */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+        return root;
 
-#define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
-#define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
-#define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
-#define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
-#define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
-#define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
-#define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
+      /* whew got the first case : create the AST */
+      return newNode (RRC, root->left->left, NULL);
+
+    }
+
+  /* not found return root */
+  return root;
+}
 
 /*-----------------------------------------------------------------*/
-/* backPatchLabels - change and or not operators to flow control    */
+/* optimizeSWAP :- optimize for nibble/byte/word swaps             */
 /*-----------------------------------------------------------------*/
-ast *backPatchLabels (ast *tree, symbol *trueLabel, symbol *falseLabel )
+ast *
+optimizeSWAP (ast * root)
 {
+  /* will look for trees of the form
+     (?expr << 4) | (?expr >> 4) or
+     (?expr >> 4) | (?expr << 4) will make that
+     into a SWAP : operation ..
+     note : by 4 I mean (number of bits required to hold the
+     variable /2 ) */
+  /* if the root operation is not a | operation then not */
+  if (!IS_BITOR (root))
+    return root;
 
-    if ( ! tree )
-  return NULL ;
-
-    if ( ! (IS_ANDORNOT(tree)))
-  return tree ;
+  /* (?expr << 4) | (?expr >> 4) */
+  if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
+      || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
+    {
 
-    /* if this an and */
-    if (IS_AND(tree)) {
-  static int localLbl = 0 ;
-  symbol *localLabel ;
+      if (!SPEC_USIGN (TETYPE (root->left->left)))
+        return root;
 
-  sprintf (buffer,"_and_%d",localLbl++);
-  localLabel = newSymbol(buffer,NestLevel);
+      if (!IS_AST_LIT_VALUE (root->left->right) ||
+          !IS_AST_LIT_VALUE (root->right->right))
+        return root;
 
-  tree->left = backPatchLabels (tree->left, localLabel,falseLabel);
+      /* make sure it is the same expression */
+      if (!isAstEqual (root->left->left,
+                       root->right->left))
+        return root;
 
-  /* 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);
+      if (AST_ULONG_VALUE (root->left->right) !=
+          (getSize (TTYPE (root->left->left)) * 4))
+        return root;
 
-  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));
+      if (AST_ULONG_VALUE (root->right->right) !=
+          (getSize (TTYPE (root->left->left)) * 4))
+        return root;
 
-  tree->right = createLabel(localLabel,tree->right);
-  tree->right = newIfxNode(tree->right,trueLabel,falseLabel);
+      /* make sure the port supports SWAP */
+      if (port->hasExtBitOp
+          && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
+        return root;
 
-  return newNode(NULLOP,tree->left,tree->right);
+      /* found it : create the AST */
+      return newNode (SWAP, root->left->left, NULL);
     }
 
-    /* if this is an or operation */
-    if (IS_OR(tree)) {
-  static int localLbl = 0 ;
-  symbol *localLabel ;
 
-  sprintf (buffer,"_or_%d",localLbl++);
-  localLabel = newSymbol(buffer,NestLevel);
+  /* not found return root */
+  return root;
+}
 
-  tree->left = backPatchLabels (tree->left, trueLabel,localLabel);
+/*-----------------------------------------------------------------*/
+/* optimizeCompare - optimizes compares for bit variables          */
+/*-----------------------------------------------------------------*/
+static ast *
+optimizeCompare (ast * root)
+{
+  ast *optExpr = NULL;
+  value *vleft;
+  value *vright;
+  unsigned int litValue;
 
-  /* 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);
+  /* if nothing then return nothing */
+  if (!root)
+    return NULL;
 
-  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));
+  /* if not a compare op then do leaves */
+  if (!IS_COMPARE_OP (root))
+    {
+      root->left = optimizeCompare (root->left);
+      root->right = optimizeCompare (root->right);
+      return root;
+    }
 
-  tree->right = createLabel(localLabel,tree->right);
-  tree->right = newIfxNode(tree->right,trueLabel,falseLabel);
+  /* if left & right are the same then depending
+     of the operation do */
+  if (isAstEqual (root->left, root->right))
+    {
+      switch (root->opval.op)
+        {
+        case '>':
+        case '<':
+        case NE_OP:
+          optExpr = newAst_VALUE (constCharVal (0));
+          break;
+        case GE_OP:
+        case LE_OP:
+        case EQ_OP:
+          optExpr = newAst_VALUE (constCharVal (1));
+          break;
+        }
 
-  return newNode(NULLOP,tree->left,tree->right);
+      return decorateType (optExpr, RESULT_TYPE_NONE);
     }
 
-    /* change not */
-    if (IS_NOT(tree)) {
-  int wasnot = IS_NOT(tree->left);
-  tree->left = backPatchLabels (tree->left,falseLabel,trueLabel);
+  vleft = (root->left->type == EX_VALUE ?
+           root->left->opval.val : NULL);
 
-  /* if the left is already a IFX */
-  if ( ! IS_IFX(tree->left) )
-      tree->left = newNode (IFX,tree->left,NULL);
+  vright = (root->right->type == EX_VALUE ?
+            root->right->opval.val : NULL);
 
-  if (wasnot) {
-      tree->left->trueLabel = trueLabel ;
-      tree->left->falseLabel= falseLabel ;
-  } else {
-      tree->left->trueLabel = falseLabel ;
-      tree->left->falseLabel= trueLabel ;
-  }
-  return tree->left ;
-    }
+  /* if left is a BITVAR in BITSPACE */
+  /* and right is a LITERAL then     */
+  /* optimize else do nothing        */
+  if (vleft && vright &&
+      IS_BITVAR (vleft->etype) &&
+      IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
+      IS_LITERAL (vright->etype))
+    {
 
-    if (IS_IFX(tree)) {
-  tree->trueLabel = trueLabel ;
-  tree->falseLabel= falseLabel;
-    }
+      /* if right side > 1 then comparison may never succeed */
+      if ((litValue = (int) ulFromVal (vright)) > 1)
+        {
+          werror (W_BAD_COMPARE);
+          goto noOptimize;
+        }
 
-    return tree ;
-}
+      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;
+            }
+        }
+      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), RESULT_TYPE_NONE);
+    }                           /* end-of-if of BITVAR */
 
+noOptimize:
+  return root;
+}
 
 /*-----------------------------------------------------------------*/
-/* createBlock - create expression tree for block                  */
+/* addSymToBlock : adds the symbol to the first block we find      */
 /*-----------------------------------------------------------------*/
-ast  *createBlock   ( symbol *decl,   ast  *body )
+void
+addSymToBlock (symbol * sym, ast * tree)
 {
-    ast *ex ;
+  /* reached end of tree or a leaf */
+  if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
+    return;
 
-    /* if the block has nothing */
-    if (!body)
-  return NULL;
+  /* found a block */
+  if (IS_AST_OP (tree) &&
+      tree->opval.op == BLOCK)
+    {
+
+      symbol *lsym = copySymbol (sym);
 
-    ex = newNode(BLOCK,NULL,body);
-    ex->values.sym = decl ;
+      lsym->next = AST_VALUES (tree, sym);
+      AST_VALUES (tree, sym) = lsym;
+      return;
+    }
 
-    ex->right = ex->right ;
-    ex->level++ ;
-    ex->lineno = 0 ;
-    return ex;
+  addSymToBlock (sym, tree->left);
+  addSymToBlock (sym, tree->right);
 }
 
 /*-----------------------------------------------------------------*/
-/* createLabel - creates the expression tree for labels            */
+/* processRegParms - do processing for register parameters         */
 /*-----------------------------------------------------------------*/
-ast  *createLabel  ( symbol  *label,  ast  *stmnt  )
+static void
+processRegParms (value * args, ast * body)
 {
-    symbol *csym;
-    char  name[SDCC_NAME_MAX+1];
-    ast   *rValue ;
+  while (args)
+    {
+      if (IS_REGPARM (args->etype))
+        addSymToBlock (args->sym, body);
+      args = args->next;
+    }
+}
 
-    /* must create fresh symbol if the symbol name  */
-    /* exists in the symbol table, since there can  */
-    /* be a variable with the same name as the labl */
-    if ((csym = findSym (SymbolTab,NULL,label->name)) &&
-        (csym->level == label->level))
-  label = newSymbol(label->name,label->level);
+/*-----------------------------------------------------------------*/
+/* resetParmKey - resets the operandkeys for the symbols           */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (resetParmKey)
+{
+  symbol *sym = item;
 
-    /* change the name before putting it in add _*/
-    sprintf (name,"%s",label->name);
+  sym->key = 0;
+  sym->defs = NULL;
+  sym->uses = NULL;
+  sym->remat = 0;
+  return 1;
+}
 
-    /* put the label in the LabelSymbol table    */
-    /* but first check if a label of the same    */
-    /* name exists                               */
-    if ( (csym = findSym(LabelTab,NULL,name)))
-  werror(E_DUPLICATE_LABEL,label->name);
-    else
-  addSym (LabelTab, label, name,label->level,0);
+/*------------------------------------------------------------------*/
+/* fixupInlineLabel - change a label in an inlined function so that */
+/*                    it is always unique no matter how many times  */
+/*                    the function is inlined.                      */
+/*------------------------------------------------------------------*/
+static void
+fixupInlineLabel (symbol * sym)
+{
+  char name[SDCC_NAME_MAX + 1];
 
-    label->islbl = 1;
-    label->key = labelKey++ ;
-    rValue =  newNode (LABEL,newAst_VALUE(symbolVal(label)),stmnt);
-    rValue->lineno = 0;
+  SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
+  strcpy (sym->name, name);
+}
 
-    return rValue ;
+/*------------------------------------------------------------------*/
+/* copyAstLoc - copy location information (file, line, block, etc.) */
+/*              from one ast node to another                        */
+/*------------------------------------------------------------------*/
+static void
+copyAstLoc (ast * dest, ast * src)
+{
+  dest->filename = src->filename;
+  dest->lineno = src->lineno;
+  dest->level = src->level;
+  dest->block = src->block;
+  dest->seqPoint = src->seqPoint;
 }
 
 /*-----------------------------------------------------------------*/
-/* createCase - generates the parsetree for a case statement       */
+/* fixupInline - perform various fixups on an inline function tree */
+/*               to take into account that it is no longer a       */
+/*               stand-alone function.                             */
 /*-----------------------------------------------------------------*/
-ast  *createCase (ast *swStat, ast *caseVal, ast *stmnt   )
+static void
+fixupInline (ast * tree, int level)
 {
-    char caseLbl[SDCC_NAME_MAX+1];
-    ast *rexpr;
-    value *val;
+  int savedBlockno = currBlockno;
 
-    /* if the switch statement does not exist */
-    /* then case is out of context            */
-    if (!swStat) {
-  werror(E_CASE_CONTEXT);
-  return NULL ;
-    }
+  if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
+    {
+      symbol * decls;
 
-    caseVal = decorateType(resolveSymbols(caseVal));
-    /* if not a constant then error  */
-    if (!IS_LITERAL(caseVal->ftype)) {
-  werror(E_CASE_CONSTANT);
-  return NULL ;
-    }
+      currBlockno = ++blockNo;
+      level++;
 
-    /* if not a integer than error */
-    if (!IS_INTEGRAL(caseVal->ftype)) {
-  werror(E_CASE_NON_INTEGER);
-  return NULL;
+      /* Add any declared variables back into the symbol table */
+      decls = tree->values.sym;
+      while (decls)
+        {
+          decls->level = level;
+          decls->block = currBlockno;
+          addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
+          decls = decls->next;
+        }
     }
 
-    /* find the end of the switch values chain   */
-    if (!(val = swStat->values.switchVals.swVals))
-  swStat->values.switchVals.swVals = caseVal->opval.val ;
-    else {
-  /* also order the cases according to value */
-  value *pval = NULL;
-  int cVal = (int) floatFromVal(caseVal->opval.val);
-  while (val && (int) floatFromVal(val) < cVal) {
-      pval = val;
-      val = val->next ;
-  }
+  tree->level = level;
+  tree->block = currBlockno;
 
-  /* if we reached the end then */
-  if (!val) {
-      pval->next =  caseVal->opval.val;
-  } 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;
-  }
+  /* Update symbols */
+  if (IS_AST_VALUE (tree) &&
+      tree->opval.val->sym)
+    {
+      symbol * sym = tree->opval.val->sym;
+
+      sym->level = level;
+      sym->block = currBlockno;
+
+      sym->reqv = NULL;
+      SYM_SPIL_LOC (sym) = NULL;
+      sym->key = 0;
 
+      /* If the symbol is a label, we need to renumber it */
+      if (sym->islbl)
+        fixupInlineLabel (sym);
     }
 
-    /* create the case label   */
-    sprintf(caseLbl,"_case_%d_%d",
-      swStat->values.switchVals.swNum,
-      (int) floatFromVal(caseVal->opval.val));
+  /* Update IFX target labels */
+  if (tree->type == EX_OP && tree->opval.op == IFX)
+    {
+      if (tree->trueLabel)
+        fixupInlineLabel (tree->trueLabel);
+      if (tree->falseLabel)
+        fixupInlineLabel (tree->falseLabel);
+    }
 
-    rexpr = createLabel(newSymbol(caseLbl,0),stmnt);
-    rexpr->lineno = 0;
-    return rexpr;
-}
+  /* Replace RETURN with optional assignment and a GOTO to the end */
+  /* of the inlined function */
+  if (tree->type == EX_OP && tree->opval.op == RETURN)
+    {
+      ast * assignTree = NULL;
+      ast * gotoTree;
 
-/*-----------------------------------------------------------------*/
-/* createDefault - creates the parse tree for the default statement*/
-/*-----------------------------------------------------------------*/
-ast  *createDefault (ast *swStat, ast *stmnt)
-{
-    char  defLbl[SDCC_NAME_MAX+1];
+      if (inlineState.retsym && tree->right)
+        {
+          assignTree = newNode ('=',
+                                newAst_VALUE (symbolVal (inlineState.retsym)),
+                                tree->right);
+          copyAstLoc (assignTree, tree);
+        }
 
-    /* if the switch statement does not exist */
-    /* then case is out of context            */
-    if (!swStat) {
-  werror(E_CASE_CONTEXT);
-  return NULL ;
-    }
+      gotoTree = newNode (GOTO,
+                          newAst_VALUE (symbolVal (inlineState.retlab)),
+                          NULL);
+      copyAstLoc (gotoTree, tree);
 
-    /* turn on the default flag   */
-    swStat->values.switchVals.swDefault = 1   ;
+      tree->opval.op = NULLOP;
+      tree->left = assignTree;
+      tree->right = gotoTree;
+    }
 
-    /* create the label  */
-    sprintf (defLbl,"_default_%d",swStat->values.switchVals.swNum);
-    return createLabel(newSymbol(defLbl,0),stmnt);
-}
+  /* Update any children */
+  if (tree->left)
+      fixupInline (tree->left, level);
+  if (tree->right)
+      fixupInline (tree->right, level);
 
-/*-----------------------------------------------------------------*/
-/* createIf - creates the parsetree for the if statement           */
-/*-----------------------------------------------------------------*/
-ast *createIf ( ast *condAst, ast *ifBody, ast *elseBody )
-{
-    static int Lblnum = 0 ;
-    ast *ifTree ;
-    symbol *ifTrue , *ifFalse, *ifEnd ;
-
-    /* if neither exists */
-    if (! elseBody && !ifBody)
-  return condAst ;
-
-    /* create the labels */
-    sprintf (buffer,"_iffalse_%d",Lblnum);
-    ifFalse = newSymbol (buffer,NestLevel);
-    /* if no else body then end == false */
-    if ( ! elseBody )
-  ifEnd = ifFalse ;
-    else {
-  sprintf (buffer,"_ifend_%d",Lblnum);
-  ifEnd = newSymbol (buffer,NestLevel);
-    }
-
-    sprintf (buffer,"_iftrue_%d",Lblnum);
-    ifTrue = newSymbol (buffer,NestLevel);
-
-    Lblnum++ ;
-
-    /* attach the ifTrue label to the top of it body */
-    ifBody = createLabel(ifTrue,ifBody);
-    /* attach a goto end to the ifBody if else is present */
-    if ( elseBody ) {
-  ifBody = newNode(NULLOP,ifBody,
-       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));
-    }
-    else {
-  ifBody = newNode(NULLOP,ifBody,
-       createLabel(ifFalse,NULL));
-    }
-    condAst = backPatchLabels (condAst,ifTrue,ifFalse);
-    if (IS_IFX(condAst))
-  ifTree = condAst;
-    else
-  ifTree = newIfxNode(condAst,ifTrue,ifFalse);
+  if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
+    {
+      symbol * label = tree->left->opval.val->sym;
 
-    return newNode(NULLOP,ifTree,
-       newNode(NULLOP,ifBody,elseBody));
+      label->key = labelKey++;
+      /* Add this label back into the symbol table */
+      addSym (LabelTab, label, label->name, label->level, 0, 0);
+    }
 
+  if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
+    {
+      level--;
+      currBlockno = savedBlockno;
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* createDo - creates parse tree for do                            */
-/*        _dobody_n:                                               */
-/*            statements                                           */
-/*        _docontinue_n:                                           */
-/*            condition_expression +-> trueLabel -> _dobody_n      */
-/*                                 |                               */
-/*                                 +-> falseLabel-> _dobreak_n     */
-/*        _dobreak_n:                                              */
+/* inlineAddDecl - add a variable declaration to an ast block. It  */
+/*                 is also added to the symbol table if addSymTab  */
+/*                 is nonzero.                                     */
 /*-----------------------------------------------------------------*/
-ast *createDo ( symbol *trueLabel, symbol *continueLabel,
-    symbol *falseLabel, ast *condAst, ast *doBody )
+static void
+inlineAddDecl (symbol * sym, ast * block, int addSymTab)
 {
-    ast *doTree ;
-
-
-    /* if the body does not exist then it is simple */
-    if ( ! doBody ) {
-  condAst = backPatchLabels(condAst,continueLabel,NULL);
-  doTree = (IS_IFX(condAst) ? createLabel(continueLabel,condAst)
-      : newNode(IFX,createLabel(continueLabel,condAst),NULL));
-  doTree->trueLabel = continueLabel ;
-  doTree->falseLabel= NULL ;
-  return doTree ;
-    }
+  sym->reqv = NULL;
+  SYM_SPIL_LOC (sym) = NULL;
+  sym->key = 0;
+  if (block != NULL)
+    {
+      symbol **decl = &(block->values.sym);
 
-    /* otherwise we have a body */
-    condAst = backPatchLabels(condAst,trueLabel,falseLabel);
+      sym->level = block->level;
+      sym->block = block->block;
 
-    /* attach the body label to the top */
-    doBody = createLabel(trueLabel,doBody);
-    /* attach the continue label to end of body */
-    doBody = newNode(NULLOP, doBody,
-         createLabel(continueLabel,NULL));
+      while (*decl)
+        {
+          if (strcmp ((*decl)->name, sym->name) == 0)
+            return;
+          decl = &( (*decl)->next );
+        }
 
-    /* now put the break label at the end */
-    if (IS_IFX(condAst))
-  doTree = condAst;
-    else
-  doTree = newIfxNode(condAst,trueLabel,falseLabel);
+      *decl = sym;
 
-    doTree = newNode(NULLOP,doTree,createLabel(falseLabel,NULL));
+      if (addSymTab)
+        addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
 
-    /* putting it together */
-    return newNode(NULLOP,doBody,doTree);
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* createFor - creates parse tree for 'for' statement              */
-/*        initExpr                                                 */
-/*   _forcond_n:                                                   */
-/*        condExpr  +-> trueLabel -> _forbody_n                    */
-/*                  |                                              */
-/*                  +-> falseLabel-> _forbreak_n                   */
-/*   _forbody_n:                                                   */
-/*        statements                                               */
-/*   _forcontinue_n:                                               */
-/*        loopExpr                                                 */
-/*        goto _forcond_n ;                                        */
-/*   _forbreak_n:                                                  */
+/* inlineTempVar - create a temporary variable for inlining        */
 /*-----------------------------------------------------------------*/
-ast *createFor ( symbol *trueLabel, symbol *continueLabel ,
-     symbol *falseLabel,symbol *condLabel     ,
-     ast *initExpr, ast *condExpr, ast *loopExpr,
-     ast *forBody )
+static symbol *
+inlineTempVar (sym_link * type, int level)
 {
-    ast *forTree ;
-
-    /* if loopexpression not present then we can generate it */
-    /* the same way as a while */
-    if ( ! loopExpr )
-  return newNode(NULLOP,initExpr,
-           createWhile (trueLabel, continueLabel,
-            falseLabel,condExpr, forBody ));
-    /* vanilla for statement */
-    condExpr = backPatchLabels(condExpr,trueLabel,falseLabel);
-
-    if (condExpr && !IS_IFX(condExpr))
-  condExpr = newIfxNode(condExpr,trueLabel,falseLabel);
-
-
-    /* attach condition label to condition */
-    condExpr = createLabel(condLabel,condExpr);
-
-    /* attach body label to body */
-    forBody = createLabel(trueLabel,forBody);
+  symbol * sym;
+
+  sym = newSymbol (genSymName(level), level );
+  sym->type = copyLinkChain (type);
+  sym->etype = getSpec(sym->type);
+  SPEC_SCLS (sym->etype) = S_AUTO;
+  SPEC_OCLS (sym->etype) = NULL;
+  SPEC_EXTR (sym->etype) = 0;
+  SPEC_STAT (sym->etype) = 0;
+  if IS_SPEC (sym->type)
+    SPEC_VOLATILE (sym->type) = 0;
+  else
+    DCL_PTR_VOLATILE (sym->type) = 0;
+  SPEC_ABSA (sym->etype) = 0;
 
-    /* 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)));
-    /* 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));
-    return forTree ;
+  return sym;
 }
 
 /*-----------------------------------------------------------------*/
-/* createWhile - creates parse tree for while statement            */
-/*               the while statement will be created as follows    */
-/*                                                                 */
-/*      _while_continue_n:                                         */
-/*            condition_expression +-> trueLabel -> _while_boby_n  */
-/*                                 |                               */
-/*                                 +-> falseLabel -> _while_break_n*/
-/*      _while_body_n:                                             */
-/*            statements                                           */
-/*            goto _while_continue_n                               */
-/*      _while_break_n:                                            */
+/* inlineFindParmRecurse - recursive function for inlineFindParm   */
 /*-----------------------------------------------------------------*/
-ast *createWhile (symbol *trueLabel, symbol *continueLabel,
-       symbol *falseLabel,ast *condExpr, ast *whileBody )
+static ast *
+inlineFindParmRecurse (ast * parms, int *index)
 {
-    ast *whileTree ;
+  if (!parms)
+    return NULL;
 
-    /* put the continue label */
-    condExpr = backPatchLabels (condExpr,trueLabel,falseLabel);
-    condExpr = createLabel(continueLabel,condExpr);
-    condExpr->lineno = 0;
-
-    /* put the body label in front of the body */
-    whileBody = createLabel(trueLabel,whileBody);
-    whileBody->lineno = 0;
-    /* 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)));
-
-    /* put it all together */
-    if ( IS_IFX(condExpr) )
-  whileTree = condExpr ;
-    else {
-  whileTree = newNode (IFX, condExpr,NULL );
-  /* put the true & false labels in place */
-  whileTree->trueLabel = trueLabel ;
-  whileTree->falseLabel= falseLabel;
-    }
+  if (parms->type == EX_OP && parms->opval.op == PARAM)
+  {
+    ast * p;
+
+    p=inlineFindParmRecurse (parms->left, index);
+    if (p)
+      return p;
+    p=inlineFindParmRecurse (parms->right, index);
+    if (p)
+      return p;
+  }
+  if (!*index)
+    return parms;
+  (*index)--;
+  return NULL;
+}
 
-    return newNode(NULLOP,whileTree,whileBody );
+/*-----------------------------------------------------------------*/
+/* inlineFindParm - search an ast tree of parameters to find one   */
+/*                  at a particular index (0=first parameter).     */
+/*                  Returns NULL if not found.                     */
+/*-----------------------------------------------------------------*/
+static ast *
+inlineFindParm (ast * parms, int index)
+{
+  return inlineFindParmRecurse (parms, &index);
 }
 
 /*-----------------------------------------------------------------*/
-/* optimizeGetHbit - get highest order bit of the expression       */
+/* expandInlineFuncs - replace calls to inline functions with the  */
+/*                     function itself                             */
 /*-----------------------------------------------------------------*/
-ast *optimizeGetHbit (ast *tree)
+static void
+expandInlineFuncs (ast * tree, ast * block)
 {
-    int i,j;
-    /* if this is not a bit and */
-    if (!IS_BITAND(tree))
-  return tree;
+  if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
+      && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
+    {
+      symbol * func = tree->left->opval.val->sym;
+      symbol * csym;
 
-    /* will look for tree of the form
-       ( expr >> ((sizeof expr) -1) ) & 1 */
-    if (!IS_AST_LIT_VALUE(tree->right))
-  return tree;
+      /* The symbol is probably not bound yet, so find the real one */
+      csym = findSymWithLevel (SymbolTab, func);
+      if (csym)
+        func = csym;
 
-    if (AST_LIT_VALUE(tree->right) != 1)
-  return tree;
+      /* Is this an inline function that we can inline? */
+      if (IFFUNC_ISINLINE (func->type) && func->funcTree)
+        {
+          symbol * retsym = NULL;
+          symbol * retlab;
+          ast * inlinetree;
+          ast * inlinetree2;
+          ast * temptree;
+          value * args;
+          int argIndex;
+
+          /* Generate a label for the inlined function to branch to */
+          /* in case it contains a return statement */
+          retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
+          retlab->isitmp = 1;
+          retlab->islbl = 1;
+          inlineState.retlab = retlab;
+
+          /* Build the subtree for the inlined function in the form: */
+          /* { //inlinetree block                                    */
+          /*   { //inlinetree2 block                                 */
+          /*     inline_function_code;                               */
+          /*     retlab:                                             */
+          /*   }                                                     */
+          /* }                                                       */
+          temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
+          copyAstLoc (temptree, tree);
+          temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
+          copyAstLoc (temptree, tree);
+          temptree = newNode (BLOCK, NULL, temptree);
+          copyAstLoc (temptree, tree);
+          inlinetree2 = temptree;
+          inlinetree = newNode (BLOCK, NULL, inlinetree2);
+          copyAstLoc (inlinetree, tree);
+
+          /* To pass parameters to the inlined function, we need some  */
+          /* intermediate variables. This avoids scoping problems      */
+          /* when the parameter declaration names are used differently */
+          /* during the function call. For example, a function         */
+          /* declared as func(int x, int y) but called as func(y,x).   */
+          /* { //inlinetree block                                      */
+          /*   type1 temparg1 = argument1;                             */
+          /*   ...                                                     */
+          /*   typen tempargn = argumentn;                             */
+          /*   { //inlinetree2 block                                   */
+          /*     type1 param1 = temparg1;                              */
+          /*     ...                                                   */
+          /*     typen paramn = tempargn;                              */
+          /*     inline_function_code;                                 */
+          /*     retlab:                                               */
+          /*   }                                                       */
+          /* }                                                         */
+          args = FUNC_ARGS (func->type);
+          argIndex = 0;
+          while (args)
+            {
+              symbol * temparg;
+              ast * assigntree;
+              symbol * parm;
+              ast * passedarg = inlineFindParm (tree->right, argIndex);
+
+              if (!passedarg)
+                {
+                  werror(E_TOO_FEW_PARMS);
+                  break;
+                }
+
+              temparg = inlineTempVar (args->sym->type, tree->level+1);
+              inlineAddDecl (temparg, inlinetree, FALSE);
+
+              assigntree = newNode ('=',
+                                    newAst_VALUE (symbolVal (temparg)),
+                                    passedarg);
+              assigntree->initMode=1; // tell that assignment is initializer
+              inlinetree->right = newNode (NULLOP,
+                                           assigntree,
+                                           inlinetree->right);
+
+              parm = copySymbol (args->sym);
+              inlineAddDecl (parm, inlinetree2, FALSE);
+              parm->_isparm = 0;
+
+              assigntree = newNode ('=',
+                                    newAst_VALUE (symbolVal (parm)),
+                                    newAst_VALUE (symbolVal (temparg)));
+              assigntree->initMode=1; // tell that assignment is initializer
+              inlinetree2->right = newNode (NULLOP,
+                                           assigntree,
+                                           inlinetree2->right);
+
+              args = args->next;
+              argIndex++;
+            }
+
+          /* Handle the return type */
+          if (!IS_VOID (func->type->next))
+            {
+              /* Create a temporary symbol to hold the return value and   */
+              /* join it with the inlined function using the comma        */
+              /* operator. The fixupInline function will take care of     */
+              /* changing return statements into assignments to retsym.   */
+              /* (parameter passing and return label omitted for clarity) */
+              /* rettype retsym;                                          */
+              /* ...                                                      */
+              /* {{inline_function_code}}, retsym                         */
+
+              retsym = inlineTempVar (func->type->next, tree->level);
+              inlineAddDecl (retsym, block, TRUE);
+
+              tree->opval.op = ',';
+              tree->left = inlinetree;
+              tree->right = newAst_VALUE (symbolVal (retsym));
+            }
+          else
+            {
+              tree->opval.op = NULLOP;
+              tree->left = NULL;
+              tree->right = inlinetree;
+            }
+          inlineState.retsym = retsym;
+
+          /* Renumber the various internal counters on the inlined   */
+          /* function's tree nodes and symbols. Add the inlined      */
+          /* function's local variables to the appropriate scope(s). */
+          /* Convert inlined return statements to an assignment to   */
+          /* retsym (if needed) and a goto retlab.                   */
+          fixupInline (inlinetree, inlinetree->level);
+          inlineState.count++;
+        }
+    }
 
-    if (!IS_RIGHT_OP(tree->left))
-  return tree;
+  /* Recursively continue to search for functions to inline. */
+  if (IS_AST_OP (tree))
+    {
+      if (tree->opval.op == BLOCK)
+        block = tree;
 
-    if (!IS_AST_LIT_VALUE(tree->left->right))
-  return tree;
+      if (tree->left)
+        expandInlineFuncs (tree->left, block);
+      if (tree->right)
+        expandInlineFuncs (tree->right, block);
+    }
+}
 
-    if ((i = (int) AST_LIT_VALUE(tree->left->right)) !=
-  ( j = (getSize(TTYPE(tree->left->left))*8 - 1)))
-  return tree;
+/*-----------------------------------------------------------------*/
+/* createFunction - This is the key node that calls the iCode for  */
+/*                  generating the code for a function. Note code  */
+/*                  is generated function by function, later when  */
+/*                  add inter-procedural analysis this will change */
+/*-----------------------------------------------------------------*/
+ast *
+createFunction (symbol * name, ast * body)
+{
+  ast *ex;
+  symbol *csym;
+  int stack = 0;
+  sym_link *fetype;
+  iCode *piCode = NULL;
 
-    return decorateType(newNode(GETHBIT,tree->left->left,NULL));
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
 
-}
+  /* if check function return 0 then some problem */
+  if (checkFunction (name, NULL) == 0)
+    return NULL;
 
-/*-----------------------------------------------------------------*/
-/* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
-/*-----------------------------------------------------------------*/
-ast *optimizeRRCRLC ( ast *root )
-{
-    /* will look for trees of the form
-       (?expr << 1) | (?expr >> 7) or
-       (?expr >> 7) | (?expr << 1) will make that
-       into a RLC : operation ..
-       Will also look for
-       (?expr >> 1) | (?expr << 7) or
-       (?expr << 7) | (?expr >> 1) will make that
-       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 (!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
-       negative check a lot to improve the efficiency */
-    /* (?expr << 1) | (?expr >> 7) */
-    if (IS_LEFT_OP(root->left)    &&
-  IS_RIGHT_OP(root->right)  ) {
-
-  if (!SPEC_USIGN(TETYPE(root->left->left)))
-      return root;
+  /* create a dummy block if none exists */
+  if (!body)
+    body = newNode (BLOCK, NULL, NULL);
 
-  if (!IS_AST_LIT_VALUE(root->left->right) ||
-      !IS_AST_LIT_VALUE(root->right->right))
-      goto tryNext0;
+  noLineno++;
 
-  /* make sure it is the same expression */
-  if (!isAstEqual(root->left->left,
-      root->right->left))
-      goto tryNext0;
+  /* check if the function name already in the symbol table */
+  if ((csym = findSym (SymbolTab, NULL, name->name)))
+    {
+      name = csym;
+      /* special case for compiler defined functions
+         we need to add the name to the publics list : this
+         actually means we are now compiling the compiler
+         support routine */
+      if (name->cdef)
+        {
+          addSet (&publics, name);
+        }
+    }
+  else
+    {
+      addSymChain (&name);
+      allocVariables (name);
+    }
+  name->lastLine = lexLineno;
+  currFunc = name;
 
-  if (AST_LIT_VALUE(root->left->right) != 1 )
-      goto tryNext0 ;
+  /* set the stack pointer */
+  stackPtr  = -port->stack.direction * port->stack.call_overhead;
+  xstackPtr = 0;
 
-  if (AST_LIT_VALUE(root->right->right) !=
-      (getSize(TTYPE(root->left->left))*8 - 1))
-      goto tryNext0 ;
+  if (IFFUNC_ISISR (name->type))
+    stackPtr -= port->stack.direction * port->stack.isr_overhead;
 
-  /* whew got the first case : create the AST */
-  return  newNode(RLC,root->left->left,NULL);
+  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;
     }
 
- tryNext0:
-    /* check for second case */
-    /* (?expr >> 7) | (?expr << 1) */
-    if (IS_LEFT_OP(root->right)    &&
-  IS_RIGHT_OP(root->left)  ) {
-
-  if (!SPEC_USIGN(TETYPE(root->left->left)))
-      return root;
+  fetype = getSpec (name->type);        /* get the specifier for the function */
+  /* if this is a reentrant function then */
+  if (IFFUNC_ISREENT (name->type))
+    reentrant++;
 
-  if (!IS_AST_LIT_VALUE(root->left->right) ||
-      !IS_AST_LIT_VALUE(root->right->right))
-      goto tryNext1 ;
+  inlineState.count = 0;
+  expandInlineFuncs (body, NULL);
 
-  /* make sure it is the same symbol */
-  if (!isAstEqual(root->left->left,
-      root->right->left))
-      goto tryNext1 ;
+  if (FUNC_ISINLINE (name->type))
+    name->funcTree = copyAst (body);
 
-  if (AST_LIT_VALUE(root->right->right) != 1 )
-      goto tryNext1 ;
+  allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
 
-  if (AST_LIT_VALUE(root->left->right) !=
-      (getSize(TTYPE(root->left->left))*8 - 1))
-      goto tryNext1 ;
+  /* do processing for parameters that are passed in registers */
+  processRegParms (FUNC_ARGS(name->type), body);
 
-  /* whew got the first case : create the AST */
-  return  newNode(RLC,root->left->left,NULL);
+  /* set the stack pointer */
+  stackPtr = 0;
+  xstackPtr = -1;
 
-    }
+  gatherImplicitVariables (body, NULL);  /* move implicit variables into blocks */
 
- tryNext1:
-    /* third case for RRC */
-    /*  (?symbol >> 1) | (?symbol << 7) */
-    if (IS_LEFT_OP(root->right)    &&
-  IS_RIGHT_OP(root->left)  ) {
+  /* allocate & autoinit the block variables */
+  processBlockVars (body, &stack, ALLOCATE);
 
-  if (!SPEC_USIGN(TETYPE(root->left->left)))
-      return root;
+  /* name needs to be mangled */
+  SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
 
-  if (!IS_AST_LIT_VALUE(root->left->right) ||
-      !IS_AST_LIT_VALUE(root->right->right))
-      goto tryNext2;
+  body = resolveSymbols (body); /* resolve the symbols */
+  body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
 
-  /* make sure it is the same symbol */
-  if (!isAstEqual(root->left->left,
-      root->right->left))
-      goto tryNext2;
+  /* save the stack information */
+  if (options.useXstack)
+    name->xstack = SPEC_STAK (fetype) = stack;
+  else
+    name->stack = SPEC_STAK (fetype) = stack;
+
+  ex = newAst_VALUE (symbolVal (name)); /* create name */
+  ex = newNode (FUNCTION, ex, body);
+  ex->values.args = FUNC_ARGS(name->type);
+  ex->decorated=1;
+  if (options.dump_tree)
+    PA(ex);
+  if (fatalError)
+    goto skipall;
+
+  /* Do not generate code for inline functions unless extern also. */
+#if 0
+  if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
+    goto skipall;
+#else
+  /* Temporary hack: always generate code for static inline functions. */
+  /* Ideally static inline functions should only be generated if needed. */
+  if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
+    goto skipall;
+#endif
 
-  if (AST_LIT_VALUE(root->left->right) != 1 )
-      goto tryNext2;
+  /* create the node & generate intermediate code */
+  GcurMemmap = code;
+  codeOutBuf = &code->oBuf;
+  piCode = iCodeFromAst (ex);
+  name->generated = 1;
 
-  if (AST_LIT_VALUE(root->right->right) !=
-      (getSize(TTYPE(root->left->left))*8 - 1))
-      goto tryNext2;
+  if (fatalError)
+    goto skipall;
 
-  /* whew got the first case : create the AST */
-  return newNode(RRC,root->left->left,NULL);
+  eBBlockFromiCode (piCode);
 
+  /* if there are any statics then do them */
+  if (staticAutos)
+    {
+      GcurMemmap = statsg;
+      codeOutBuf = &statsg->oBuf;
+      eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
+      staticAutos = NULL;
     }
- tryNext2:
-    /* fourth and last case for now */
-    /* (?symbol << 7) | (?symbol >> 1) */
-    if (IS_RIGHT_OP(root->right)    &&
-  IS_LEFT_OP(root->left)  ) {
-
-  if (!SPEC_USIGN(TETYPE(root->left->left)))
-      return root;
 
-  if (!IS_AST_LIT_VALUE(root->left->right) ||
-      !IS_AST_LIT_VALUE(root->right->right))
-      return root;
+skipall:
 
-  /* make sure it is the same symbol */
-  if (!isAstEqual(root->left->left,
-      root->right->left))
-      return root;
+  /* dealloc the block variables */
+  processBlockVars (body, &stack, DEALLOCATE);
+  outputDebugStackSymbols();
+  /* deallocate paramaters */
+  deallocParms (FUNC_ARGS(name->type));
 
-  if (AST_LIT_VALUE(root->right->right) != 1 )
-      return root ;
+  if (IFFUNC_ISREENT (name->type))
+    reentrant--;
 
-  if (AST_LIT_VALUE(root->left->right) !=
-      (getSize(TTYPE(root->left->left))*8 - 1))
-      return root ;
+  /* we are done freeup memory & cleanup */
+  noLineno--;
+  if (port->reset_labelKey)
+    labelKey = 1;
+  name->key = 0;
+  FUNC_HASBODY(name->type) = 1;
+  addSet (&operKeyReset, name);
+  applyToSet (operKeyReset, resetParmKey);
 
-  /* whew got the first case : create the AST */
-  return  newNode(RRC,root->left->left,NULL);
+  if (options.debug)
+    cdbStructBlock(1);
 
-    }
+  cleanUpLevel (LabelTab, 0);
+  cleanUpBlock (StructTab, 1);
+  cleanUpBlock (TypedefTab, 1);
 
-    /* not found return root */
-    return root;
+  xstack->syms = NULL;
+  istack->syms = NULL;
+  return NULL;
 }
 
+
+#define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
 /*-----------------------------------------------------------------*/
-/* optimizeCompare - otimizes compares for bit variables     */
+/* ast_print : prints the ast (for debugging purposes)             */
 /*-----------------------------------------------------------------*/
-ast  *optimizeCompare ( ast *root )
+
+void ast_print (ast * tree, FILE *outfile, int indent)
 {
-    ast *optExpr = NULL;
-    value *vleft;
-    value *vright;
-    unsigned int litValue ;
 
-    /* if nothing then return nothing */
-    if (!root)
-  return NULL ;
+  if (!tree) return ;
 
-    /* if not a compare op then do leaves */
-    if (!IS_COMPARE_OP(root)) {
-  root->left = optimizeCompare (root->left);
-  root->right= optimizeCompare (root->right);
-  return root ;
-    }
+  /* can print only decorated trees */
+  if (!tree->decorated) return;
 
-    /* if left & right are the same then depending
-       of the operation do */
-    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;
+  /* 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);
   }
 
-  return decorateType(optExpr);
-    }
-
-    vleft = (root->left->type == EX_VALUE ?
-       root->left->opval.val : NULL );
-
-    vright = (root->right->type == EX_VALUE ?
-        root->right->opval.val : NULL);
 
-    /* if left is a BITVAR in BITSPACE */
-    /* and right is a LITERAL then opt-*/
-    /* imize else do nothing       */
-    if (vleft && vright                   &&
-  IS_BITVAR(vleft->etype)     &&
-  IN_BITSPACE(SPEC_OCLS(vleft->etype))  &&
-  IS_LITERAL(vright->etype)) {
-
-  /* if right side > 1 then comparison may never succeed */
-  if ( (litValue = (int) floatFromVal(vright)) > 1 ) {
-      werror(W_BAD_COMPARE);
-      goto noOptimize ;
+  /* 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 ( 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;
-      }
-  } 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;
+  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 ;
   }
-  return decorateType(resolveSymbols(optExpr));
-    } /* end-of-if of BITVAR */
-
-    noOptimize :
-  return root;
-}
-/*-----------------------------------------------------------------*/
-/* addSymToBlock : adds the symbol to the first block we find      */
-/*-----------------------------------------------------------------*/
-void addSymToBlock (symbol *sym, ast *tree)
-{
-    /* reached end of tree or a leaf */
-    if (!tree || IS_AST_LINK(tree) || IS_AST_VALUE(tree))
-  return ;
-
-    /* found a block */
-    if (IS_AST_OP(tree) &&
-  tree->opval.op == BLOCK ) {
-
-  symbol *lsym = copySymbol(sym);
-
-  lsym->next = AST_VALUES(tree,sym);
-  AST_VALUES(tree,sym) = lsym ;
-  return ;
-    }
-
-    addSymToBlock(sym,tree->left);
-    addSymToBlock(sym,tree->right);
-}
-
-/*-----------------------------------------------------------------*/
-/* processRegParms - do processing for register parameters         */
-/*-----------------------------------------------------------------*/
-static void processRegParms (value *args, ast *body)
-{
-    while (args) {
-  if (IS_REGPARM(args->etype))
-      addSymToBlock(args->sym,body);
-  args = args->next;
+  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;
     }
-}
-
-/*-----------------------------------------------------------------*/
-/* resetParmKey - resets the operandkeys for the symbols           */
-/*-----------------------------------------------------------------*/
-DEFSETFUNC(resetParmKey)
-{
-    symbol *sym = item;
-
-    sym->key = 0 ;
-    sym->defs = NULL ;
-    sym->uses = NULL ;
-    sym->remat= 0;
-    return 1;
-}
-
-/*-----------------------------------------------------------------*/
-/* createFunction - This is the key node that calls the iCode for  */
-/*                  generating the code for a function. Note code  */
-/*                  is generated function by function, later when  */
-/*                  add inter-procedural analysis this will change */
-/*-----------------------------------------------------------------*/
-ast  *createFunction   (symbol  *name,   ast  *body )
-{
-    ast  *ex ;
-    symbol *csym;
-    int stack = 0 ;
-    sym_link *fetype;
-    iCode *piCode = NULL;
-
-    /* if check function return 0 then some problem */
-    if (checkFunction (name) == 0)
-  return NULL;
-
-    /* create a dummy block if none exists */
-    if (!body)
-  body = newNode(BLOCK,NULL,NULL);
-
-    noLineno++ ;
-
-    /* check if the function name already in the symbol table */
-    if ((csym = findSym (SymbolTab,NULL,name->name))) {
-  name = csym ;
-  /* special case for compiler defined functions
-     we need to add the name to the publics list : this
-     actually means we are now compiling the compiler
-     support routine */
-  if (name->cdef) {
-      addSet(&publics,name);
+    ast_print(tree->right,outfile,indent+2);
+    INDENT(indent,outfile);
+    fprintf(outfile,"}\n");
+    return;
+  }
+  if (tree->opval.op == NULLOP) {
+    ast_print(tree->left,outfile,indent);
+    ast_print(tree->right,outfile,indent);
+    return ;
   }
+  INDENT(indent,outfile);
+
+  /*------------------------------------------------------------------*/
+  /*----------------------------*/
+  /*   leaf has been reached    */
+  /*----------------------------*/
+  /* if this is of type value */
+  /* just get the type        */
+  if (tree->type == EX_VALUE) {
+
+    if (IS_LITERAL (tree->opval.val->etype)) {
+      fprintf(outfile,"CONSTANT (%p) value = ", tree);
+      if (SPEC_USIGN (tree->opval.val->etype))
+        fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
+      else
+        fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
+      fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
+        floatFromVal(tree->opval.val));
+    } else if (tree->opval.val->sym) {
+      /* if the undefined flag is set then give error message */
+      if (tree->opval.val->sym->undefined) {
+        fprintf(outfile,"UNDEFINED SYMBOL ");
+      } else {
+        fprintf(outfile,"SYMBOL ");
+      }
+      fprintf(outfile,"(%s=%p @ %p)",
+        tree->opval.val->sym->name, tree, tree->opval.val->sym);
     }
-    else {
-  addSymChain(name);
-  allocVariables(name);
+    if (tree->ftype) {
+      fprintf(outfile," type (");
+      printTypeChain(tree->ftype,outfile);
+      fprintf(outfile,")\n");
+    } else {
+      fprintf(outfile,"\n");
     }
-    name->lastLine = yylineno;
-    currFunc = name ;
-    processFuncArgs(currFunc,0);
-
-    /* set the stack pointer */
-    /* PENDING: check this for the mcs51 */
-    stackPtr = -port->stack.direction * port->stack.call_overhead;
-    if (IS_ISR(name->etype))
-  stackPtr -= port->stack.direction * port->stack.isr_overhead;
-    if (IS_RENT(name->etype) || options.stackAuto)
-  stackPtr -= port->stack.direction * port->stack.reent_overhead;
+    return ;
+  }
 
-    xstackPtr = -port->stack.direction * port->stack.call_overhead;
+  /* 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 ;
+  }
 
-    fetype = getSpec(name->type); /* get the specifier for the function */
-    /* if this is a reentrant function then */
-    if (IS_RENT(fetype))
-  reentrant++ ;
 
-    allocParms (name->args);           /* allocate the parameters */
+  /* depending on type of operator do */
 
-    /* do processing for parameters that are passed in registers */
-    processRegParms (name->args,body);
+  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;
 
-   /* set the stack pointer */
-    stackPtr = 0;
-    xstackPtr= -1;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*      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 ;
 
-    /* allocate & autoinit the block variables */
-    processBlockVars (body, &stack,ALLOCATE);
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*    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 ;
 
-    /* save the stack information */
-    if (options.useXstack)
-  name->xstack = SPEC_STAK(fetype) = stack;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*  ++/-- operation           */
+    /*----------------------------*/
+  case INC_OP:
+    if (tree->left)
+      fprintf(outfile,"post-");
     else
-  name->stack = SPEC_STAK(fetype) = stack;
+      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 ;
 
-    /* name needs to be mangled */
-    sprintf (name->rname,"%s%s", port->fun_prefix, name->name);
+  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 ;
 
-    body = resolveSymbols(body); /* resolve the symbols */
-    body = decorateType (body);  /* propagateType & do semantic checks */
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*  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 ;
 
-    ex = newAst_VALUE(symbolVal(name));    /* create name       */
-    ex = newNode (FUNCTION,ex,body);
-    ex->values.args = name->args ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*  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 ;
 
-    if (fatalError) {
-  werror(E_FUNC_NO_CODE,name->name);
-  goto skipall ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*  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 ;
 
-    /* create the node & generate intermediate code */
-    codeOutFile = code->oFile;
-    piCode = iCodeFromAst(ex);
 
-     if (fatalError) {
-   werror(E_FUNC_NO_CODE,name->name);
-   goto skipall ;
-     }
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*    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 ;
 
-     eBBlockFromiCode(piCode);
+  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 ;
 
-    /* if there are any statics then do them */
-    if (staticAutos) {
-  codeOutFile = statsg->oFile;
-  eBBlockFromiCode (iCodeFromAst (decorateType(resolveSymbols(staticAutos))));
-  staticAutos = NULL;
-    }
+  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 ;
 
- skipall:
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*     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 ;
 
-    /* dealloc the block variables */
-    processBlockVars(body, &stack,DEALLOCATE);
-    /* deallocate paramaters */
-    deallocParms(name->args);
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /* 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 ;
 
-    if (IS_RENT(fetype))
-  reentrant-- ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*    assignment operators    */
+    /*----------------------------*/
+  case MUL_ASSIGN:
+    fprintf(outfile,"MULASS(*=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case DIV_ASSIGN:
+    fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case AND_ASSIGN:
+    fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case OR_ASSIGN:
+    fprintf(outfile,"ORASS(|=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case XOR_ASSIGN:
+    fprintf(outfile,"XORASS(^=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case RIGHT_ASSIGN:
+    fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case LEFT_ASSIGN:
+    fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*    -= operator             */
+    /*----------------------------*/
+  case SUB_ASSIGN:
+    fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*          += operator       */
+    /*----------------------------*/
+  case ADD_ASSIGN:
+    fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*      straight assignemnt   */
+    /*----------------------------*/
+  case '=':
+    fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*      comma operator        */
+    /*----------------------------*/
+  case ',':
+    fprintf(outfile,"COMMA(,) (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*       function call        */
+    /*----------------------------*/
+  case CALL:
+  case PCALL:
+    fprintf(outfile,"CALL (%p) type (",tree);
+    printTypeChain(tree->ftype,outfile);
+    fprintf(outfile,")\n");
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent+2);
+    return;
+  case PARAM:
+    fprintf(outfile,"PARMS\n");
+    ast_print(tree->left,outfile,indent+2);
+    if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
+      ast_print(tree->right,outfile,indent+2);
+    }
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*     return statement       */
+    /*----------------------------*/
+  case RETURN:
+    fprintf(outfile,"RETURN (%p) type (",tree);
+    if (tree->right) {
+      printTypeChain(tree->right->ftype,outfile);
+    }
+    fprintf(outfile,")\n");
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*     label statement        */
+    /*----------------------------*/
+  case LABEL :
+    fprintf(outfile,"LABEL (%p)\n",tree);
+    ast_print(tree->left,outfile,indent+2);
+    ast_print(tree->right,outfile,indent);
+    return;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /*     switch statement       */
+    /*----------------------------*/
+  case SWITCH:
+    {
+      value *val;
+      fprintf(outfile,"SWITCH (%p) ",tree);
+      ast_print(tree->left,outfile,0);
+      for (val = tree->values.switchVals.swVals; val ; val = val->next) {
+        INDENT(indent+2,outfile);
+        fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
+          (int) ulFromVal(val),
+          tree->values.switchVals.swNum,
+          (int) ulFromVal(val));
+      }
+      ast_print(tree->right,outfile,indent);
+    }
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /* ifx Statement              */
+    /*----------------------------*/
+  case IFX:
+    fprintf(outfile,"IF (%p) \n",tree);
+    ast_print(tree->left,outfile,indent+2);
+    if (tree->trueLabel) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
+    }
+    if (tree->falseLabel) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
+    }
+    ast_print(tree->right,outfile,indent+2);
+    return ;
+    /*----------------------------*/
+    /* goto Statement              */
+    /*----------------------------*/
+  case GOTO:
+    fprintf(outfile,"GOTO (%p) \n",tree);
+    ast_print(tree->left,outfile,indent+2);
+    fprintf(outfile,"\n");
+    return ;
+    /*------------------------------------------------------------------*/
+    /*----------------------------*/
+    /* for Statement              */
+    /*----------------------------*/
+  case FOR:
+    fprintf(outfile,"FOR (%p) \n",tree);
+    if (AST_FOR( tree, initExpr)) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"INIT EXPR ");
+      ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
+    }
+    if (AST_FOR( tree, condExpr)) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"COND EXPR ");
+      ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
+    }
+    if (AST_FOR( tree, loopExpr)) {
+      INDENT(indent+2,outfile);
+      fprintf(outfile,"LOOP EXPR ");
+      ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
+    }
+    fprintf(outfile,"FOR LOOP BODY \n");
+    ast_print(tree->left,outfile,indent+2);
+    return ;
+  case CRITICAL:
+    fprintf(outfile,"CRITICAL (%p) \n",tree);
+    ast_print(tree->left,outfile,indent+2);
+  default:
+    return ;
+  }
+}
 
-    /* we are done freeup memory & cleanup */
-    noLineno-- ;
-    labelKey = 1 ;
-    name->key = 0;
-    name->fbody = 1;
-    addSet(&operKeyReset,name);
-    applyToSet(operKeyReset,resetParmKey);
+void PA(ast *t)
+{
+  ast_print(t,stdout,0);
+}
 
-    if (options.debug && !options.nodebug)
-  cdbStructBlock(1,cdbFile);
+/*-----------------------------------------------------------------*/
+/* astErrors : returns non-zero if errors present in tree          */
+/*-----------------------------------------------------------------*/
+int astErrors(ast *t)
+{
+  int errors=0;
 
-    cleanUpLevel(LabelTab,0);
-    cleanUpBlock(StructTab,1);
-    cleanUpBlock(TypedefTab,1);
+  if (t)
+    {
+      if (t->isError)
+        errors++;
 
-    xstack->syms = NULL;
-    istack->syms = NULL;
-    return NULL ;
-}
+      if (t->type == EX_VALUE
+          && t->opval.val->sym
+          && t->opval.val->sym->undefined)
+        errors++;
 
+      errors += astErrors(t->left);
+      errors += astErrors(t->right);
+    }
 
+  return errors;
+}