* sim/ucsim/configure.in,
[fw/sdcc] / src / SDCCval.c
index daf3f930f4c6497b6ea7bbbde5a9056370864bc7..b2f8fe0e1b0cf4db8434243e7c9913409bb91067 100644 (file)
 /*----------------------------------------------------------------------
 /*----------------------------------------------------------------------
-    SDCCval.c :- has routine to do all kinds of fun stuff with the 
+    SDCCval.c :- has routine to do all kinds of fun stuff with the
                 value wrapper & with initialiser lists.
                 value wrapper & with initialiser lists.
-    
+
     Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
 
     This program is free software; you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation; either version 2, or (at your option) any
     later version.
     Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
 
     This program is free software; you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation; either version 2, or (at your option) any
     later version.
-    
+
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-    
+
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-    
+
     In other words, you are welcome to use, share and improve this program.
     You are forbidden to forbid anyone else to use, share and improve
     In other words, you are welcome to use, share and improve this program.
     You are forbidden to forbid anyone else to use, share and improve
-    what you give them.   Help stamp out software-hoarding!  
+    what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
 #include "common.h"
 #include <math.h>
 #include <stdlib.h>
 #include <limits.h>
 -------------------------------------------------------------------------*/
 
 #include "common.h"
 #include <math.h>
 #include <stdlib.h>
 #include <limits.h>
+#include "newalloc.h"
 
 
-int            cNestLevel ;
+int cNestLevel;
 
 /*-----------------------------------------------------------------*/
 
 /*-----------------------------------------------------------------*/
-/* newValue - allocates and returns a new value                   */
+/* newValue - allocates and returns a new value        */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-value *newValue ()
+value *
+newValue ()
 {
 {
-    value *val ;
-    
-    ALLOC(val,sizeof(value));
-    
-    return val ;
+  value *val;
+
+  val = Safe_alloc (sizeof (value));
+
+  return val;
 }
 
 /*-----------------------------------------------------------------*/
 /* newiList - new initializer list                                 */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* newiList - new initializer list                                 */
 /*-----------------------------------------------------------------*/
-initList *newiList ( int type, void *ilist)
+initList *
+newiList (int type, void *ilist)
+{
+  initList *nilist;
+
+
+  nilist = Safe_alloc (sizeof (initList));
+
+  nilist->type = type;
+  nilist->lineno = mylineno;
+  nilist->filename = currFname;
+
+  switch (type)
+    {
+    case INIT_NODE:
+      nilist->init.node = (struct ast *) ilist;
+      break;
+
+    case INIT_DEEP:
+      nilist->init.deep = (struct initList *) ilist;
+      break;
+    }
+
+  return nilist;
+}
+
+/*------------------------------------------------------------------*/
+/* revinit   - reverses the initial values for a value  chain        */
+/*------------------------------------------------------------------*/
+initList *
+revinit (initList * val)
+{
+  initList *prev, *curr, *next;
+
+  if (!val)
+    return NULL;
+
+  prev = val;
+  curr = val->next;
+
+  while (curr)
+    {
+      next = curr->next;
+      curr->next = prev;
+      prev = curr;
+      curr = next;
+    }
+  val->next = (void *) NULL;
+  return prev;
+}
+
+bool
+convertIListToConstList(initList *src, literalList **lList)
 {
 {
-    initList *nilist;
+    initList    *iLoop;
+    literalList *head, *last, *newL;
     
     
+    head = last = NULL;
     
     
-    ALLOC(nilist,sizeof(initList));    
+    if (!src || src->type != INIT_DEEP)
+    {
+       return FALSE;
+    }
     
     
-    nilist->type = type        ;
-    nilist->lineno = yylineno ;
+    iLoop =  src->init.deep;
     
     
-    switch (type)   {
-    case INIT_NODE :
-       nilist->init.node = (struct ast *) ilist ;
-       break ;
-       
-    case INIT_DEEP :
-       nilist->init.deep = (struct initList *) ilist ;
-       break ;
+    while (iLoop)
+    {
+       if (iLoop->type != INIT_NODE)
+       {
+           return FALSE;
+       }
+
+       if (!IS_AST_LIT_VALUE(decorateType(resolveSymbols(iLoop->init.node), RESULT_CHECK)))
+       {
+           return FALSE;
+       }
+       iLoop = iLoop->next;
+    }
+
+    // We've now established that the initializer list contains only literal values.
+
+    iLoop = src->init.deep;
+    while (iLoop)
+    {
+       double val = AST_LIT_VALUE(iLoop->init.node);
+
+       if (last && last->literalValue == val)
+       {
+           last->count++;
+       }
+       else
+       {
+           newL = Safe_alloc(sizeof(literalList));
+           newL->literalValue = val;
+           newL->count = 1;
+           newL->next = NULL;
+           
+           if (last)
+           {
+               last->next = newL;
+           }
+           else
+           {
+               head = newL;
+           }
+           last = newL;
+       }
+       iLoop = iLoop->next;
     }
     
     }
     
-    return nilist ;
+    if (!head)    
+    {
+       return FALSE;
+    }
+    
+    *lList = head;
+    return TRUE;
 }
 
 }
 
-/*------------------------------------------------------------------*/
-/* revinit   - reverses the initial values for a value  chain       */
-/*------------------------------------------------------------------*/
-initList *revinit   ( initList   *val)
+literalList *
+copyLiteralList(literalList *src)
 {
 {
-    initList  *prev  , *curr, *next ;
+    literalList *head, *prev, *newL;
     
     
-    if (!val)
-       return NULL ;
+    head = prev = NULL;
     
     
-    prev = val ;
-    curr = val->next ;
+    while (src)
+    {
+       newL = Safe_alloc(sizeof(literalList));
+       
+       newL->literalValue = src->literalValue;
+       newL->count = src->count;
+       newL->next = NULL;
+       
+       if (prev)
+       {
+           prev->next = newL;
+       }
+       else
+       {
+           head = newL;
+       }
+       prev = newL;
+       src = src->next;
+    }
     
     
-    while (curr)   {
-       next = curr->next ;
-       curr->next = prev   ;
-       prev = curr ;
-       curr = next ;
-    }
-    val->next = (void *) NULL ;
-    return prev ;
+    return head;
 }
 
 }
 
+
+
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
-/* copyIlist - copy initializer list                               */
+/* copyIlist - copy initializer list            */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
-initList *copyIlist (initList *src)
+initList *
+copyIlist (initList * src)
 {
 {
-    initList *dest = NULL;
-    
-    if (!src)
-       return NULL ;
-    
-    switch (src->type) {
-    case INIT_DEEP :
-       dest = newiList (INIT_DEEP,copyIlist (src->init.deep));
-       break;
-    case INIT_NODE :
-       dest = newiList (INIT_NODE,copyAst (src->init.node)) ;
-       break;
+  initList *dest = NULL;
+
+  if (!src)
+    return NULL;
+
+  switch (src->type)
+    {
+    case INIT_DEEP:
+      dest = newiList (INIT_DEEP, copyIlist (src->init.deep));
+      break;
+    case INIT_NODE:
+      dest = newiList (INIT_NODE, copyAst (src->init.node));
+      break;
     }
     }
-    
-    if ( src->next )
-       dest->next = copyIlist(src->next);
-    
-    return dest ;
+
+  if (src->next)
+    dest->next = copyIlist (src->next);
+
+  return dest;
 }
 
 /*------------------------------------------------------------------*/
 /* list2int - converts the first element of the list to value       */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* list2int - converts the first element of the list to value       */
 /*------------------------------------------------------------------*/
-double list2int (initList   *val)
+double
+list2int (initList * val)
 {
 {
-    initList *i = val;
-    
-    if ( i->type == INIT_DEEP )
-       return list2int (val->init.deep) ;
-    
-    return floatFromVal(constExprValue(val->init.node,TRUE));
+  initList *i = val;
+
+  if (i->type == INIT_DEEP)
+    return list2int (val->init.deep);
+
+  return floatFromVal (constExprValue (val->init.node, TRUE));
 }
 
 /*------------------------------------------------------------------*/
 /* list2val - converts the first element of the list to value       */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* list2val - converts the first element of the list to value       */
 /*------------------------------------------------------------------*/
-value *list2val (initList   *val)
+value *
+list2val (initList * val)
 {
 {
-    if (!val)
-       return NULL;
+  if (!val)
+    return NULL;
 
 
-    if ( val->type == INIT_DEEP )
-       return list2val (val->init.deep) ;
-    
-    return constExprValue(val->init.node,TRUE);
+  if (val->type == INIT_DEEP)
+    return list2val (val->init.deep);
+
+  return constExprValue (val->init.node, TRUE);
 }
 
 /*------------------------------------------------------------------*/
 /* list2expr - returns the first expression in the initializer list */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* list2expr - returns the first expression in the initializer list */
 /*------------------------------------------------------------------*/
-ast    *list2expr ( initList   *ilist)
+ast *
+list2expr (initList * ilist)
 {
 {
-    if ( ilist->type == INIT_DEEP )
-       return list2expr (ilist->init.deep) ;
-    return ilist->init.node ;
+  if (ilist->type == INIT_DEEP)
+    return list2expr (ilist->init.deep);
+  return ilist->init.node;
 }
 
 /*------------------------------------------------------------------*/
 /* resolveIvalSym - resolve symbols in initial values               */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* resolveIvalSym - resolve symbols in initial values               */
 /*------------------------------------------------------------------*/
-void resolveIvalSym ( initList *ilist)
+void
+resolveIvalSym (initList * ilist, sym_link * type)
 {
 {
-    if ( ! ilist )
-       return ;
-    
-    if ( ilist->type == INIT_NODE )
-       ilist->init.node = decorateType(resolveSymbols (ilist->init.node));
-    
-    if ( ilist->type == INIT_DEEP )
-       resolveIvalSym (ilist->init.deep);
-    
-    resolveIvalSym (ilist->next);
+  RESULT_TYPE resultType;
+
+  if (!ilist)
+    return;
+
+  if (ilist->type == INIT_NODE)
+    {
+      if (IS_PTR (type))
+        resultType = RESULT_TYPE_INT;
+      else
+        resultType = getResultTypeFromType (getSpec (type));
+      ilist->init.node = decorateType (resolveSymbols (ilist->init.node),
+                                      resultType);
+    }
+
+  if (ilist->type == INIT_DEEP)
+    resolveIvalSym (ilist->init.deep, type);
+
+  resolveIvalSym (ilist->next, type);
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
-/* symbolVal - creates a value for a symbol                       */
+/* symbolVal - creates a value for a symbol              */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-value *symbolVal ( symbol  *sym )
+value *
+symbolVal (symbol * sym)
 {
 {
-    value *val ;
-    
-    if (!sym)
-       return NULL ;
-    
-    val = newValue();
-    val->sym = sym ;
-    
-    if ( sym->type ) {
-       val->type = sym->type;
-       val->etype= getSpec(val->type);
+  value *val;
+
+  if (!sym)
+    return NULL;
+
+  val = newValue ();
+  val->sym = sym;
+
+  if (sym->type)
+    {
+      val->type = sym->type;
+      val->etype = getSpec (val->type);
     }
     }
-    
-    if ( *sym->rname )
-       sprintf (val->name,"%s",sym->rname);
-    else
-       sprintf(val->name,"_%s",sym->name);
-    
-    
-    return val ;
+
+  if (*sym->rname)
+    {
+       SNPRINTF (val->name, sizeof(val->name), "%s", sym->rname);
+    }
+  else
+    {
+       SNPRINTF (val->name, sizeof(val->name), "_%s", sym->name);
+    }
+
+  return val;
 }
 
 }
 
+#if defined(REDUCE_LITERALS)
+/*--------------------------------------------------------------------*/
+/* cheapestVal - convert a val to the cheapest as possible value      */
+/*--------------------------------------------------------------------*/
+static value *cheapestVal (value *val) {
+  TYPE_DWORD  sval=0;
+  TYPE_UDWORD uval=0;
+
+  if (IS_FLOAT(val->type) || IS_CHAR(val->type))
+    return val;
+
+  if (SPEC_LONG(val->type)) {
+    if (SPEC_USIGN(val->type)) {
+      uval=SPEC_CVAL(val->type).v_ulong;
+    } else {
+      sval=SPEC_CVAL(val->type).v_long;
+    }
+  } else {
+    if (SPEC_USIGN(val->type)) {
+      uval=SPEC_CVAL(val->type).v_uint;
+    } else {
+      sval=SPEC_CVAL(val->type).v_int;
+    }
+  }
+
+  if (SPEC_USIGN(val->type)) {
+    if (uval<=0xffff) {
+      SPEC_LONG(val->type)=0;
+      SPEC_CVAL(val->type).v_uint = (TYPE_UWORD)uval;
+      if (uval<=0xff) {
+       SPEC_NOUN(val->type)=V_CHAR;
+      }
+    }
+  } else { // not unsigned
+    if (sval<0) {
+      if (sval>=-32768) {
+       SPEC_LONG(val->type)=0;
+       SPEC_CVAL(val->type).v_int = (TYPE_WORD)sval;
+       if (sval>=-128) {
+         SPEC_NOUN(val->type)=V_CHAR;
+       }
+      }
+    } else { // sval>=0
+      if (sval<=32767) {
+       SPEC_LONG(val->type)=0;
+       SPEC_CVAL(val->type).v_int = (TYPE_WORD)sval;
+       if (sval<=127) {
+         SPEC_NOUN(val->type)=V_CHAR;
+       }
+      }
+    }
+  }
+  return val;
+}
+
+#else
+
+static value *cheapestVal (value *val)
+{
+  if (IS_FLOAT (val->type) || IS_CHAR (val->type))
+    return val;
+
+  /* - signed/unsigned must not be changed.
+     - long must not be changed.
+
+     the only possible reduction is from signed int to signed char,
+     because it's automatically promoted back to signed int.
+
+     a reduction from unsigned int to unsigned char is a bug,
+     because an _unsigned_ char is promoted to _signed_ int! */
+  if (IS_INT(val->type) &&
+      !SPEC_USIGN(val->type) &&
+      !SPEC_LONG(val->type) &&
+      SPEC_CVAL(val->type).v_int >= -128 &&
+      SPEC_CVAL(val->type).v_int <     0)
+
+    {
+      SPEC_NOUN(val->type) = V_CHAR;
+    }
+  /* 'unsigned char' promotes to 'signed int', so that we can
+     reduce it the other way */
+  if (IS_INT(val->type) &&
+      !SPEC_USIGN(val->type) &&
+      !SPEC_LONG(val->type) &&
+      SPEC_CVAL(val->type).v_int >=   0 &&
+      SPEC_CVAL(val->type).v_int <= 255)
+
+    {
+      SPEC_NOUN(val->type) = V_CHAR;
+      SPEC_USIGN(val->type) = 1;
+    }
+  return (val);
+}
+#endif
+
 /*-----------------------------------------------------------------*/
 /* valueFromLit - creates a value from a literal                   */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* valueFromLit - creates a value from a literal                   */
 /*-----------------------------------------------------------------*/
-value *valueFromLit (float lit)
+value *
+valueFromLit (double lit)
 {
 {
-    char buffer[50];
-    
-    if ( ( ((long) lit ) - lit ) == 0 ) {      
-       sprintf(buffer,"%ld",(long) lit);
-       return constVal (buffer);
+  char buffer[50];
+
+  if ((((TYPE_DWORD) lit) - lit) == 0)
+    {
+      SNPRINTF (buffer, sizeof(buffer), "%d", (TYPE_DWORD) lit);
+      return constVal (buffer);
     }
     }
-    
-    sprintf(buffer,"%f",lit);
-    return constFloatVal (buffer);
+
+  SNPRINTF (buffer, sizeof(buffer), "%f", lit);
+  return constFloatVal (buffer);
 }
 
 /*-----------------------------------------------------------------*/
 /* constFloatVal - converts a FLOAT constant to value              */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* constFloatVal - converts a FLOAT constant to value              */
 /*-----------------------------------------------------------------*/
-value *constFloatVal ( char *s )
+value *
+constFloatVal (char *s)
 {
 {
-    value *val = newValue();
-    float sval;
-    
-    if(sscanf (s,"%f",&sval) != 1) {
-       werror(E_INVALID_FLOAT_CONST,s);
-       return constVal("0");
+  value *val = newValue ();
+  double sval;
+
+  if (sscanf (s, "%lf", &sval) != 1)
+    {
+      werror (E_INVALID_FLOAT_CONST, s);
+      return constVal ("0");
     }
     }
-    
-    val->type = val->etype = newLink();
-    val->type->class = SPECIFIER ;
-    SPEC_NOUN(val->type) = V_FLOAT ;
-    SPEC_SCLS(val->type) = S_LITERAL;
-    SPEC_CVAL(val->type).v_float = sval;
-    
-    return val;
+
+  val->type = val->etype = newLink (SPECIFIER);
+  SPEC_NOUN (val->type) = V_FLOAT;
+  SPEC_SCLS (val->type) = S_LITERAL;
+  SPEC_CVAL (val->type).v_float = sval;
+
+  return val;
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
-/* constVal - converts a INTEGER constant into a value            */
+/* constVal - converts an INTEGER constant into a cheapest value   */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-value *constVal   (char *s)
+value *constVal (char *s)
 {
 {
-    value *val ;
-    short hex = 0 , octal = 0 ;
-    char  scanFmt[10] ;
-    int         scI = 0 ;
-    unsigned long sval ;
-    
-    val = newValue() ;       /* alloc space for value   */
-    
-    val->type = val->etype = newLink() ; /* create the spcifier */
-    val->type->class   = SPECIFIER ;
-    SPEC_NOUN(val->type) =  V_INT ;
-    SPEC_SCLS(val->type) =  S_LITERAL ;
-    
-    /* set the _unsigned flag if 'uU' found */
-    if (strchr(s,'u') || strchr(s,'U'))
-       SPEC_USIGN(val->type) = 1;
-    
-    /* set the _long flag if 'lL' is found */
-    if (strchr(s,'l') || strchr(s,'L'))
-       SPEC_LONG(val->type) = 1;
-    
-    hex = ((strchr(s,'x') || strchr(s,'X')) ? 1 : 0) ;
-    
-    /* set the octal flag   */
-    if (!hex && *s == '0' && *(s+1) )
-       octal = 1 ;
-    
-    /* create the scan string */
-    scanFmt[scI++] = '%' ;
-    
-    if (octal)
-       scanFmt[scI++] = 'o' ;
-    else
-       if (hex)
-           scanFmt[scI++] = 'x' ;
-       else
-           if (SPEC_USIGN(val->type))
-               scanFmt[scI++] = 'u' ;
-           else
-               scanFmt[scI++] = 'd' ;
-    
-    scanFmt[scI++] = '\0' ;
-    
-    /* if hex or octal then set the unsigned flag   */
-    if ( hex || octal ) {
-       SPEC_USIGN(val->type) = 1 ;
-       sscanf(s,scanFmt,&sval);
-    } else
-       sval = atol(s);
-    
-    
-    if (SPEC_LONG(val->type) || sval > 32768) {
-       if (SPEC_USIGN(val->type))
-           SPEC_CVAL(val->type).v_ulong = sval ;
-       else
-           SPEC_CVAL(val->type).v_long = sval ;
-       SPEC_LONG(val->type) = 1;
+  value *val;
+  short hex = 0, octal = 0;
+  char scanFmt[10];
+  int scI = 0;
+  double dval;
+
+  val = newValue ();           /* alloc space for value   */
+
+  val->type = val->etype = newLink (SPECIFIER);        /* create the spcifier */
+  SPEC_SCLS (val->type) = S_LITERAL;
+  // let's start with a signed char
+  SPEC_NOUN (val->type) = V_CHAR;
+  SPEC_USIGN (val->type) = 0;
+
+  hex = ((strchr (s, 'x') || strchr (s, 'X')) ? 1 : 0);
+
+  /* set the octal flag   */
+  if (!hex && *s == '0' && *(s + 1))
+    octal = 1;
+
+  /* create the scan string */
+  scanFmt[scI++] = '%';
+
+  scanFmt[scI++] = 'l';
+
+  if (octal)
+    scanFmt[scI++] = 'o';
+  else if (hex)
+    scanFmt[scI++] = 'x';
+  else
+    scanFmt[scI++] = 'f';
+
+  scanFmt[scI++] = '\0';
+
+  if (octal || hex) {
+    unsigned long sval;
+    sscanf (s, scanFmt, &sval);
+    dval=sval;
+  } else {
+    sscanf (s, scanFmt, &dval);
+  }
+
+  /* Setup the flags first */
+  /* set the _long flag if 'lL' is found */
+  if (strchr (s, 'l') || strchr (s, 'L')) {
+    SPEC_NOUN (val->type) = V_INT;
+    SPEC_LONG (val->type) = 1;
+  }
+
+  /* set the unsigned flag if 'uU' is found */
+  if (strchr (s, 'u') || strchr (s, 'U')) {
+    SPEC_USIGN (val->type) = 1;
+  }
+
+  if (dval<0) { // "-28u" will still be signed and negative
+    if (dval<-128) { // check if we have to promote to int
+      SPEC_NOUN (val->type) = V_INT;
     }
     }
-    else {
-       if (SPEC_USIGN(val->type))
-           SPEC_CVAL(val->type).v_uint = sval ;
-       else
-           SPEC_CVAL(val->type).v_int = sval ;
+    if (dval<-32768) { // check if we have to promote to long int
+      SPEC_LONG (val->type) = 1;
+    }
+  } else { // >=0
+    if (dval>0xff ||   /* check if we have to promote to int */
+        SPEC_USIGN (val->type)) { /* if it's unsigned, we can't use unsigned
+                                    char. After an integral promotion it will
+                                    be a signed int; this certainly isn't what
+                                    the programer wants */
+      SPEC_NOUN (val->type) = V_INT;
+    }
+    else { /* store char's always as unsigned; this helps other optimizations */
+      SPEC_USIGN (val->type) = 1;
+    }
+    if (dval>0xffff && SPEC_USIGN (val->type)) { // check if we have to promote to long
+      SPEC_LONG (val->type) = 1;
+    }
+    else if (dval>0x7fff && !SPEC_USIGN (val->type)) { // check if we have to promote to long int
+      if ((hex || octal) && /* hex or octal constants may be stored in unsigned type */
+          dval<=0xffff) {
+        SPEC_USIGN (val->type) = 1;
+      } else {
+        SPEC_LONG (val->type) = 1;
+        if (dval>0x7fffffff) {
+          SPEC_USIGN (val->type) = 1;
+       }
+      }
+    }
+  }
+
+  if (SPEC_LONG (val->type))
+    {
+      if (SPEC_USIGN (val->type))
+        {
+          SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD)dval;
+        }
+      else
+        {
+          SPEC_CVAL (val->type).v_long = (TYPE_DWORD)dval;
+        }
+    }
+  else
+    {
+      if (SPEC_USIGN (val->type))
+        {
+          SPEC_CVAL (val->type).v_uint = (TYPE_UWORD)dval;
+        }
+      else
+        {
+          SPEC_CVAL (val->type).v_int = (TYPE_WORD)dval;
+        }
     }
 
     }
 
-    // check the size and make it a short if required
-    if (sval < 256 )
-       SPEC_SHORT(val->etype) = 1;                     
-    
-    return val ;
-    
+  return val;
+}
+
+/*! /fn char hexEscape(char **src)
+
+    /param src Pointer to 'x' from start of hex character value
+*/
+
+unsigned char hexEscape(char **src)
+{
+  char *s ;
+  unsigned long value ;
+
+  (*src)++ ;   /* Skip over the 'x' */
+  s = *src ;   /* Save for error detection */
+  
+  value = strtol (*src, src, 16);
+  
+  if (s == *src) {
+      // no valid hex found
+      werror(E_INVALID_HEX);
+  } else {
+    if (value > 255) {
+      werror(W_ESC_SEQ_OOR_FOR_CHAR);
+    }
+  }
+  return (char) value;
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
-/* copyStr - copies src to dest ignoring leading & trailing \"s     */
+/* octalEscape - process an octal constant of max three digits      */
+/* return the octal value, throw a warning for illegal octal        */
+/* adjust src to point at the last proccesed char                   */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
-void   copyStr (char *dest, char *src )
+
+unsigned char octalEscape (char **str) {
+  int digits;
+  unsigned value=0;
+
+  for (digits=0; digits<3; digits++) {
+    if (**str>='0' && **str<='7') {
+      value = value*8 + (**str-'0');
+      (*str)++;
+    } else {
+      break;
+    }
+  }
+  if (digits) {
+    if (value > 255 /* || (**str>='0' && **str<='7') */ ) {
+      werror (W_ESC_SEQ_OOR_FOR_CHAR);
+    }
+  }
+  return value;
+}
+
+/*! 
+  /fn int copyStr (char *dest, char *src)
+  
+  Copies a source string to a dest buffer interpreting escape sequences
+  and special characters
+
+  /param dest Buffer to receive the resultant string
+  /param src  Buffer containing the source string with escape sequecnes
+  /return Number of characters in output string
+
+*/
+
+int 
+copyStr (char *dest, char *src)
+
 {
 {
-    unsigned int x;
-    while (*src) {
-       if (*src == '\"' ) 
-           src++ ;
-       else
-           if ( *src == '\\' ) {
-               src++ ;
-               switch (*src) {
-               case 'n'        :
-                   *dest++ = '\n';
-                   break ;
-               case 't'        :
-                   *dest++ = '\t';
-                   break;
-               case 'v'        :
-                   *dest++ = '\v';
-                   break;
-               case 'b'        :
-                   *dest++ = '\b';
-                   break;
-               case 'r'        :
-                   *dest++ = '\r';
-                   break;
-               case 'f'        :
-                   *dest++ = '\f';
-                   break;
-               case 'a' :
-                   *dest++ = '\a';
-                   break;
-               case '0':
-                   /* embedded octal or hex constant */
-                   if (*(src+1) == 'x' ||
-                       *(src+1) == 'X') {
-                       x = strtol(src,&src,16);
-                       *dest++ = x;
-                   } else {
-                       /* must be octal */
-                       x = strtol(src,&src,8);
-                       *dest++ = x;
-                   }
-                   break;
-                       
-               case '\\':
-                   *dest++ = '\\';
-                   break;
-               case '\?':
-                   *dest++ = '\?';
-                   break;
-               case '\'':
-                   *dest++ = '\'';
-                   break;
-               case '\"':
-                   *dest++ = '\"';
-                   break;                  
-               default :
-                   *dest++ = *src ;
-               }
-               src++ ;
+  char *OriginalDest = dest ;
+
+  while (*src)
+    {
+      if (*src == '\"')
+       src++;
+      else if (*src == '\\')
+       {
+         src++;
+         switch (*src)
+           {
+           case 'n':
+             *dest++ = '\n';
+             break;
+           case 't':
+             *dest++ = '\t';
+             break;
+           case 'v':
+             *dest++ = '\v';
+             break;
+           case 'b':
+             *dest++ = '\b';
+             break;
+           case 'r':
+             *dest++ = '\r';
+             break;
+           case 'f':
+             *dest++ = '\f';
+             break;
+           case 'a':
+             *dest++ = '\a';
+             break;
+
+           case '0':
+           case '1':
+           case '2':
+           case '3':
+           case '4':
+           case '5':
+           case '6':
+           case '7':
+             *dest++ = octalEscape(&src);
+             src-- ;
+             break;
+
+           case 'x': 
+             *dest++ = hexEscape(&src) ;
+             src-- ;
+             break ;
+
+           case '\\':
+             *dest++ = '\\';
+             break;
+           case '\?':
+             *dest++ = '\?';
+             break;
+           case '\'':
+             *dest++ = '\'';
+             break;
+           case '\"':
+             *dest++ = '\"';
+             break;
+           default:
+             *dest++ = *src;
            }
            }
-           else
-               *dest++ = *src++ ;
+         src++;
+       }
+      else
+       *dest++ = *src++;
     }
     }
-    
-    *dest = '\0' ;
+
+  *dest++ = '\0';
+
+  return dest - OriginalDest ;
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
-/* strVal - converts a string constant to a value                  */
+/* strVal - converts a string constant to a value       */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
-value *strVal  ( char  *s )
+value *
+strVal (char *s)
 {
 {
-    value *val ;
-    
-    val = newValue() ;       /* get a new one */
-    
-    /* get a declarator        */
-    val->type   =  newLink();
-    DCL_TYPE(val->type) = ARRAY ;
-    DCL_ELEM(val->type) = strlen(s) - 1;
-    val->type->next = val->etype = newLink() ;
-    val->etype->class      =  SPECIFIER;
-    SPEC_NOUN(val->etype)   =  V_CHAR   ;
-    SPEC_SCLS(val->etype)   =  S_LITERAL;
-    
-    ALLOC_ATOMIC(SPEC_CVAL(val->etype).v_char,strlen(s)+1);
-    copyStr (SPEC_CVAL(val->etype).v_char,s);
-    return val;
+  value *val;
+
+  val = newValue ();           /* get a new one */
+
+  /* get a declarator */
+  val->type = newLink (DECLARATOR);
+  DCL_TYPE (val->type) = ARRAY;
+  val->type->next = val->etype = newLink (SPECIFIER);
+  SPEC_NOUN (val->etype) = V_CHAR;
+  SPEC_SCLS (val->etype) = S_LITERAL;
+
+  SPEC_CVAL (val->etype).v_char = Safe_alloc (strlen (s) + 1);
+  DCL_ELEM (val->type) = copyStr (SPEC_CVAL (val->etype).v_char, s);
+
+  return val;
 }
 
 
 /*------------------------------------------------------------------*/
 /* reverseValWithType - reverses value chain with type & etype      */
 /*------------------------------------------------------------------*/
 }
 
 
 /*------------------------------------------------------------------*/
 /* reverseValWithType - reverses value chain with type & etype      */
 /*------------------------------------------------------------------*/
-value  *reverseValWithType ( value *val )
+value *
+reverseValWithType (value * val)
 {
 {
-    link *type ;
-    link *etype;
-    
-    if (!val) 
-       return NULL ;
-    
-    /* save the type * etype chains */
-    type = val->type ;
-    etype = val->etype ;
-    
-    /* set the current one 2b null */
-    val->type = val->etype = NULL;
-    val = reverseVal (val);
-    
-    /* restore type & etype */
-    val->type = type ;
-    val->etype = etype ;
-    
-    return val;
+  sym_link *type;
+  sym_link *etype;
+
+  if (!val)
+    return NULL;
+
+  /* save the type * etype chains */
+  type = val->type;
+  etype = val->etype;
+
+  /* set the current one 2b null */
+  val->type = val->etype = NULL;
+  val = reverseVal (val);
+
+  /* restore type & etype */
+  val->type = type;
+  val->etype = etype;
+
+  return val;
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
-/* reverseVal - reverses the values for a value  chain                     */
+/* reverseVal - reverses the values for a value  chain        */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
-value   *reverseVal   ( value  *val)
+value *
+reverseVal (value * val)
 {
 {
-    value  *prev  , *curr, *next ;
-    
-    if (!val)
-       return NULL ;
-    
-    prev = val ;
-    curr = val->next ;
-    
-    while (curr) {
-       next = curr->next ;
-       curr->next = prev   ;
-       prev = curr ;
-       curr = next ;
-    }
-    val->next = (void *) NULL ;
-    return prev ;
+  value *prev, *curr, *next;
+
+  if (!val)
+    return NULL;
+
+  prev = val;
+  curr = val->next;
+
+  while (curr)
+    {
+      next = curr->next;
+      curr->next = prev;
+      prev = curr;
+      curr = next;
+    }
+  val->next = (void *) NULL;
+  return prev;
 }
 
 /*------------------------------------------------------------------*/
 /* copyValueChain - will copy a chain of values                     */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* copyValueChain - will copy a chain of values                     */
 /*------------------------------------------------------------------*/
-value *copyValueChain ( value *src )
+value *
+copyValueChain (value * src)
 {
 {
-    value *dest ;
-    
-    if ( ! src )
-       return NULL ;
-    
-    dest = copyValue (src);
-    dest->next = copyValueChain (src->next);
-    
-    return dest ;
+  value *dest;
+
+  if (!src)
+    return NULL;
+
+  dest = copyValue (src);
+  dest->next = copyValueChain (src->next);
+
+  return dest;
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
-/* copyValue - copies contents of a vlue to a fresh one             */
+/* copyValue - copies contents of a value to a fresh one            */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
-value *copyValue  (value   *src)
+value *
+copyValue (value * src)
 {
 {
-    value *dest ;
-    
-    dest = newValue();
-    dest->sym    = copySymbol(src->sym);
-    strcpy(dest->name,src->name);
-    dest->type   = (src->type ? copyLinkChain(src->type) : NULL) ;
-    dest->etype  = (src->type ? getSpec(dest->type) : NULL);
-    
-    return dest ;
+  value *dest;
+
+  dest = newValue ();
+  dest->sym = copySymbol (src->sym);
+  strncpyz (dest->name, src->name, SDCC_NAME_MAX);
+  dest->type = (src->type ? copyLinkChain (src->type) : NULL);
+  dest->etype = (src->type ? getSpec (dest->type) : NULL);
+
+  return dest;
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
-/* charVal - converts a character constant to a value              */
+/* charVal - converts a character constant to a value       */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
-value *charVal ( char *s )
+value *
+charVal (char *s)
 {
 {
-    value *val ;
-    
-    val = newValue ();
-    
-    val->type = val->etype = newLink();
-    val->type->class = SPECIFIER  ;
-    SPEC_NOUN(val->type) = V_CHAR ;
-    SPEC_SCLS(val->type) = S_LITERAL ;
-    
-    s++ ;      /* get rid of quotation */
-    /* if \ then special processing    */
-    if ( *s == '\\' )  {
-       s++ ;   /* go beyond the backslash      */
-       switch (*s)             {
-       case 'n'        :
-           SPEC_CVAL(val->type).v_int = '\n';
-           break ;
-       case 't'        :
-           SPEC_CVAL(val->type).v_int = '\t';
-           break;
-       case 'v'        :
-           SPEC_CVAL(val->type).v_int = '\v';
-           break;
-       case 'b'        :
-           SPEC_CVAL(val->type).v_int = '\b';
-           break;
-       case 'r'        :
-           SPEC_CVAL(val->type).v_int = '\r';
-           break;
-       case 'f'        :
-           SPEC_CVAL(val->type).v_int = '\f';
-           break;
-       case 'a' :
-           SPEC_CVAL(val->type).v_int = '\a';
-           break;
+  value *val;
+
+  val = newValue ();
+
+  val->type = val->etype = newLink (SPECIFIER);
+  SPEC_NOUN (val->type) = V_CHAR;
+  SPEC_USIGN(val->type) = 1;
+  SPEC_SCLS (val->type) = S_LITERAL;
+
+  s++;                         /* get rid of quotation */
+  /* if \ then special processing */
+  if (*s == '\\')
+    {
+      s++;                     /* go beyond the backslash  */
+      switch (*s)
+       {
+       case 'n':
+         SPEC_CVAL (val->type).v_uint = '\n';
+         break;
+       case 't':
+         SPEC_CVAL (val->type).v_uint = '\t';
+         break;
+       case 'v':
+         SPEC_CVAL (val->type).v_uint = '\v';
+         break;
+       case 'b':
+         SPEC_CVAL (val->type).v_uint = '\b';
+         break;
+       case 'r':
+         SPEC_CVAL (val->type).v_uint = '\r';
+         break;
+       case 'f':
+         SPEC_CVAL (val->type).v_uint = '\f';
+         break;
+       case 'a':
+         SPEC_CVAL (val->type).v_uint = '\a';
+         break;
        case '\\':
        case '\\':
-           SPEC_CVAL(val->type).v_int = '\\';
-           break;
+         SPEC_CVAL (val->type).v_uint = '\\';
+         break;
        case '\?':
        case '\?':
-           SPEC_CVAL(val->type).v_int = '\?';
-           break;
+         SPEC_CVAL (val->type).v_uint = '\?';
+         break;
        case '\'':
        case '\'':
-           SPEC_CVAL(val->type).v_int = '\'';
-           break;
+         SPEC_CVAL (val->type).v_uint = '\'';
+         break;
        case '\"':
        case '\"':
-           SPEC_CVAL(val->type).v_int = '\"';
-           break;
-       case '0'        :
-           sscanf(s,"%o",&SPEC_CVAL(val->type).v_int);
-           break;
-       case 'x' :
-           s++ ; /* go behond the 'x' */
-           sscanf(s,"%x",&SPEC_CVAL(val->type).v_int);
-           break;
-       default :
-           SPEC_CVAL(val->type).v_int = *s;
-           break;
+         SPEC_CVAL (val->type).v_uint = '\"';
+         break;
+
+       case '0' :
+       case '1' :
+       case '2' :
+       case '3' :
+       case '4' :
+       case '5' :
+       case '6' :
+       case '7' :
+         SPEC_CVAL (val->type).v_uint = octalEscape(&s);
+         break;
+
+       case 'x':
+         SPEC_CVAL (val->type).v_uint = hexEscape(&s) ;
+         break;
+
+       default:
+         SPEC_CVAL (val->type).v_uint = (unsigned char)*s;
+         break;
        }
     }
        }
     }
-    else       /* not a backslash */
-       SPEC_CVAL(val->type).v_int = *s;
-    
-    return val ;
+  else                         /* not a backslash */
+    SPEC_CVAL (val->type).v_uint = (unsigned char)*s;
+
+  return val;
 }
 
 /*------------------------------------------------------------------*/
 /* valFromType - creates a value from type given                    */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valFromType - creates a value from type given                    */
 /*------------------------------------------------------------------*/
-value *valFromType ( link *type)
+value *
+valFromType (sym_link * type)
 {
 {
-    value *val = newValue();
-    val->type = copyLinkChain(type);
-    val->etype = getSpec(val->type);
-    return val;
+  value *val = newValue ();
+  val->type = copyLinkChain (type);
+  val->etype = getSpec (val->type);
+  return val;
 }
 
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
-/* floatFromVal - value to unsinged integer conversion             */
+/* floatFromVal - value to double float conversion                  */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
-double   floatFromVal ( value *val )
+double
+floatFromVal (value * val)
 {
 {
-    if (!val)
-       return 0;
+  if (!val)
+    return 0;
 
 
-    if (val->etype && SPEC_SCLS(val->etype) != S_LITERAL) {
-       werror(E_CONST_EXPECTED,val->name);
-       return 0;
+  if (val->etype && SPEC_SCLS (val->etype) != S_LITERAL)
+    {
+      werror (E_CONST_EXPECTED, val->name);
+      return 0;
     }
     }
-    
-    /* if it is not a specifier then we can assume that */
-    /* it will be an unsigned long                      */
-    if (!IS_SPEC(val->type))
-       return (double) SPEC_CVAL(val->etype).v_ulong;
-
-    if (SPEC_NOUN(val->etype) == V_FLOAT )
-       return (double) SPEC_CVAL(val->etype).v_float ;
-    else {
-       if (SPEC_LONG(val->etype)) {
-           if (SPEC_USIGN(val->etype))
-               return (double) SPEC_CVAL(val->etype).v_ulong ;
-           else
-               return (double) SPEC_CVAL(val->etype).v_long  ;
-       }
-       else {
-           if (SPEC_USIGN(val->etype))
-               return (double) SPEC_CVAL(val->etype).v_uint ;
-           else
-               return (double) SPEC_CVAL(val->etype).v_int  ;
-       }
+
+  /* if it is not a specifier then we can assume that */
+  /* it will be an unsigned long                      */
+  if (!IS_SPEC (val->type))
+    return (double) SPEC_CVAL (val->etype).v_ulong;
+
+  if (SPEC_NOUN (val->etype) == V_FLOAT)
+    return (double) SPEC_CVAL (val->etype).v_float;
+
+  if (SPEC_LONG (val->etype))
+    {
+      if (SPEC_USIGN (val->etype))
+       return (double) SPEC_CVAL (val->etype).v_ulong;
+      else
+       return (double) SPEC_CVAL (val->etype).v_long;
     }
     }
-}
 
 
+  if (SPEC_NOUN (val->etype) == V_INT) {
+    if (SPEC_USIGN (val->etype))
+      return (double) SPEC_CVAL (val->etype).v_uint;
+    else
+      return (double) SPEC_CVAL (val->etype).v_int;
+  }
+
+  if (SPEC_NOUN (val->etype) == V_CHAR) {
+    if (SPEC_USIGN (val->etype))
+      return (double) (unsigned char)SPEC_CVAL (val->etype).v_uint;
+    else
+      return (double) (signed char)SPEC_CVAL (val->etype).v_int;
+  }
+
+  if (IS_BITVAR(val->etype)) {
+    return (double) SPEC_CVAL (val->etype).v_uint;
+  }
+
+  if (SPEC_NOUN (val->etype) == V_VOID) {
+    return (double) SPEC_CVAL (val->etype).v_ulong;
+  }
+
+  // we are lost !
+  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+         "floatFromVal: unknown value");
+  return 0;
+}
 
 /*------------------------------------------------------------------*/
 
 /*------------------------------------------------------------------*/
-/* valUnaryPM - dones the unary +/- operation on a constant         */
+/* valUnaryPM - does the unary +/- operation on a constant          */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
-value *valUnaryPM (value   *val)
+value *
+valUnaryPM (value * val)
 {
 {
-    /* depending on type */
-    if (SPEC_NOUN(val->etype) == V_FLOAT )
-       SPEC_CVAL(val->etype).v_float = -1.0 * SPEC_CVAL(val->etype).v_float;
-    else {
-       if ( SPEC_LONG(val->etype)) {
-           if (SPEC_USIGN(val->etype))
-               SPEC_CVAL(val->etype).v_ulong = - SPEC_CVAL(val->etype).v_ulong ;
-           else
-               SPEC_CVAL(val->etype).v_long  = - SPEC_CVAL(val->etype).v_long;
+  /* depending on type */
+  if (SPEC_NOUN (val->etype) == V_FLOAT)
+    SPEC_CVAL (val->etype).v_float = -1.0 * SPEC_CVAL (val->etype).v_float;
+  else
+    {
+      if (SPEC_LONG (val->etype))
+       {
+         if (SPEC_USIGN (val->etype))
+           SPEC_CVAL (val->etype).v_ulong = 0-SPEC_CVAL (val->etype).v_ulong;
+         else
+           SPEC_CVAL (val->etype).v_long = -SPEC_CVAL (val->etype).v_long;
        }
        }
-       else {
-           if (SPEC_USIGN(val->etype))
-               SPEC_CVAL(val->etype).v_uint  = -  SPEC_CVAL(val->etype).v_uint ;
-           else
-               SPEC_CVAL(val->etype).v_int   = - SPEC_CVAL(val->etype).v_int ; 
+      else
+       {
+         if (SPEC_USIGN (val->etype))
+           SPEC_CVAL (val->etype).v_uint = 0-SPEC_CVAL (val->etype).v_uint;
+         else
+           SPEC_CVAL (val->etype).v_int = -SPEC_CVAL (val->etype).v_int;
        }
     }
        }
     }
-    return val ;
-    
+  // -(unsigned 3) now really is signed
+  SPEC_USIGN(val->etype)=0;
+  // -(unsigned char)135 now really is an int
+  if (SPEC_NOUN(val->etype) == V_CHAR) {
+    if (SPEC_CVAL(val->etype).v_int < -128) {
+      SPEC_NOUN(val->etype) = V_INT;
+    }
+  }
+  return val;
 }
 
 /*------------------------------------------------------------------*/
 /* valueComplement - complements a constant                         */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valueComplement - complements a constant                         */
 /*------------------------------------------------------------------*/
-value *valComplement ( value  *val)
+value *
+valComplement (value * val)
 {
 {
-    /* depending on type */
-    if ( SPEC_LONG(val->etype)) {
-       if (SPEC_USIGN(val->etype))
-           SPEC_CVAL(val->etype).v_ulong = ~SPEC_CVAL(val->etype).v_ulong ;
-       else
-           SPEC_CVAL(val->etype).v_long  = ~SPEC_CVAL(val->etype).v_long;
+  /* depending on type */
+  if (SPEC_LONG (val->etype))
+    {
+      if (SPEC_USIGN (val->etype))
+       SPEC_CVAL (val->etype).v_ulong = ~SPEC_CVAL (val->etype).v_ulong;
+      else
+       SPEC_CVAL (val->etype).v_long = ~SPEC_CVAL (val->etype).v_long;
     }
     }
-    else {
-       if (SPEC_USIGN(val->etype))
-           SPEC_CVAL(val->etype).v_uint  = ~SPEC_CVAL(val->etype).v_uint ;
-       else
-           SPEC_CVAL(val->etype).v_int   = ~SPEC_CVAL(val->etype).v_int ; 
+  else
+    {
+      if (SPEC_USIGN (val->etype))
+       SPEC_CVAL (val->etype).v_uint = ~SPEC_CVAL (val->etype).v_uint;
+      else
+       SPEC_CVAL (val->etype).v_int = ~SPEC_CVAL (val->etype).v_int;
     }
     }
-    return val ;
+  // ~(unsigned 3) now really is signed
+  SPEC_USIGN(val->etype)=0;
+  return val;
 }
 
 /*------------------------------------------------------------------*/
 /* valueNot - complements a constant                                */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valueNot - complements a constant                                */
 /*------------------------------------------------------------------*/
-value *valNot ( value  *val)
+value *
+valNot (value * val)
 {
 {
-    /* depending on type */
-    if ( SPEC_LONG(val->etype)) {
-       if (SPEC_USIGN(val->etype))
-           SPEC_CVAL(val->etype).v_ulong = !SPEC_CVAL(val->etype).v_ulong ;
-       else
-           SPEC_CVAL(val->etype).v_long  = !SPEC_CVAL(val->etype).v_long;
+  /* depending on type */
+  if (SPEC_LONG (val->etype))
+    {
+      if (SPEC_USIGN (val->etype))
+       SPEC_CVAL (val->etype).v_ulong = !SPEC_CVAL (val->etype).v_ulong;
+      else
+       SPEC_CVAL (val->etype).v_long = !SPEC_CVAL (val->etype).v_long;
     }
     }
-    else {
-       if (SPEC_USIGN(val->etype))
-           SPEC_CVAL(val->etype).v_uint  = !SPEC_CVAL(val->etype).v_uint ;
-       else
-           SPEC_CVAL(val->etype).v_int   = !SPEC_CVAL(val->etype).v_int ; 
+  else
+    {
+      if (SPEC_USIGN (val->etype))
+       SPEC_CVAL (val->etype).v_uint = !SPEC_CVAL (val->etype).v_uint;
+      else
+       SPEC_CVAL (val->etype).v_int = !SPEC_CVAL (val->etype).v_int;
     }
     }
-    return val ;
+  return val;
 }
 
 /*------------------------------------------------------------------*/
 /* valMult - multiply constants                                     */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valMult - multiply constants                                     */
 /*------------------------------------------------------------------*/
-value *valMult (value  *lval, value *rval)
+value *
+valMult (value * lval, value * rval)
 {
 {
-    value *val ;
-    
-    /* create a new value */
-    val = newValue();
-    val->type = val->etype = newLink();
-    val->type->class = SPECIFIER  ;
-    SPEC_NOUN(val->type) = (IS_FLOAT(lval->etype) || 
-                           IS_FLOAT(rval->etype) ? V_FLOAT : V_INT ); 
-    SPEC_SCLS(val->type) = S_LITERAL;/* will remain literal */
-    SPEC_USIGN(val->type) = (SPEC_USIGN(lval->etype) | SPEC_USIGN(rval->etype));
-    SPEC_LONG(val->type) = (SPEC_LONG(lval->etype) | SPEC_LONG(rval->etype));
-    
-    if (IS_FLOAT(val->type))
-       SPEC_CVAL(val->type).v_float = floatFromVal(lval) * floatFromVal(rval);
-    else {
-       if (SPEC_LONG(val->type)) {
-           if (SPEC_USIGN(val->type))
-               SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) * 
-                   (unsigned long) floatFromVal(rval);
-           else
-               SPEC_CVAL(val->type).v_long = (long) floatFromVal(lval) * 
-                   (long) floatFromVal(rval);
-       }
-       else {
-           if (SPEC_USIGN(val->type))
-               SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) * 
-                   (unsigned) floatFromVal(rval);
-           else
-               SPEC_CVAL(val->type).v_int = (int) floatFromVal(lval) * 
-                   (int) floatFromVal(rval);
-       }
+  value *val;
+
+  /* create a new value */
+  val = newValue ();
+  val->type = val->etype = computeType (lval->etype,
+                                       rval->etype,
+                                       RESULT_TYPE_INT,
+                                       '*');
+  SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */
+
+  if (IS_FLOAT (val->type))
+    SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval);
+      /* signed and unsigned mul are the same, as long as the precision of the
+         result isn't bigger than the precision of the operands. */
+  else if (SPEC_LONG (val->type))
+    SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) *
+                                   (TYPE_UDWORD) floatFromVal (rval);
+  else if (SPEC_USIGN (val->type)) /* unsigned int */
+    {
+      TYPE_UDWORD ul = (TYPE_UWORD) floatFromVal (lval) *
+                       (TYPE_UWORD) floatFromVal (rval);
+
+      SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) ul;
+      if (ul != (TYPE_UWORD) ul)
+        werror (W_INT_OVL);
+    }
+  else /* signed int */
+    {
+      TYPE_DWORD l = (TYPE_WORD) floatFromVal (lval) *
+                     (TYPE_WORD) floatFromVal (rval);
+
+      SPEC_CVAL (val->type).v_int = (TYPE_WORD) l;
+      if (l != (TYPE_WORD) l)
+        werror (W_INT_OVL);
     }
     }
-    return val ;   
+  return cheapestVal (val);
 }
 
 /*------------------------------------------------------------------*/
 /* valDiv  - Divide   constants                                     */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valDiv  - Divide   constants                                     */
 /*------------------------------------------------------------------*/
-value *valDiv  (value  *lval, value *rval)
+value *
+valDiv (value * lval, value * rval)
 {
 {
-    value *val ;
+  value *val;
 
 
-    if (floatFromVal(rval) == 0) {
-       werror(E_DIVIDE_BY_ZERO);
-       return rval;
+  if (floatFromVal (rval) == 0)
+    {
+      werror (E_DIVIDE_BY_ZERO);
+      return rval;
     }
     }
-       
-    /* create a new value */
-    val = newValue();
-    val->type = val->etype = ((floatFromVal(lval) / floatFromVal(rval)) < 256 ?
-                             newCharLink() : newIntLink());
-    if (IS_FLOAT(lval->etype) || IS_FLOAT(rval->etype))
-       SPEC_NOUN(val->etype) = V_FLOAT ;
-    SPEC_SCLS(val->etype) = S_LITERAL ;
-    SPEC_USIGN(val->type) = (SPEC_USIGN(lval->etype) | SPEC_USIGN(rval->etype));
-    SPEC_LONG(val->type) = (SPEC_LONG(lval->etype) | SPEC_LONG(rval->etype));
-    
-    if (IS_FLOAT(val->type))
-       SPEC_CVAL(val->type).v_float = floatFromVal(lval) / floatFromVal(rval);
-    else {
-       if (SPEC_LONG(val->type)) {
-           if (SPEC_USIGN(val->type))
-               SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) /
-                   (unsigned long) floatFromVal(rval);
-           else
-               SPEC_CVAL(val->type).v_long = (long) floatFromVal(lval) /
-                   (long) floatFromVal(rval);
-       }
-       else {
-           if (SPEC_USIGN(val->type))
-               SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) /
-                   (unsigned) floatFromVal(rval);
-           else
-               SPEC_CVAL(val->type).v_int = (int) floatFromVal(lval) / 
-                   (int) floatFromVal(rval);
-       }
+
+  /* create a new value */
+  val = newValue ();
+  val->type = val->etype = computeType (lval->etype,
+                                       rval->etype,
+                                       RESULT_TYPE_INT,
+                                       '/');
+  SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */
+
+  if (IS_FLOAT (val->type))
+    SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval);
+  else if (SPEC_LONG (val->type))
+    {
+      if (SPEC_USIGN (val->type))
+       SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) /
+         (TYPE_UDWORD) floatFromVal (rval);
+      else
+       SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) /
+         (TYPE_DWORD) floatFromVal (rval);
+    }
+  else
+    {
+      if (SPEC_USIGN (val->type))
+        SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) /
+          (TYPE_UWORD) floatFromVal (rval);
+      else
+        SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) /
+          (TYPE_WORD) floatFromVal (rval);
     }
     }
-    return val ;   
+  return cheapestVal (val);
 }
 
 /*------------------------------------------------------------------*/
 /* valMod  - Modulus  constants                                     */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valMod  - Modulus  constants                                     */
 /*------------------------------------------------------------------*/
-value *valMod  (value  *lval, value *rval)
+value *
+valMod (value * lval, value * rval)
 {
 {
-    value *val ;
-    
-    /* create a new value */
-    val = newValue();
-    val->type = val->etype = newLink();
-    val->type->class = SPECIFIER  ;
-    SPEC_NOUN(val->type) = V_INT ;   /* type is int */
-    SPEC_SCLS(val->type) = S_LITERAL;/* will remain literal */
-    SPEC_USIGN(val->type) = (SPEC_USIGN(lval->etype) | SPEC_USIGN(rval->etype));
-    SPEC_LONG(val->type) = (SPEC_LONG(lval->etype) | SPEC_LONG(rval->etype));
-    
-    if (SPEC_LONG(val->type)) {
-       if (SPEC_USIGN(val->type))
-           SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) % 
-               (unsigned long) floatFromVal(rval);
-       else
-           SPEC_CVAL(val->type).v_long = (unsigned long) floatFromVal(lval) % 
-               (unsigned long) floatFromVal(rval);
+  value *val;
+
+  /* create a new value */
+  val = newValue();
+  val->type = val->etype = computeType (lval->etype,
+                                       rval->etype,
+                                       RESULT_TYPE_INT,
+                                       '%');
+  SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */
+
+  if (SPEC_LONG (val->type))
+    {
+      if (SPEC_USIGN (val->type))
+       SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) %
+         (TYPE_UDWORD) floatFromVal (rval);
+      else
+       SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) %
+         (TYPE_DWORD) floatFromVal (rval);
     }
     }
-    else {
-       if (SPEC_USIGN(val->type))
-           SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) % 
-               (unsigned) floatFromVal(rval);
-       else
-           SPEC_CVAL(val->type).v_int = (unsigned) floatFromVal(lval) % 
-               (unsigned) floatFromVal(rval);
+  else
+    {
+      if (SPEC_USIGN (val->type))
+        SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) %
+          (TYPE_UWORD) floatFromVal (rval);
+      else
+        SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) %
+          (TYPE_WORD) floatFromVal (rval);
     }
     }
-    
-    return val ;   
+  return cheapestVal (val);
 }
 
 /*------------------------------------------------------------------*/
 /* valPlus - Addition constants                                     */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valPlus - Addition constants                                     */
 /*------------------------------------------------------------------*/
-value *valPlus (value  *lval, value *rval)
+value *
+valPlus (value * lval, value * rval)
 {
 {
-    value *val ;
-    
-    /* create a new value */
-    val = newValue();
-    val->type = val->etype = newLink();
-    val->type->class = SPECIFIER  ;
-    SPEC_NOUN(val->type) = (IS_FLOAT(lval->etype) || 
-                           IS_FLOAT(rval->etype) ? V_FLOAT : V_INT ); 
-    SPEC_SCLS(val->type) = S_LITERAL;/* will remain literal */
-    SPEC_USIGN(val->type) = (SPEC_USIGN(lval->etype) | SPEC_USIGN(rval->etype));
-    SPEC_LONG(val->type) = (SPEC_LONG(lval->etype) | SPEC_LONG(rval->etype));
-    
-    if (IS_FLOAT(val->type))
-       SPEC_CVAL(val->type).v_float = floatFromVal(lval) + floatFromVal(rval);
-    else {
-       if (SPEC_LONG(val->type)) {
-           if (SPEC_USIGN(val->type))
-               SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) +
-                   (unsigned long) floatFromVal(rval);
-           else
-               SPEC_CVAL(val->type).v_long = (long) floatFromVal(lval) +
-                   (long) floatFromVal(rval);
-       }
-       else {
-           if (SPEC_USIGN(val->type))
-               SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) +
-                   (unsigned) floatFromVal(rval);
-           else
-               SPEC_CVAL(val->type).v_int = (int) floatFromVal(lval) + 
-                   (int) floatFromVal(rval);
-       }
+  value *val;
+
+  /* create a new value */
+  val = newValue();
+  val->type = val->etype = computeType (lval->etype,
+                                       rval->etype,
+                                       RESULT_TYPE_INT,
+                                       '+');
+  SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */
+  
+  if (IS_FLOAT (val->type))
+    SPEC_CVAL (val->type).v_float = floatFromVal (lval) + floatFromVal (rval);
+  else  if (SPEC_LONG (val->type))
+    {
+      if (SPEC_USIGN (val->type))
+        SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) +
+         (TYPE_UDWORD) floatFromVal (rval);
+      else
+        SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) +
+          (TYPE_DWORD) floatFromVal (rval);
     }
     }
-    return val ;     
+  else
+    {
+      if (SPEC_USIGN (val->type))
+        SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) +
+          (TYPE_UWORD) floatFromVal (rval);
+      else
+        SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) +
+          (TYPE_WORD) floatFromVal (rval);
+    }
+  return cheapestVal (val);
 }
 
 /*------------------------------------------------------------------*/
 /* valMinus - Addition constants                                    */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valMinus - Addition constants                                    */
 /*------------------------------------------------------------------*/
-value *valMinus (value  *lval, value *rval)
+value *
+valMinus (value * lval, value * rval)
 {
 {
-    value *val ;
-    
-    /* create a new value */
-    val = newValue();
-    val->type = val->etype = newLink();
-    val->type->class = SPECIFIER  ;
-    SPEC_NOUN(val->type) = (IS_FLOAT(lval->etype) || 
-                           IS_FLOAT(rval->etype) ? V_FLOAT : V_INT ); 
-    SPEC_SCLS(val->type) = S_LITERAL;/* will remain literal */
-    SPEC_USIGN(val->type) = (SPEC_USIGN(lval->etype) | SPEC_USIGN(rval->etype));
-    SPEC_LONG(val->type) = (SPEC_LONG(lval->etype) | SPEC_LONG(rval->etype));
-    
-    if (IS_FLOAT(val->type))
-       SPEC_CVAL(val->type).v_float = floatFromVal(lval) - floatFromVal(rval);
-    else {
-       if (SPEC_LONG(val->type)) {
-           if (SPEC_USIGN(val->type))
-               SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) -
-                   (unsigned long) floatFromVal(rval);
-           else
-               SPEC_CVAL(val->type).v_long = (long) floatFromVal(lval) -
-                   (long) floatFromVal(rval);
-       }
-       else {
-           if (SPEC_USIGN(val->type))
-               SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) -
-                   (unsigned) floatFromVal(rval);
-           else
-               SPEC_CVAL(val->type).v_int = (int) floatFromVal(lval) - (int) floatFromVal(rval);
-       }
+  value *val;
+
+  /* create a new value */
+  val = newValue();
+  val->type = val->etype = computeType (lval->etype,
+                                       rval->etype,
+                                       RESULT_TYPE_INT,
+                                       '-');
+  SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */
+  
+  if (IS_FLOAT (val->type))
+    SPEC_CVAL (val->type).v_float = floatFromVal (lval) - floatFromVal (rval);
+  else  if (SPEC_LONG (val->type))
+    {
+      if (SPEC_USIGN (val->type))
+        SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) -
+          (TYPE_UDWORD) floatFromVal (rval);
+      else
+        SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) -
+          (TYPE_DWORD) floatFromVal (rval);
     }
     }
-    return val ; 
+  else
+   {
+     if (SPEC_USIGN (val->type))
+       SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) -
+         (TYPE_UWORD) floatFromVal (rval);
+     else
+       SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) -
+         (TYPE_WORD) floatFromVal (rval);
+    }
+  return cheapestVal (val);
 }
 
 /*------------------------------------------------------------------*/
 /* valShift - Shift left or right                                   */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valShift - Shift left or right                                   */
 /*------------------------------------------------------------------*/
-value *valShift (value  *lval, value *rval, int lr)
+value *
+valShift (value * lval, value * rval, int lr)
 {
 {
-   value *val ;
-
-   /* create a new value */
-   val = newValue();
-   val->type = val->etype = newLink();
-   val->type->class = SPECIFIER  ;
-   SPEC_NOUN(val->type) = V_INT ;   /* type is int */
-   SPEC_SCLS(val->type) = S_LITERAL;/* will remain literal */
-   SPEC_USIGN(val->type) = (SPEC_USIGN(lval->etype) | SPEC_USIGN(rval->etype));
-   SPEC_LONG(val->type) = (SPEC_LONG(lval->etype) | SPEC_LONG(rval->etype));
-   
-   if (lr) {
-       if (SPEC_LONG(val->type)) {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) << 
-                  (unsigned long) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_long = (long) floatFromVal(lval) << 
-                  (long) floatFromVal(rval);
-       }
-       else {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) << 
-                  (unsigned) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_int = (int) floatFromVal(lval) << 
-                  (int) floatFromVal(rval);
-       }
-   }
-   else {
-       if (SPEC_LONG(val->type)) {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) >>
-                  (unsigned long) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_long = (long) floatFromVal(lval) >>
-                  (long) floatFromVal(rval);
-       }
-       else {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) >>
-                  (unsigned) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_int = (int) floatFromVal(lval) >>
-                  (int) floatFromVal(rval);
-       }
-   }
-
-   return val ;   
+  value *val;
+
+  /* create a new value */
+  val = newValue();
+  val->type = val->etype = computeType (lval->etype,
+                                       NULL,
+                                       RESULT_TYPE_INT,
+                                       'S');
+  SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */
+
+  if (getSize (val->type) * 8 <= (TYPE_UDWORD) floatFromVal (rval) &&
+       /* left shift */
+      (lr ||
+       /* right shift and unsigned */
+       (!lr && SPEC_USIGN (rval->type))))
+    {
+      werror (W_SHIFT_CHANGED, (lr ? "left" : "right"));
+    }
+
+  if (SPEC_LONG (val->type))
+    {
+      if (SPEC_USIGN (val->type))
+        {
+          SPEC_CVAL (val->type).v_ulong = lr ?
+           (TYPE_UDWORD) floatFromVal (lval) << (TYPE_UDWORD) floatFromVal (rval) : \
+           (TYPE_UDWORD) floatFromVal (lval) >> (TYPE_UDWORD) floatFromVal (rval);
+        }
+      else
+        {
+          SPEC_CVAL (val->type).v_long = lr ?
+           (TYPE_DWORD) floatFromVal (lval) << (TYPE_UDWORD) floatFromVal (rval) : \
+           (TYPE_DWORD) floatFromVal (lval) >> (TYPE_UDWORD) floatFromVal (rval);
+        }
+    }
+  else
+    {
+      if (SPEC_USIGN (val->type))
+        {
+          SPEC_CVAL (val->type).v_uint = lr ?
+           (TYPE_UWORD) floatFromVal (lval) << (TYPE_UDWORD) floatFromVal (rval) : \
+           (TYPE_UWORD) floatFromVal (lval) >> (TYPE_UDWORD) floatFromVal (rval);
+        }
+      else
+        {
+          SPEC_CVAL (val->type).v_int = lr ?
+           (TYPE_WORD) floatFromVal (lval) << (TYPE_UDWORD) floatFromVal (rval) : \
+           (TYPE_WORD) floatFromVal (lval) >> (TYPE_UDWORD) floatFromVal (rval);
+        }
+    }
+  return cheapestVal (val);
 }
 
 /*------------------------------------------------------------------*/
 /* valCompare- Compares two literal                                 */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valCompare- Compares two literal                                 */
 /*------------------------------------------------------------------*/
-value *valCompare (value  *lval, value *rval, int ctype)
+value *
+valCompare (value * lval, value * rval, int ctype)
 {
 {
-   value *val ;
-
-   /* create a new value */
-   val = newValue();
-   val->type = val->etype = newCharLink();
-   val->type->class = SPECIFIER  ;
-   SPEC_NOUN(val->type) = V_INT ;   /* type is int */
-   SPEC_SCLS(val->type) = S_LITERAL;/* will remain literal */   
-
-   switch (ctype)
-   {
-   case '<' :                 
-       SPEC_CVAL(val->type).v_int = floatFromVal(lval) < floatFromVal(rval);
-       break ;
-
-   case '>' :    
-       SPEC_CVAL(val->type).v_int = floatFromVal(lval) > floatFromVal(rval);
-      break ;
-
-   case LE_OP  :
-       SPEC_CVAL(val->type).v_int = floatFromVal(lval) <= floatFromVal(rval);
-       break ;
-
-   case GE_OP  :
-       SPEC_CVAL(val->type).v_int = floatFromVal(lval) >= floatFromVal(rval);
-       break ;
-
-   case EQ_OP  :
-       SPEC_CVAL(val->type).v_int = floatFromVal(lval) == floatFromVal(rval);
-       break ;
+  value *val;
+
+  /* create a new value */
+  val = newValue ();
+  val->type = val->etype = newCharLink ();
+  val->type->class = SPECIFIER;
+  SPEC_NOUN (val->type) = V_CHAR;      /* type is char */
+  SPEC_USIGN (val->type) = 1;
+  SPEC_SCLS (val->type) = S_LITERAL;   /* will remain literal */
+
+  switch (ctype)
+    {
+    case '<':
+      SPEC_CVAL (val->type).v_int = floatFromVal (lval) < floatFromVal (rval);
+      break;
+
+    case '>':
+      SPEC_CVAL (val->type).v_int = floatFromVal (lval) > floatFromVal (rval);
+      break;
+
+    case LE_OP:
+      SPEC_CVAL (val->type).v_int = floatFromVal (lval) <= floatFromVal (rval);
+      break;
+
+    case GE_OP:
+      SPEC_CVAL (val->type).v_int = floatFromVal (lval) >= floatFromVal (rval);
+      break;
+
+    case EQ_OP:
+      if (SPEC_NOUN(lval->type) == V_FLOAT ||
+         SPEC_NOUN(rval->type) == V_FLOAT)
+       {
+         SPEC_CVAL (val->type).v_int = floatFromVal (lval) == floatFromVal (rval);
+       }
+      else
+       {
+         /* integrals: ignore signedness */
+         TYPE_UDWORD l, r;
+
+         l = (TYPE_UDWORD) floatFromVal (lval);
+         r = (TYPE_UDWORD) floatFromVal (rval);
+         /* In order to correctly compare 'signed int' and 'unsigned int' it's
+            neccessary to strip them to 16 bit.
+            Literals are reduced to their cheapest type, therefore left and
+            right might have different types. It's neccessary to find a
+            common type: int (used for char too) or long */
+         if (!IS_LONG (lval->etype) &&
+             !IS_LONG (rval->etype))
+           {
+             r = (TYPE_UWORD) r;
+             l = (TYPE_UWORD) l;
+           }
+         SPEC_CVAL (val->type).v_int = l == r;
+       }
+      break;
+    case NE_OP:
+      if (SPEC_NOUN(lval->type) == V_FLOAT ||
+         SPEC_NOUN(rval->type) == V_FLOAT)
+       {
+         SPEC_CVAL (val->type).v_int = floatFromVal (lval) != floatFromVal (rval);
+       }
+      else
+       {
+         /* integrals: ignore signedness */
+         TYPE_UDWORD l, r;
+
+         l = (TYPE_UDWORD) floatFromVal (lval);
+         r = (TYPE_UDWORD) floatFromVal (rval);
+         /* In order to correctly compare 'signed int' and 'unsigned int' it's
+            neccessary to strip them to 16 bit.
+            Literals are reduced to their cheapest type, therefore left and
+            right might have different types. It's neccessary to find a
+            common type: int (used for char too) or long */
+         if (!IS_LONG (lval->etype) &&
+             !IS_LONG (rval->etype))
+           {
+             r = (TYPE_UWORD) r;
+             l = (TYPE_UWORD) l;
+           }
+         SPEC_CVAL (val->type).v_int = l != r;
+       }
+      break;
 
 
-   case NE_OP  :
-       SPEC_CVAL(val->type).v_int = floatFromVal(lval) != floatFromVal(rval);
-       break ;
-       
-   }                            
+    }
 
 
-   return val ;   
+  return val;
 }
 
 /*------------------------------------------------------------------*/
 /* valBitwise - Bitwise operation                                   */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valBitwise - Bitwise operation                                   */
 /*------------------------------------------------------------------*/
-value *valBitwise (value  *lval, value *rval, int op)
+value *
+valBitwise (value * lval, value * rval, int op)
 {
 {
-   value *val ;
-
-   /* create a new value */
-   val = newValue();
-   val->type = copyLinkChain (lval->type);
-   val->etype = getSpec(val->type);
+  value *val;
+
+  /* create a new value */
+  val = newValue ();
+  val->type = computeType (lval->etype, rval->etype, RESULT_TYPE_CHAR, op);
+  val->etype = getSpec (val->type);
+  SPEC_SCLS (val->etype) = S_LITERAL;
+
+  switch (op)
+    {
+    case '&':
+      if (SPEC_LONG (val->type))
+       {
+         if (SPEC_USIGN (val->type))
+           SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) &
+             (TYPE_UDWORD) floatFromVal (rval);
+         else
+           SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) &
+             (TYPE_DWORD) floatFromVal (rval);
+       }
+      else
+       {
+         if (SPEC_USIGN (val->type))
+           SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) &
+             (TYPE_UWORD) floatFromVal (rval);
+         else
+           SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) & (TYPE_WORD) floatFromVal (rval);
+       }
+      break;
+
+    case '|':
+      if (SPEC_LONG (val->type))
+       {
+         if (SPEC_USIGN (val->type))
+           SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) |
+             (TYPE_UDWORD) floatFromVal (rval);
+         else
+           SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) |
+             (TYPE_DWORD) floatFromVal (rval);
+       }
+      else
+       {
+         if (SPEC_USIGN (val->type))
+           SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) |
+             (TYPE_UWORD) floatFromVal (rval);
+         else
+           SPEC_CVAL (val->type).v_int =
+             (TYPE_WORD) floatFromVal (lval) | (TYPE_WORD) floatFromVal (rval);
+       }
 
 
-   switch (op)
-   {
-   case '&' :
-       if (SPEC_LONG(val->type)) {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) &
-                  (unsigned long) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_long = (long) floatFromVal(lval) &
-                  (long) floatFromVal(rval);
-       }
-       else {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) &
-                  (unsigned) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_int = (int) floatFromVal(lval) & (int) floatFromVal(rval);
-       }
-       break ;
-
-   case '|' :
-       if (SPEC_LONG(val->type)) {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) |
-                  (unsigned long) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_long = (long) floatFromVal(lval) |
-                  (long) floatFromVal(rval);
-       }
-       else {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) |
-                  (unsigned) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_int = 
-                  (int) floatFromVal(lval) | (int) floatFromVal(rval);
-       }
-      break ;
-
-   case '^' :
-       if (SPEC_LONG(val->type)) {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_ulong = (unsigned long) floatFromVal(lval) ^
-                  (unsigned long) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_long = (long) floatFromVal(lval) ^
-                  (long) floatFromVal(rval);
-       }
-       else {
-          if (SPEC_USIGN(val->type))
-              SPEC_CVAL(val->type).v_uint = (unsigned) floatFromVal(lval) ^
-                  (unsigned) floatFromVal(rval);
-          else
-              SPEC_CVAL(val->type).v_int = 
-                  (int) floatFromVal(lval) ^ (int) floatFromVal(rval);
-       }
-      break ;               
-   }
-
-   return val ;   
+      break;
+
+    case '^':
+      if (SPEC_LONG (val->type))
+       {
+         if (SPEC_USIGN (val->type))
+           SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) ^
+             (TYPE_UDWORD) floatFromVal (rval);
+         else
+           SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) ^
+             (TYPE_DWORD) floatFromVal (rval);
+       }
+      else
+       {
+         if (SPEC_USIGN (val->type))
+           SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) ^
+             (TYPE_UWORD) floatFromVal (rval);
+         else
+           SPEC_CVAL (val->type).v_int =
+             (TYPE_WORD) floatFromVal (lval) ^ (TYPE_WORD) floatFromVal (rval);
+       }
+      break;
+    }
+    
+  return cheapestVal(val);
 }
 
 /*------------------------------------------------------------------*/
 /* valAndOr   - Generates code for and / or operation               */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valAndOr   - Generates code for and / or operation               */
 /*------------------------------------------------------------------*/
-value *valLogicAndOr (value  *lval, value *rval, int op)
+value *
+valLogicAndOr (value * lval, value * rval, int op)
 {
 {
-   value *val ;
+  value *val;
+
+  /* create a new value */
+  val = newValue ();
+  val->type = val->etype = newCharLink ();
+  val->type->class = SPECIFIER;
+  SPEC_SCLS (val->type) = S_LITERAL;   /* will remain literal */
+  SPEC_USIGN (val->type) = 1;
+
+  switch (op)
+    {
+    case AND_OP:
+      SPEC_CVAL (val->type).v_int = floatFromVal (lval) && floatFromVal (rval);
+      break;
+
+    case OR_OP:
+      SPEC_CVAL (val->type).v_int = floatFromVal (lval) || floatFromVal (rval);
+      break;
+    }
 
 
-   /* create a new value */
-   val = newValue();
-   val->type = val->etype = newCharLink();
-   val->type->class = SPECIFIER  ;
-   SPEC_SCLS(val->type) = S_LITERAL;/* will remain literal */  
 
 
-   switch (op)
-   {
-   case AND_OP :
-       SPEC_CVAL(val->type).v_int = floatFromVal(lval)  && floatFromVal(rval);
-       break ;
-
-   case OR_OP :
-       SPEC_CVAL(val->type).v_int = floatFromVal(lval)  || floatFromVal(rval);
-       break ;
-   }
-  
-   
-   return val ;   
+  return val;
 }
 
 /*------------------------------------------------------------------*/
 /* valCastLiteral - casts a literal value to another type           */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* valCastLiteral - casts a literal value to another type           */
 /*------------------------------------------------------------------*/
-value *valCastLiteral (link *dtype, double fval)
+value *
+valCastLiteral (sym_link * dtype, double fval)
 {
 {
-    value *val ;
-
-    if (!dtype)
-       return NULL ;
-
-    val = newValue();
-    val->etype = getSpec (val->type = copyLinkChain(dtype));
-    SPEC_SCLS(val->etype) = S_LITERAL ;
-    /* if it is not a specifier then we can assume that */
-    /* it will be an unsigned long                      */
-    if (!IS_SPEC(val->type)) {
-       SPEC_CVAL(val->etype).v_ulong = (unsigned long) fval;
-       return val;
-    }
-
-    if (SPEC_NOUN(val->etype) == V_FLOAT )
-       SPEC_CVAL(val->etype).v_float = fval;
-    else {
-       if (SPEC_LONG(val->etype)) {
-           if (SPEC_USIGN(val->etype))
-               SPEC_CVAL(val->etype).v_ulong = (unsigned long) fval;
-           else
-               SPEC_CVAL(val->etype).v_long  = (long) fval;
-       }
-       else {
-           if (SPEC_USIGN(val->etype))
-               SPEC_CVAL(val->etype).v_uint = (unsigned int) fval;
-           else
-               SPEC_CVAL(val->etype).v_int  = (int) fval;   
-       }
-    }
-    return val;
+  value *val;
+  TYPE_UDWORD l = (TYPE_UDWORD)fval;
+
+  if (!dtype)
+    return NULL;
+
+  val = newValue ();
+  val->etype = getSpec (val->type = copyLinkChain (dtype));
+  SPEC_SCLS (val->etype) = S_LITERAL;
+
+  /* if it is not a specifier then we can assume that */
+  /* it will be an unsigned long                      */
+  if (!IS_SPEC (val->type)) {
+      SPEC_CVAL (val->etype).v_ulong = l;
+      return val;
+  }
+
+  if (SPEC_NOUN (val->etype) == V_FLOAT)
+      SPEC_CVAL (val->etype).v_float = fval;
+  else if (SPEC_NOUN (val->etype) == V_BIT ||
+           SPEC_NOUN (val->etype) == V_SBIT)
+    SPEC_CVAL (val->etype).v_uint = l & 1;   
+  else if (SPEC_NOUN (val->etype) == V_BITFIELD)
+    SPEC_CVAL (val->etype).v_uint = l &
+                                   (0xffffu >> (16 - SPEC_BLEN (val->etype)));
+  else if (SPEC_NOUN (val->etype) == V_CHAR) {
+      if (SPEC_USIGN (val->etype))
+         SPEC_CVAL (val->etype).v_uint= (TYPE_UBYTE) l;
+      else
+         SPEC_CVAL (val->etype).v_int = (TYPE_BYTE) l;
+  } else {
+      if (SPEC_LONG (val->etype)) {
+         if (SPEC_USIGN (val->etype))
+             SPEC_CVAL (val->etype).v_ulong = (TYPE_UDWORD) l;
+         else
+             SPEC_CVAL (val->etype).v_long = (TYPE_DWORD) l;
+      } else {
+         if (SPEC_USIGN (val->etype))
+             SPEC_CVAL (val->etype).v_uint = (TYPE_UWORD)l;
+         else
+             SPEC_CVAL (val->etype).v_int = (TYPE_WORD)l;
+      }
+  }
+  return val;
 }
 
 /*------------------------------------------------------------------*/
 /* getNelements - determines # of elements from init list           */
 /*------------------------------------------------------------------*/
 }
 
 /*------------------------------------------------------------------*/
 /* getNelements - determines # of elements from init list           */
 /*------------------------------------------------------------------*/
-int getNelements (link *type,initList *ilist)
+int
+getNelements (sym_link * type, initList * ilist)
 {
 {
-    link *etype = getSpec(type);
-    int i;
-
-    if (! ilist)
-       return 0;
-
-    if (ilist->type == INIT_DEEP)
-       ilist = ilist->init.deep;
-
-    /* if type is a character array and there is only one
-       initialiser then get the length of the string */
-    if (IS_ARRAY(type) && IS_CHAR(etype) && !ilist->next) {
-       ast *iast = ilist->init.node;
-       value *v = (iast->type == EX_VALUE ? iast->opval.val : NULL);
-       if (!v) {
-           werror(E_INIT_WRONG);
-           return 0;
+  int i;
+
+  if (!ilist)
+    return 0;
+
+  if (ilist->type == INIT_DEEP)
+    ilist = ilist->init.deep;
+
+  /* if type is a character array and there is only one
+     (string) initialiser then get the length of the string */
+  if (IS_ARRAY (type) && IS_CHAR (type->next) && !ilist->next)
+    {
+      ast *iast = ilist->init.node;
+      value *v = (iast->type == EX_VALUE ? iast->opval.val : NULL);
+      if (!v)
+       {
+         werror (E_CONST_EXPECTED);
+         return 0;
        }
        }
-       if (!IS_ARRAY(v->type) || !IS_CHAR(v->etype)) {
-            werror(E_INIT_WRONG);
-            return 0;
+
+      if (IS_ARRAY (v->type) && IS_CHAR (v->etype))
+       // yep, it's a string
+       {
+         return DCL_ELEM (v->type);
        }
        }
-       return DCL_ELEM(v->type);
     }
 
     }
 
-    i = 0 ;
-    while (ilist) {
-       i++;
-       ilist = ilist->next;
+  i = 0;
+  while (ilist)
+    {
+      i++;
+      ilist = ilist->next;
     }
     }
-
-    return i;
+  return i;
 }
 
 /*-----------------------------------------------------------------*/
 /* valForArray - returns a value with name of array index          */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* valForArray - returns a value with name of array index          */
 /*-----------------------------------------------------------------*/
-value *valForArray (ast *arrExpr)
+value *
+valForArray (ast * arrExpr)
 {
 {
-    value *val, *lval = NULL ;
-    char buffer[128];
-    int size = getSize(arrExpr->left->ftype->next);
-    /* if the right or left is an array
-       resolve it first */
-    if (IS_AST_OP(arrExpr->left)) {
-       if (arrExpr->left->opval.op == '[')
-           lval = valForArray(arrExpr->left);
-       else
-           if (arrExpr->left->opval.op == '.')
-               lval = valForStructElem(arrExpr->left->left,
-                                       arrExpr->left->right);
-           else
-               if (arrExpr->left->opval.op == PTR_OP &&
-                   IS_ADDRESS_OF_OP(arrExpr->left->left))
-                   lval = valForStructElem(arrExpr->left->left->left,
-                                           arrExpr->left->right);
-               else
-                   return NULL;
-                   
-    } else
-       if (!IS_AST_SYM_VALUE(arrExpr->left))
-           return NULL ;
-    
-    if (!IS_AST_LIT_VALUE(arrExpr->right))
+  value *val, *lval = NULL;
+  char buffer[128];
+  int size = getSize (arrExpr->left->ftype->next);
+  /* if the right or left is an array
+     resolve it first */
+  if (IS_AST_OP (arrExpr->left))
+    {
+      if (arrExpr->left->opval.op == '[')
+       lval = valForArray (arrExpr->left);
+      else if (arrExpr->left->opval.op == '.')
+       lval = valForStructElem (arrExpr->left->left,
+                                arrExpr->left->right);
+      else if (arrExpr->left->opval.op == PTR_OP &&
+              IS_ADDRESS_OF_OP (arrExpr->left->left))
+       lval = valForStructElem (arrExpr->left->left->left,
+                                arrExpr->left->right);
+      else
        return NULL;
        return NULL;
-    
-    val = newValue();
-    if (!lval)
-       sprintf(buffer,"%s",AST_SYMBOL(arrExpr->left)->rname);
-    else
-       sprintf(buffer,"%s",lval->name);
-      
-    sprintf(val->name,"(%s + %d)",buffer,
-           (int)AST_LIT_VALUE(arrExpr->right)*size);    
-    
-    val->type = newLink();    
-    if (SPEC_SCLS(arrExpr->left->etype) == S_CODE) {
-       DCL_TYPE(val->type) = CPOINTER ;
-       DCL_PTR_CONST(val->type) = port->mem.code_ro;
+
     }
     }
-    else
-       if (SPEC_SCLS(arrExpr->left->etype) == S_XDATA)
-           DCL_TYPE(val->type) = FPOINTER;
-       else
-           if (SPEC_SCLS(arrExpr->left->etype) == S_XSTACK )
-               DCL_TYPE(val->type) = PPOINTER ;
-           else
-               if (SPEC_SCLS(arrExpr->left->etype) == S_IDATA)
-                   DCL_TYPE(val->type) = IPOINTER ;
-               else
-                   if (SPEC_SCLS(arrExpr->left->etype) == S_EEPROM)
-                       DCL_TYPE(val->type) = EEPPOINTER ;
-                   else
-                       DCL_TYPE(val->type) = POINTER ;
-    val->type->next = arrExpr->left->ftype;
-    val->etype = getSpec(val->type);
-    return val;
+  else if (!IS_AST_SYM_VALUE (arrExpr->left))
+    return NULL;
+
+  if (!IS_AST_LIT_VALUE (arrExpr->right))
+    return NULL;
+
+  val = newValue ();
+  if (!lval)
+    {
+       SNPRINTF (buffer, sizeof(buffer), "%s", AST_SYMBOL (arrExpr->left)->rname);
+    }
+  else
+    {
+       SNPRINTF (buffer, sizeof(buffer), "%s", lval->name);
+    }
+
+  SNPRINTF (val->name, sizeof(val->name), "(%s + %d)", buffer,
+          (int) AST_LIT_VALUE (arrExpr->right) * size);
+
+  val->type = newLink (DECLARATOR);
+  if (SPEC_SCLS (arrExpr->left->etype) == S_CODE)
+    DCL_TYPE (val->type) = CPOINTER;
+  else if (SPEC_SCLS (arrExpr->left->etype) == S_XDATA)
+    DCL_TYPE (val->type) = FPOINTER;
+  else if (SPEC_SCLS (arrExpr->left->etype) == S_XSTACK)
+    DCL_TYPE (val->type) = PPOINTER;
+  else if (SPEC_SCLS (arrExpr->left->etype) == S_IDATA)
+    DCL_TYPE (val->type) = IPOINTER;
+  else if (SPEC_SCLS (arrExpr->left->etype) == S_EEPROM)
+    DCL_TYPE (val->type) = EEPPOINTER;
+  else
+    DCL_TYPE (val->type) = POINTER;
+  val->type->next = arrExpr->left->ftype;
+  val->etype = getSpec (val->type);
+  return val;
 }
 
 /*-----------------------------------------------------------------*/
 /* valForStructElem - returns value with name of struct element    */
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
 /* valForStructElem - returns value with name of struct element    */
 /*-----------------------------------------------------------------*/
-value *valForStructElem(ast *structT, ast *elemT)
+value *
+valForStructElem (ast * structT, ast * elemT)
 {
 {
-    value *val, *lval = NULL;
-    char buffer[128];
-    symbol *sym;
-
-    /* left could be furthur derefed */
-    if (IS_AST_OP(structT)) {
-       if (structT->opval.op == '[')
-           lval = valForArray(structT);
-       else
-           if (structT->opval.op == '.')
-               lval = valForStructElem(structT->left,structT->right);
-           else
-               if (structT->opval.op == PTR_OP &&
-                   IS_ADDRESS_OF_OP(structT->left))
-                   lval = valForStructElem(structT->left->left,
-                                           structT->right);
-               else
-                   return NULL;
+  value *val, *lval = NULL;
+  char buffer[128];
+  symbol *sym;
+
+  /* left could be furthur derefed */
+  if (IS_AST_OP (structT))
+    {
+      if (structT->opval.op == '[')
+       lval = valForArray (structT);
+      else if (structT->opval.op == '.')
+       lval = valForStructElem (structT->left, structT->right);
+      else if (structT->opval.op == PTR_OP &&
+              IS_ADDRESS_OF_OP (structT->left))
+       lval = valForStructElem (structT->left->left,
+                                structT->right);
+      else
+       return NULL;
     }
 
     }
 
-    if (!IS_AST_SYM_VALUE(elemT))
-       return NULL;
+  if (!IS_AST_SYM_VALUE (elemT))
+    return NULL;
 
 
-    if (!IS_STRUCT(structT->etype))
-       return NULL;
+  if (!IS_STRUCT (structT->etype))
+    return NULL;
 
 
-    if ((sym = getStructElement(SPEC_STRUCT(structT->etype),
-                               AST_SYMBOL(elemT))) == NULL) {
-       return NULL;
+  if ((sym = getStructElement (SPEC_STRUCT (structT->etype),
+                              AST_SYMBOL (elemT))) == NULL)
+    {
+      return NULL;
     }
 
     }
 
-    val = newValue();
-    if (!lval)
-       sprintf(buffer,"%s",AST_SYMBOL(structT)->rname);
-    else
-       sprintf(buffer,"%s",lval->name);
-      
-    sprintf(val->name,"(%s + %d)",buffer,
-           (int)sym->offset);   
-    
-    val->type = newLink();
-    if (SPEC_SCLS(structT->etype) == S_CODE) {
-       DCL_TYPE(val->type) = CPOINTER ;
-       DCL_PTR_CONST(val->type) = port->mem.code_ro;
+  val = newValue ();
+  if (!lval)
+    {
+       SNPRINTF(buffer, sizeof(buffer), "%s", AST_SYMBOL (structT)->rname);
     }
     }
-    else
-       if (SPEC_SCLS(structT->etype) == S_XDATA)
-           DCL_TYPE(val->type) = FPOINTER;
-       else
-           if (SPEC_SCLS(structT->etype) == S_XSTACK )
-               DCL_TYPE(val->type) = PPOINTER ;
-           else
-               if (SPEC_SCLS(structT->etype) == S_IDATA)
-                   DCL_TYPE(val->type) = IPOINTER ;
-               else
-                   if (SPEC_SCLS(structT->etype) == S_EEPROM)
-                       DCL_TYPE(val->type) = EEPPOINTER ;
-                   else
-                       DCL_TYPE(val->type) = POINTER ;
-    val->type->next = sym->type;
-    val->etype = getSpec(val->type);
-    return val; 
+  else
+    {
+       SNPRINTF (buffer, sizeof(buffer), "%s", lval->name);
+    }
+
+  SNPRINTF (val->name, sizeof(val->name), "(%s + %d)", buffer,
+          (int) sym->offset);
+
+  val->type = newLink (DECLARATOR);
+  if (SPEC_SCLS (structT->etype) == S_CODE)
+    DCL_TYPE (val->type) = CPOINTER;
+  else if (SPEC_SCLS (structT->etype) == S_XDATA)
+    DCL_TYPE (val->type) = FPOINTER;
+  else if (SPEC_SCLS (structT->etype) == S_XSTACK)
+    DCL_TYPE (val->type) = PPOINTER;
+  else if (SPEC_SCLS (structT->etype) == S_IDATA)
+    DCL_TYPE (val->type) = IPOINTER;
+  else if (SPEC_SCLS (structT->etype) == S_EEPROM)
+    DCL_TYPE (val->type) = EEPPOINTER;
+  else
+    DCL_TYPE (val->type) = POINTER;
+  val->type->next = sym->type;
+  val->etype = getSpec (val->type);
+  return val;
+}
+
+/*-----------------------------------------------------------------*/
+/* valForCastAggr - will return value for a cast of an aggregate   */
+/*                  plus minus a constant                          */
+/*-----------------------------------------------------------------*/
+value *
+valForCastAggr (ast * aexpr, sym_link * type, ast * cnst, int op)
+{
+  value *val;
+
+  if (!IS_AST_SYM_VALUE (aexpr))
+    return NULL;
+  if (!IS_AST_LIT_VALUE (cnst))
+    return NULL;
+
+  val = newValue ();
+
+  SNPRINTF (val->name, sizeof(val->name), "(%s %c %d)",
+          AST_SYMBOL (aexpr)->rname, op,
+          getSize (type->next) * (int) AST_LIT_VALUE (cnst));
+
+  val->type = type;
+  val->etype = getSpec (val->type);
+  return val;
+}
+
+/*-----------------------------------------------------------------*/
+/* valForCastAggr - will return value for a cast of an aggregate   */
+/*                  with no constant                               */
+/*-----------------------------------------------------------------*/
+value *
+valForCastArr (ast * aexpr, sym_link * type)
+{
+  value *val;
+
+  if (!IS_AST_SYM_VALUE (aexpr))
+    return NULL;
+
+  val = newValue ();
+
+  SNPRINTF (val->name, sizeof(val->name), "(%s)",
+          AST_SYMBOL (aexpr)->rname);
+
+  val->type = type;
+  val->etype = getSpec (val->type);
+  return val;
 }
 }