int=32 but short=16
[fw/sdcc] / src / SDCCval.c
index 502099538decf292b522dc83eb9591cb1a2a8532..fe15c800b49c63a17e1813aa53fad01ed426fd42 100644 (file)
 #include <limits.h>
 #include "newalloc.h"
 
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define LONG_LONG __int64
+#else
+#define LONG_LONG long long
+#endif
+
 int cNestLevel;
 
 /*-----------------------------------------------------------------*/
@@ -39,7 +45,7 @@ newValue ()
 {
   value *val;
 
-  val = Safe_calloc (1, sizeof (value));
+  val = Safe_alloc (sizeof (value));
 
   return val;
 }
@@ -53,7 +59,7 @@ newiList (int type, void *ilist)
   initList *nilist;
 
 
-  nilist = Safe_calloc (1, sizeof (initList));
+  nilist = Safe_alloc (sizeof (initList));
 
   nilist->type = type;
   nilist->lineno = yylineno;
@@ -139,7 +145,7 @@ convertIListToConstList(initList *src, literalList **lList)
        }
        else
        {
-           newL = Safe_malloc(sizeof(literalList));
+           newL = Safe_alloc(sizeof(literalList));
            newL->literalValue = val;
            newL->count = 1;
            newL->next = NULL;
@@ -175,7 +181,7 @@ copyLiteralList(literalList *src)
     
     while (src)
     {
-       newL = Safe_malloc(sizeof(literalList));
+       newL = Safe_alloc(sizeof(literalList));
        
        newL->literalValue = src->literalValue;
        newL->count = src->count;
@@ -312,6 +318,63 @@ symbolVal (symbol * sym)
   return val;
 }
 
+/*--------------------------------------------------------------------*/
+/* cheapestVal - convert a val to the cheapest as possible value      */
+/*--------------------------------------------------------------------*/
+value *cheapestVal (value *val) {
+  long sval=0;
+  unsigned long 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<=0xff) {
+      SPEC_NOUN(val->type)=V_CHAR;
+      SPEC_LONG(val->type)=0;
+    } else {
+      if (uval<=0xffff) {
+       SPEC_LONG(val->type)=0;
+      }
+    }
+  } else {
+    if (sval<0) {
+      if (sval>=-128) {
+       SPEC_NOUN(val->type)=V_CHAR;
+       SPEC_LONG(val->type)=0;
+      } else {
+       if (sval>=-32768) {
+         SPEC_LONG(val->type)=0;
+       }
+      }
+    } else {
+      if (sval<=127) {
+       SPEC_NOUN(val->type)=V_CHAR;
+       SPEC_LONG(val->type)=0;
+      } else {
+       if (sval<=32767) {
+         SPEC_LONG(val->type)=0;
+       }
+      }
+    }
+  }
+  return val;
+}
+
 /*-----------------------------------------------------------------*/
 /* valueFromLit - creates a value from a literal                   */
 /*-----------------------------------------------------------------*/
@@ -337,9 +400,9 @@ value *
 constFloatVal (char *s)
 {
   value *val = newValue ();
-  float sval;
+  double sval;
 
-  if (sscanf (s, "%f", &sval) != 1)
+  if (sscanf (s, "%lf", &sval) != 1)
     {
       werror (E_INVALID_FLOAT_CONST, s);
       return constVal ("0");
@@ -363,7 +426,7 @@ value *constVal (char *s)
   short hex = 0, octal = 0;
   char scanFmt[10];
   int scI = 0;
-  unsigned long sval;
+  LONG_LONG sval;
 
   val = newValue ();           /* alloc space for value   */
 
@@ -387,6 +450,8 @@ value *constVal (char *s)
   /* create the scan string */
   scanFmt[scI++] = '%';
 
+  scanFmt[scI++] = 'L';
+
   if (octal)
     scanFmt[scI++] = 'o';
   else if (hex)
@@ -394,14 +459,13 @@ value *constVal (char *s)
   else
     scanFmt[scI++] = 'd';
 
-  scanFmt[scI++] = 'L';
   scanFmt[scI++] = '\0';
 
   sscanf (s, scanFmt, &sval);
 
   if (sval<0) { // "-28u" will still be signed and negative
     SPEC_USIGN (val->type) = 0;
-    if (sval<-32768) { // check if have to promote to long
+    if (sval<-32768) { // check if we have to promote to long
       SPEC_NOUN (val->type) = V_INT;
       SPEC_LONG (val->type) = 1;
       SPEC_CVAL (val->type).v_long=sval;
@@ -432,40 +496,34 @@ value *constVal (char *s)
     /param src Pointer to 'x' from start of hex character value
 */
 
-char hexEscape(char **src)
-
+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);
+  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;
+  return (char) value;
 }
+
 /*------------------------------------------------------------------*/
 /* 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                   */
 /*------------------------------------------------------------------*/
 
-char octalEscape (char **str) {
+unsigned char octalEscape (char **str) {
   int digits;
   unsigned value=0;
 
@@ -595,7 +653,7 @@ strVal (char *s)
   SPEC_NOUN (val->etype) = V_CHAR;
   SPEC_SCLS (val->etype) = S_LITERAL;
 
-  SPEC_CVAL (val->etype).v_char = Safe_calloc (1, strlen (s) + 1);
+  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;
@@ -672,7 +730,7 @@ copyValueChain (value * src)
 }
 
 /*------------------------------------------------------------------*/
-/* copyValue - copies contents of a vlue to a fresh one             */
+/* copyValue - copies contents of a value to a fresh one            */
 /*------------------------------------------------------------------*/
 value *
 copyValue (value * src)
@@ -754,20 +812,20 @@ charVal (char *s)
        case '5' :
        case '6' :
        case '7' :
-         SPEC_CVAL (val->type).v_int = octalEscape(&s);
+         SPEC_CVAL (val->type).v_uint = octalEscape(&s);
          break;
 
        case 'x':
-         SPEC_CVAL (val->type).v_int = hexEscape(&s) ;
+         SPEC_CVAL (val->type).v_uint = hexEscape(&s) ;
          break;
 
        default:
-         SPEC_CVAL (val->type).v_int = *s;
+         SPEC_CVAL (val->type).v_uint = (unsigned char)*s;
          break;
        }
     }
   else                         /* not a backslash */
-    SPEC_CVAL (val->type).v_int = *s;
+    SPEC_CVAL (val->type).v_int = (unsigned char)*s;
 
   return val;
 }
@@ -827,7 +885,7 @@ floatFromVal (value * val)
 
 
 /*------------------------------------------------------------------*/
-/* valUnaryPM - dones the unary +/- operation on a constant         */
+/* valUnaryPM - does the unary +/- operation on a constant          */
 /*------------------------------------------------------------------*/
 value *
 valUnaryPM (value * val)
@@ -853,7 +911,6 @@ valUnaryPM (value * val)
        }
     }
   return val;
-
 }
 
 /*------------------------------------------------------------------*/
@@ -919,7 +976,7 @@ valMult (value * lval, value * rval)
   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_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))
@@ -945,7 +1002,7 @@ valMult (value * lval, value * rval)
              (int) floatFromVal (rval);
        }
     }
-  return val;
+  return cheapestVal(val);
 }
 
 /*------------------------------------------------------------------*/
@@ -969,7 +1026,7 @@ valDiv (value * lval, value * rval)
   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
                           IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
   SPEC_SCLS (val->etype) = S_LITERAL;
-  SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
+  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))
@@ -979,7 +1036,8 @@ valDiv (value * lval, value * rval)
       if (SPEC_LONG (val->type))
        {
          if (SPEC_USIGN (val->type))
-           SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) /
+           SPEC_CVAL (val->type).v_ulong = 
+             (unsigned long) floatFromVal (lval) /
              (unsigned long) floatFromVal (rval);
          else
            SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) /
@@ -990,22 +1048,13 @@ valDiv (value * lval, value * rval)
          if (SPEC_USIGN (val->type)) {
            SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) /
              (unsigned) floatFromVal (rval);
-           if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-               (SPEC_CVAL (val->type).v_uint <=255)) {
-             SPEC_NOUN (val->type) = V_CHAR;
-           }
          } else {
            SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) /
              (int) floatFromVal (rval);
-           if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-               (SPEC_CVAL (val->type).v_int >=-128) &&
-               (SPEC_CVAL (val->type).v_int <=127)) {
-             SPEC_NOUN (val->type) = V_CHAR;
-           }
          }
        }
     }
-  return val;
+  return cheapestVal(val);
 }
 
 /*------------------------------------------------------------------*/
@@ -1022,7 +1071,7 @@ valMod (value * lval, value * rval)
   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_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))
@@ -1039,22 +1088,13 @@ valMod (value * lval, value * rval)
       if (SPEC_USIGN (val->type)) {
        SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) %
          (unsigned) floatFromVal (rval);
-       if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-           (SPEC_CVAL (val->type).v_uint <=255)) {
-         SPEC_NOUN (val->type) = V_CHAR;
-       }
       } else {
        SPEC_CVAL (val->type).v_int = (unsigned) floatFromVal (lval) %
          (unsigned) floatFromVal (rval);
-       if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-           (SPEC_CVAL (val->type).v_int >=-128) &&
-           (SPEC_CVAL (val->type).v_int <=127)) {
-         SPEC_NOUN (val->type) = V_CHAR;
-       }
       }
     }
 
-  return val;
+  return cheapestVal(val);
 }
 
 /*------------------------------------------------------------------*/
@@ -1072,7 +1112,11 @@ valPlus (value * lval, value * rval)
   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_USIGN (val->type) = 
+    SPEC_USIGN (lval->etype) &&
+    SPEC_USIGN (rval->etype) &&
+    (floatFromVal(lval)+floatFromVal(rval))>=0;
+    
   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
 
   if (IS_FLOAT (val->type))
@@ -1093,22 +1137,13 @@ valPlus (value * lval, value * rval)
          if (SPEC_USIGN (val->type)) {
            SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) +
              (unsigned) floatFromVal (rval);
-           if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-               (SPEC_CVAL (val->type).v_uint <=255)) {
-             SPEC_NOUN (val->type) = V_CHAR;
-           }
          } else {
            SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) +
              (int) floatFromVal (rval);
-           if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-               (SPEC_CVAL (val->type).v_int >=-128) &&
-               (SPEC_CVAL (val->type).v_int <=127)) {
-             SPEC_NOUN (val->type) = V_CHAR;
-           }
          }
        }
     }
-  return val;
+  return cheapestVal(val);
 }
 
 /*------------------------------------------------------------------*/
@@ -1126,7 +1161,11 @@ valMinus (value * lval, value * rval)
   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_USIGN (val->type) = 
+    SPEC_USIGN (lval->etype) &&
+    SPEC_USIGN (rval->etype) &&
+    (floatFromVal(lval)-floatFromVal(rval))>=0;
+
   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
 
   if (IS_FLOAT (val->type))
@@ -1149,21 +1188,13 @@ valMinus (value * lval, value * rval)
          if (SPEC_USIGN (val->type)) {
            SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) -
              (unsigned) floatFromVal (rval);
-           if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-               (SPEC_CVAL (val->type).v_uint <=255)) {
-             SPEC_NOUN (val->type) = V_CHAR;
-           }
          } else {
-           SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) - (int) floatFromVal (rval);
-           if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-               (SPEC_CVAL (val->type).v_int >=-128) &&
-               (SPEC_CVAL (val->type).v_int <=127)) {
-             SPEC_NOUN (val->type) = V_CHAR;
-           }
+           SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) - 
+             (int) floatFromVal (rval);
          }
        }
     }
-  return val;
+  return cheapestVal(val);
 }
 
 /*------------------------------------------------------------------*/
@@ -1178,7 +1209,7 @@ valShift (value * lval, value * rval, int lr)
   val = newValue ();
   val->type = val->etype = newIntLink ();
   SPEC_SCLS (val->type) = S_LITERAL;   /* will remain literal */
-  SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
+  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))
@@ -1198,23 +1229,14 @@ valShift (value * lval, value * rval, int lr)
        SPEC_CVAL (val->type).v_uint = lr ? 
          (unsigned) floatFromVal (lval) << (unsigned) floatFromVal (rval) :\
          (unsigned) floatFromVal (lval) >> (unsigned) floatFromVal (rval);
-       if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-           (SPEC_CVAL (val->type).v_uint <=255)) {
-         SPEC_NOUN (val->type) = V_CHAR;
-       }
       } else {
        SPEC_CVAL (val->type).v_int = lr ?
          (int) floatFromVal (lval) << (int) floatFromVal (rval) : \
          (int) floatFromVal (lval) >> (int) floatFromVal (rval);
-       if (/* IS_CHAR (lval->etype) && IS_CHAR (rval->etype) && */
-           (SPEC_CVAL (val->type).v_int >=-128) &&
-           (SPEC_CVAL (val->type).v_int <=127)) {
-         SPEC_NOUN (val->type) = V_CHAR;
-       }
       }
     }
 
-  return val;
+  return cheapestVal(val);
 }
 
 /*------------------------------------------------------------------*/
@@ -1229,7 +1251,8 @@ valCompare (value * lval, value * rval, int ctype)
   val = newValue ();
   val->type = val->etype = newCharLink ();
   val->type->class = SPECIFIER;
-  SPEC_NOUN (val->type) = V_INT;       /* type is int */
+  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)
@@ -1342,7 +1365,7 @@ valBitwise (value * lval, value * rval, int op)
       break;
     }
 
-  return val;
+  return cheapestVal(val);
 }
 
 /*------------------------------------------------------------------*/
@@ -1358,6 +1381,7 @@ valLogicAndOr (value * lval, value * rval, int op)
   val->type = val->etype = newCharLink ();
   val->type->class = SPECIFIER;
   SPEC_SCLS (val->type) = S_LITERAL;   /* will remain literal */
+  SPEC_USIGN (val->type) = 0;
 
   switch (op)
     {
@@ -1410,9 +1434,17 @@ valCastLiteral (sym_link * dtype, double fval)
       else
        {
          if (SPEC_USIGN (val->etype))
-           SPEC_CVAL (val->etype).v_uint = (unsigned int) fval;
+           if (SPEC_NOUN (val->etype)==V_CHAR) {
+             SPEC_CVAL (val->etype).v_uint = (unsigned char)fval;
+           } else {
+             SPEC_CVAL (val->etype).v_uint = (unsigned short)fval;
+           }
          else
-           SPEC_CVAL (val->etype).v_int = (int) fval;
+           if (SPEC_NOUN (val->etype)==V_CHAR) {
+             SPEC_CVAL (val->etype).v_int = (char)fval;
+           } else {
+             SPEC_CVAL (val->etype).v_int = (short)fval;
+           }
        }
     }
   return val;