From 6fc94eb37545261447c1bb11270c0dc1fc462667 Mon Sep 17 00:00:00 2001 From: ceriel Date: Thu, 18 Mar 1993 13:24:20 +0000 Subject: [PATCH] Improved constant arithmetic: had several bugs --- lang/cem/cpp.ansi/LLlex.c | 33 ++++++++- lang/cem/cpp.ansi/LLlex.h | 8 ++- lang/cem/cpp.ansi/ch3bin.c | 127 ++++++++++++++++++++++++++++----- lang/cem/cpp.ansi/ch3mon.c | 4 +- lang/cem/cpp.ansi/domacro.c | 2 +- lang/cem/cpp.ansi/error.c | 12 ++-- lang/cem/cpp.ansi/expression.g | 67 +++++++++-------- lang/cem/cpp.ansi/init.c | 1 + lang/cem/cpp.ansi/input.c | 1 + lang/cem/cpp.ansi/preprocess.c | 6 +- lang/cem/cpp.ansi/replace.c | 17 +++-- 11 files changed, 212 insertions(+), 66 deletions(-) diff --git a/lang/cem/cpp.ansi/LLlex.c b/lang/cem/cpp.ansi/LLlex.c index 26e039fbb..69b4c6faf 100644 --- a/lang/cem/cpp.ansi/LLlex.c +++ b/lang/cem/cpp.ansi/LLlex.c @@ -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; diff --git a/lang/cem/cpp.ansi/LLlex.h b/lang/cem/cpp.ansi/LLlex.h index d3bd91574..52d372720 100644 --- a/lang/cem/cpp.ansi/LLlex.h +++ b/lang/cem/cpp.ansi/LLlex.h @@ -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; diff --git a/lang/cem/cpp.ansi/ch3bin.c b/lang/cem/cpp.ansi/ch3bin.c index d23e98fed..59ce937ae 100644 --- a/lang/cem/cpp.ansi/ch3bin.c +++ b/lang/cem/cpp.ansi/ch3bin.c @@ -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; } diff --git a/lang/cem/cpp.ansi/ch3mon.c b/lang/cem/cpp.ansi/ch3mon.c index 5fd081d17..869d5e16d 100644 --- a/lang/cem/cpp.ansi/ch3mon.c +++ b/lang/cem/cpp.ansi/ch3mon.c @@ -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 '~': diff --git a/lang/cem/cpp.ansi/domacro.c b/lang/cem/cpp.ansi/domacro.c index 802ad6f76..236587633 100644 --- a/lang/cem/cpp.ansi/domacro.c +++ b/lang/cem/cpp.ansi/domacro.c @@ -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)) { diff --git a/lang/cem/cpp.ansi/error.c b/lang/cem/cpp.ansi/error.c index f970d60dc..922a4f4a6 100644 --- a/lang/cem/cpp.ansi/error.c +++ b/lang/cem/cpp.ansi/error.c @@ -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 { diff --git a/lang/cem/cpp.ansi/expression.g b/lang/cem/cpp.ansi/expression.g index d1076b298..384ea18a6 100644 --- a/lang/cem/cpp.ansi/expression.g +++ b/lang/cem/cpp.ansi/expression.g @@ -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) ; diff --git a/lang/cem/cpp.ansi/init.c b/lang/cem/cpp.ansi/init.c index 024ab23a2..fecf5b57c 100644 --- a/lang/cem/cpp.ansi/init.c +++ b/lang/cem/cpp.ansi/init.c @@ -32,6 +32,7 @@ struct mkey { }; char *strcpy(); +char *sprint(); init_pp() { diff --git a/lang/cem/cpp.ansi/input.c b/lang/cem/cpp.ansi/input.c index a38d67f3c..7485a6855 100644 --- a/lang/cem/cpp.ansi/input.c +++ b/lang/cem/cpp.ansi/input.c @@ -12,6 +12,7 @@ #define INP_VAR finfo struct file_info finfo; #include +#include char * getwdir(fn) diff --git a/lang/cem/cpp.ansi/preprocess.c b/lang/cem/cpp.ansi/preprocess.c index eb3f76d11..1a3a24e8b 100644 --- a/lang/cem/cpp.ansi/preprocess.c +++ b/lang/cem/cpp.ansi/preprocess.c @@ -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 \ diff --git a/lang/cem/cpp.ansi/replace.c b/lang/cem/cpp.ansi/replace.c index e5aa73d15..f2470f96f 100644 --- a/lang/cem/cpp.ansi/replace.c +++ b/lang/cem/cpp.ansi/replace.c @@ -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) {