Improved constant arithmetic: had several bugs
authorceriel <none@none>
Thu, 18 Mar 1993 13:24:20 +0000 (13:24 +0000)
committerceriel <none@none>
Thu, 18 Mar 1993 13:24:20 +0000 (13:24 +0000)
lang/cem/cpp.ansi/LLlex.c
lang/cem/cpp.ansi/LLlex.h
lang/cem/cpp.ansi/ch3bin.c
lang/cem/cpp.ansi/ch3mon.c
lang/cem/cpp.ansi/domacro.c
lang/cem/cpp.ansi/error.c
lang/cem/cpp.ansi/expression.g
lang/cem/cpp.ansi/init.c
lang/cem/cpp.ansi/input.c
lang/cem/cpp.ansi/preprocess.c
lang/cem/cpp.ansi/replace.c

index 26e039f..69b4c6f 100644 (file)
@@ -259,7 +259,10 @@ garbage:
        }
        case STNUM:                             /* a numeric constant   */
        {                       /* it may only be an integer constant */
-               register int base = 10, val = 0, vch;
+               register int base = 10, vch;
+               register arith val = 0;
+               int ovfl = 0;
+               arith ubound = ~(1<<(sizeof(arith)*8-1))/(base/2);
 
                /* Since the preprocessor only knows integers and has
                 * nothing to do with ellipsis we just return when the
@@ -279,11 +282,35 @@ garbage:
 
                }
                while ((vch = val_in_base(ch, base)) >= 0) {
-                       val = val * base + vch;         /* overflow? nah */
+                       if (val < 0 || val > ubound) ovfl++;
+                       val *= base;
+                       if (val < 0 && val + vch >= 0) ovfl++;
+                       val += vch;
                        ch = GetChar();
                }
-               while (ch == 'l' || ch == 'L' || ch == 'u' || ch == 'U')
+               ptok->tk_unsigned = 0;
+               if (ch == 'u' || ch == 'U') {
+                       ptok->tk_unsigned = 1;
                        ch = GetChar();
+                       if (ch == 'l' || ch == 'L') {
+                               ch = GetChar();
+                       }
+               }
+               else if (ch == 'l' || ch == 'L') {
+                       ch = GetChar();
+                       if (ch == 'u' || ch == 'U') {
+                               ptok->tk_unsigned = 1;
+                               ch = GetChar();
+                       }
+               }
+               if (ovfl) {
+                       warning("overflow in constant");
+                       ptok->tk_unsigned = 1;
+               }
+               else if (val < 0) {
+                       /* give warning??? */
+                       ptok->tk_unsigned = 1;
+               }
                UnGetChar();
                ptok->tk_val = val;
                return ptok->tk_symb = INTEGER;
index d3bd915..52d3727 100644 (file)
@@ -15,7 +15,10 @@ struct token {
        int tok_symb;           /* the token itself */
        union   {
                char *tok_str;
-               arith tok_val;          /* for INTEGER */
+               struct {
+                       int tok_unsigned;
+                       arith tok_val;          /* for INTEGER */
+               } tok_int;
        } tok_data;
 };
 
@@ -23,7 +26,8 @@ struct token  {
 
 #define tk_symb        tok_symb
 #define tk_str tok_data.tok_str
-#define tk_val tok_data.tok_val
+#define tk_val tok_data.tok_int.tok_val
+#define tk_unsigned tok_data.tok_int.tok_unsigned
 
 extern struct token dot;
 
index d23e98f..59ce937 100644 (file)
@@ -8,22 +8,89 @@
 #include       "Lpars.h"
 #include       "arith.h"
 
-ch3bin(pval, oper, val)
+#define arith_sign (1 << (sizeof(arith)*8-1))
+
+ch3bin(pval, pis_uns, oper, val, is_uns)
        register arith *pval, val;
-       int oper;
+       int oper, is_uns, *pis_uns;
 {
+       if (is_uns) *pis_uns = 1;
        switch (oper)   {
-       case '%':
-               if (val == 0)
-                       error("%% by 0");
-               else
-                       *pval = *pval % val;
-               break;
        case '/':
-               if (val == 0)
+               if (val == 0) {
                        error("/ by 0");
-               else
+                       break;
+               }
+               if (*pis_uns) {
+#ifdef UNSIGNED_ARITH
+                       *pval /= (UNSIGNED_ARITH) val;
+#else
+                       /*      this is more of a problem than you might
+                               think on C compilers which do not have
+                               unsigned arith (== long (probably)).
+                       */
+                       if (val & arith_sign)   {/* val > max_arith */
+                               *pval = ! (*pval >= 0 || *pval < val);
+                               /*      this is the unsigned test
+                                       *pval < val for val > max_arith
+                               */
+                       }
+                       else    {               /* val <= max_arith */
+                               arith half, bit, hdiv, hrem, rem;
+
+                               half = (*pval >> 1) & ~arith_sign;
+                               bit = *pval & 01;
+                               /*      now *pval == 2 * half + bit
+                                       and half <= max_arith
+                                       and bit <= max_arith
+                               */
+                               hdiv = half / val;
+                               hrem = half % val;
+                               rem = 2 * hrem + bit;
+                               *pval = 2 * hdiv + (rem < 0 || rem >= val);
+                               /*      that is the unsigned compare
+                                       rem >= val for val <= max_arith
+                               */
+                       }
+#endif
+               }
+               else {
+                       *pval = *pval % val;
+               }
+               break;
+       case '%':
+               if (val == 0) {
+                       error("%% by 0");
+                       break;
+               }
+               if (*pis_uns) {
+#ifdef UNSIGNED_ARITH
+                       *pval %= (UNSIGNED_ARITH) val;
+#else
+                       if (val & arith_sign)   {/* val > max_arith */
+                               *pval = (*pval >= 0 || *pval < val) ? *pval : *pval - val;
+                               /*      this is the unsigned test
+                                       *pval < val for val > max_arith
+                               */
+                       }
+                       else    {               /* val <= max_arith */
+                               arith half, bit, hrem, rem;
+
+                               half = (*pval >> 1) & ~arith_sign;
+                               bit = *pval & 01;
+                               /*      now *pval == 2 * half + bit
+                                       and half <= max_arith
+                                       and bit <= max_arith
+                               */
+                               hrem = half % val;
+                               rem = 2 * hrem + bit;
+                               *pval = (rem < 0 || rem >= val) ? rem - val : rem;
+                       }
+#endif
+               }
+               else {
                        *pval = *pval / val;
+               }
                break;
        case '*':
                *pval = *pval * val;
@@ -38,19 +105,44 @@ ch3bin(pval, oper, val)
                *pval = *pval << val;
                break;
        case RIGHT:
-               *pval = *pval >> val;
+               if (val == 0) break;
+               if (*pis_uns) {
+                       *pval = (*pval >> 1) & ~arith_sign;
+                       *pval = *pval >> (val - 1);
+               }
+               else *pval = *pval >> val;
                break;
        case '<':
-               *pval = (*pval < val);
-               break;
+               {       arith tmp = *pval; *pval = val; val = tmp; }
+               /* fall through */
        case '>':
-               *pval = (*pval > val);
+               if (*pis_uns) {
+#ifdef UNSIGNED_ARITH
+                       *pval = (UNSIGNED_ARITH) *pval > (UNSIGNED_ARITH) val;
+#else
+                       *pval = (*pval & arith_sign ?
+                               (val & arith_sign ? *pval > val : 1) :
+                               (val & arith_sign ? 0 : *pval > val)
+                       );
+#endif
+               }
+               else    *pval = (*pval > val);
                break;
        case LESSEQ:
-               *pval = (*pval <= val);
-               break;
+               {       arith tmp = *pval; *pval = val; val = tmp; }
+               /* fall through */
        case GREATEREQ:
-               *pval = (*pval >= val);
+               if (*pis_uns) {
+#ifdef UNSIGNED_ARITH
+                       *pval = (UNSIGNED_ARITH) *pval >= (UNSIGNED_ARITH) val;
+#else
+                       *pval = (*pval & arith_sign ?
+                               (val & arith_sign ? *pval >= val : 1) :
+                               (val & arith_sign ? 0 : *pval >= val)
+                       );
+#endif
+               }
+               else    *pval = (*pval >= val);
                break;
        case EQUAL:
                *pval = (*pval == val);
@@ -74,6 +166,7 @@ ch3bin(pval, oper, val)
                *pval = (*pval || val);
                break;
        case ',':
+               *pis_uns = is_uns;
                *pval = val;
                break;
        }
index 5fd081d..869d5e1 100644 (file)
@@ -8,8 +8,10 @@
 #include       "Lpars.h"
 #include       "arith.h"
 
-ch3mon(oper, pval)
+/*ARGSUSED2*/
+ch3mon(oper, pval, puns)
        register arith *pval;
+       int *puns;
 {
        switch (oper)   {
        case '~':
index 802ad6f..2365876 100644 (file)
@@ -665,7 +665,7 @@ get_text(formals, length)
 
        c = GetChar();
 
-       repl->r_ptr = repl->r_text = Malloc(repl->r_size = ITEXTSIZE);
+       repl->r_ptr = repl->r_text = Malloc((unsigned)(repl->r_size = ITEXTSIZE));
        *repl->r_ptr = '\0';
        while ((c != EOI) && (class(c) != STNL)) {
                if (BLANK(c)) {
index f970d60..922a4f4 100644 (file)
@@ -23,12 +23,12 @@ err_hdr(s)
        char *s;
 {
        if (FileName) {
-               fprint(ERROUT, "\"%s\", line %d: %s", FileName, LineNumber, s);
+               fprint(ERROUT, "\"%s\", line %d: %s", FileName, (int)LineNumber, s);
        }
        else    fprint(ERROUT, s);
 }
 
-/*VARARGS1*/
+/*VARARGS*/
 error(va_alist)
        va_dcl
 {
@@ -44,7 +44,7 @@ error(va_alist)
        va_end(ap);
 }
 
-/*VARARGS1*/
+/*VARARGS*/
 warning(va_alist)
        va_dcl
 {
@@ -59,7 +59,7 @@ warning(va_alist)
        va_end(ap);
 }
 
-/*VARARGS1*/
+/*VARARGS*/
 strict(va_alist)
        va_dcl
 {
@@ -74,7 +74,7 @@ strict(va_alist)
        va_end(ap);
 }
 
-/*VARARGS1*/
+/*VARARGS*/
 crash(va_alist)
        va_dcl
 {
@@ -90,7 +90,7 @@ crash(va_alist)
        sys_stop(S_ABORT);
 }
 
-/*VARARGS1*/
+/*VARARGS*/
 fatal(va_alist)
        va_dcl
 {
index d1076b2..384ea18 100644 (file)
@@ -15,70 +15,75 @@ extern arith ifval;
 }
 
 if_expression
+{ int is_unsigned = 0; }
 :
-       constant_expression(&ifval)
+       constant_expression(&ifval, &is_unsigned)
 ;
 
 /* 7.1 */
-primary(arith *pval;)
+primary(arith *pval; int *is_uns;)
 :
-       constant(pval)
+       constant(pval, is_uns)
 |
-       '(' expression(pval) ')'
+       '(' expression(pval, is_uns) ')'
 ;
 
-unary(arith *pval;)
+unary(arith *pval; int *is_uns;)
        {int oper;}
 :
        unop(&oper)
-       unary(pval)
-       { ch3mon(oper, pval); }
+       unary(pval, is_uns)
+       { ch3mon(oper, pval, is_uns); }
 |
-       primary(pval)
+       primary(pval, is_uns)
 ;
 
-binary_expression(int maxrank; arith *pval;)
-       {int oper; arith val1;}
+binary_expression(int maxrank; arith *pval; int *is_uns;)
+       {int oper; arith val1; int u;}
 :
-       unary(pval)
+       unary(pval, is_uns)
        [%while (rank_of(DOT) <= maxrank)
                binop(&oper)
-               binary_expression(rank_of(oper)-1, &val1)
+               binary_expression(rank_of(oper)-1, &val1, &u)
                {
-                       ch3bin(pval, oper, val1);
+                       ch3bin(pval, is_uns, oper, val1, u);
                }
        ]*
 ;
 
 /* 7.13 */
-conditional_expression(arith *pval;)
-       {arith val1 = 0, val2 = 0;}
+conditional_expression(arith *pval; int *is_uns)
+       {arith val1 = 0, val2 = 0; int u;}
 :
        /* allow all binary operators */
-       binary_expression(rank_of('?') - 1, pval)
+       binary_expression(rank_of('?') - 1, pval, is_uns)
        [       '?'
-               expression(&val1)
+               expression(&val1, is_uns)
                ':'
-               assignment_expression(&val2)
-               { *pval = (*pval ? val1 : val2); }
+               assignment_expression(&val2, &u)
+               { if (*pval) *pval = val1;
+                 else { *pval = val2; *is_uns = u; }
+               }
        ]?
 ;
 
 /* 7.14 */
-assignment_expression(arith *pval;)
+assignment_expression(arith *pval; int *is_uns)
 :
-       conditional_expression(pval)
+       conditional_expression(pval, is_uns)
 ;
 
 /* 7.15 */
-expression(arith *pval;)
-       {arith val1;}
+expression(arith *pval; int *is_uns)
+       {arith val1;
+        int is_uns1;
+       }
 :
-       assignment_expression(pval)
+       assignment_expression(pval,is_uns)
        [       ','
-               assignment_expression(&val1)
+               assignment_expression(&val1, &is_uns1)
                {
-                       ch3bin(pval, ',', val1);
+                       ch3bin(pval, is_uns, ',', val1, is_uns1);
                }
        ]*
 ;
@@ -119,11 +124,13 @@ binop(int *oper;) :
        {*oper = DOT;}
 ;
 
-constant(arith *pval;) :
+constant(arith *pval; int *is_uns) :
        INTEGER
-       {*pval = dot.tk_val;}
+       {*pval = dot.tk_val;
+        *is_uns = dot.tk_unsigned;
+       }
 ;
 
-constant_expression (arith *pval;) :
-       assignment_expression(pval)
+constant_expression (arith *pval; int *is_uns) :
+       assignment_expression(pval, is_uns)
 ;
index 024ab23..fecf5b5 100644 (file)
@@ -32,6 +32,7 @@ struct mkey   {
 };
 
 char *strcpy();
+char *sprint();
 
 init_pp()
 {
index a38d67f..7485a68 100644 (file)
@@ -12,6 +12,7 @@
 #define INP_VAR                finfo
 struct file_info       finfo;
 #include <inp_pkg.body>
+#include <alloc.h>
 
 char *
 getwdir(fn)
index eb3f76d..1a3a24e 100644 (file)
@@ -25,6 +25,8 @@ char  bits[128];
 #endif
 extern int InputLevel;
 
+extern char *sprint();
+
 Xflush()
 {
        sys_write(STDOUT, _obuf, OBUFSIZE);
@@ -46,7 +48,7 @@ static int pragma_nr;
 do_pragma()
 {
        register int size = ITEXTSIZE;
-       char *cur_line = Malloc(size);
+       char *cur_line = Malloc((unsigned)size);
        register char *c_ptr = cur_line;
        register int c = GetChar();
        register int delim = 0;
@@ -136,7 +138,7 @@ preprocess(fn)
                                register char *p = Xbuf;                \
                                sprint(Xbuf, "%s %d \"%s\"\n",          \
                                        LINE_PREFIX,                    \
-                                       LineNumber,                     \
+                                       (int)LineNumber,                \
                                        FileName);                      \
                                op--;                                   \
                                while (op >= _obuf                      \
index e5aa73d..f2470f9 100644 (file)
@@ -41,7 +41,7 @@ replace(idf)
        if (idf->id_macro->mc_flag & NOREPLACE)
                return 0;
        repl = new_repl();
-       repl->r_ptr = repl->r_text = Malloc(repl->r_size = LAPBUF);
+       repl->r_ptr = repl->r_text = Malloc((unsigned)(repl->r_size = LAPBUF));
        repl->r_args = new_args();
        repl->r_idf = idf;
        if (!expand_macro(repl, idf))
@@ -206,8 +206,8 @@ expand_defined(repl)
 newarg(args)
        struct args *args;
 {
-       args->a_expptr = args->a_expbuf = Malloc(args->a_expsize = ARGBUF);
-       args->a_rawptr = args->a_rawbuf = Malloc(args->a_rawsize = ARGBUF);
+       args->a_expptr = args->a_expbuf = Malloc((unsigned)(args->a_expsize = ARGBUF));
+       args->a_rawptr = args->a_rawbuf = Malloc((unsigned)(args->a_rawsize = ARGBUF));
 }
 
 getactuals(repl, idf)
@@ -302,14 +302,23 @@ actual(repl)
        register int ch = 0;
        register int level = 0, nostashraw = 0;
        int lastch;
+       static int Unstacked_missed;
 
        while (1) {
                lastch = ch;
                ch = GetChar();
 
+               if (nostashraw 
+                   && nostashraw >= Unstacked_missed) {
+                       nostashraw -= Unstacked_missed;
+                       Unstacked_missed = 0;
+               }
                if (Unstacked) {
                        nostashraw -= Unstacked;
-                       if (nostashraw < 0) nostashraw = 0;
+                       if (nostashraw < 0) {
+                               Unstacked_missed = -nostashraw;
+                               nostashraw = 0;
+                       }
                        EnableMacros();
                }
                if (class(ch) == STIDF || class(ch) == STELL) {