Improved constant arithmetic: had several bugs

This commit is contained in:
ceriel 1993-03-18 13:24:20 +00:00
parent eb375db4d6
commit 6fc94eb375
11 changed files with 212 additions and 66 deletions

View file

@ -259,7 +259,10 @@ garbage:
} }
case STNUM: /* a numeric constant */ case STNUM: /* a numeric constant */
{ /* it may only be an integer 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 /* Since the preprocessor only knows integers and has
* nothing to do with ellipsis we just return when the * nothing to do with ellipsis we just return when the
@ -279,11 +282,35 @@ garbage:
} }
while ((vch = val_in_base(ch, base)) >= 0) { 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(); 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(); 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(); UnGetChar();
ptok->tk_val = val; ptok->tk_val = val;
return ptok->tk_symb = INTEGER; return ptok->tk_symb = INTEGER;

View file

@ -15,7 +15,10 @@ struct token {
int tok_symb; /* the token itself */ int tok_symb; /* the token itself */
union { union {
char *tok_str; char *tok_str;
arith tok_val; /* for INTEGER */ struct {
int tok_unsigned;
arith tok_val; /* for INTEGER */
} tok_int;
} tok_data; } tok_data;
}; };
@ -23,7 +26,8 @@ struct token {
#define tk_symb tok_symb #define tk_symb tok_symb
#define tk_str tok_data.tok_str #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; extern struct token dot;

View file

@ -8,22 +8,89 @@
#include "Lpars.h" #include "Lpars.h"
#include "arith.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; register arith *pval, val;
int oper; int oper, is_uns, *pis_uns;
{ {
if (is_uns) *pis_uns = 1;
switch (oper) { switch (oper) {
case '%':
if (val == 0)
error("%% by 0");
else
*pval = *pval % val;
break;
case '/': case '/':
if (val == 0) if (val == 0) {
error("/ by 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; *pval = *pval / val;
}
break; break;
case '*': case '*':
*pval = *pval * val; *pval = *pval * val;
@ -38,19 +105,44 @@ ch3bin(pval, oper, val)
*pval = *pval << val; *pval = *pval << val;
break; break;
case RIGHT: 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; break;
case '<': case '<':
*pval = (*pval < val); { arith tmp = *pval; *pval = val; val = tmp; }
break; /* fall through */
case '>': 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; break;
case LESSEQ: case LESSEQ:
*pval = (*pval <= val); { arith tmp = *pval; *pval = val; val = tmp; }
break; /* fall through */
case GREATEREQ: 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; break;
case EQUAL: case EQUAL:
*pval = (*pval == val); *pval = (*pval == val);
@ -74,6 +166,7 @@ ch3bin(pval, oper, val)
*pval = (*pval || val); *pval = (*pval || val);
break; break;
case ',': case ',':
*pis_uns = is_uns;
*pval = val; *pval = val;
break; break;
} }

View file

@ -8,8 +8,10 @@
#include "Lpars.h" #include "Lpars.h"
#include "arith.h" #include "arith.h"
ch3mon(oper, pval) /*ARGSUSED2*/
ch3mon(oper, pval, puns)
register arith *pval; register arith *pval;
int *puns;
{ {
switch (oper) { switch (oper) {
case '~': case '~':

View file

@ -665,7 +665,7 @@ get_text(formals, length)
c = GetChar(); 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'; *repl->r_ptr = '\0';
while ((c != EOI) && (class(c) != STNL)) { while ((c != EOI) && (class(c) != STNL)) {
if (BLANK(c)) { if (BLANK(c)) {

View file

@ -23,12 +23,12 @@ err_hdr(s)
char *s; char *s;
{ {
if (FileName) { 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); else fprint(ERROUT, s);
} }
/*VARARGS1*/ /*VARARGS*/
error(va_alist) error(va_alist)
va_dcl va_dcl
{ {
@ -44,7 +44,7 @@ error(va_alist)
va_end(ap); va_end(ap);
} }
/*VARARGS1*/ /*VARARGS*/
warning(va_alist) warning(va_alist)
va_dcl va_dcl
{ {
@ -59,7 +59,7 @@ warning(va_alist)
va_end(ap); va_end(ap);
} }
/*VARARGS1*/ /*VARARGS*/
strict(va_alist) strict(va_alist)
va_dcl va_dcl
{ {
@ -74,7 +74,7 @@ strict(va_alist)
va_end(ap); va_end(ap);
} }
/*VARARGS1*/ /*VARARGS*/
crash(va_alist) crash(va_alist)
va_dcl va_dcl
{ {
@ -90,7 +90,7 @@ crash(va_alist)
sys_stop(S_ABORT); sys_stop(S_ABORT);
} }
/*VARARGS1*/ /*VARARGS*/
fatal(va_alist) fatal(va_alist)
va_dcl va_dcl
{ {

View file

@ -15,70 +15,75 @@ extern arith ifval;
} }
if_expression if_expression
{ int is_unsigned = 0; }
: :
constant_expression(&ifval) constant_expression(&ifval, &is_unsigned)
; ;
/* 7.1 */ /* 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;} {int oper;}
: :
unop(&oper) unop(&oper)
unary(pval) unary(pval, is_uns)
{ ch3mon(oper, pval); } { ch3mon(oper, pval, is_uns); }
| |
primary(pval) primary(pval, is_uns)
; ;
binary_expression(int maxrank; arith *pval;) binary_expression(int maxrank; arith *pval; int *is_uns;)
{int oper; arith val1;} {int oper; arith val1; int u;}
: :
unary(pval) unary(pval, is_uns)
[%while (rank_of(DOT) <= maxrank) [%while (rank_of(DOT) <= maxrank)
binop(&oper) 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 */ /* 7.13 */
conditional_expression(arith *pval;) conditional_expression(arith *pval; int *is_uns)
{arith val1 = 0, val2 = 0;} {arith val1 = 0, val2 = 0; int u;}
: :
/* allow all binary operators */ /* 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) assignment_expression(&val2, &u)
{ *pval = (*pval ? val1 : val2); } { if (*pval) *pval = val1;
else { *pval = val2; *is_uns = u; }
}
]? ]?
; ;
/* 7.14 */ /* 7.14 */
assignment_expression(arith *pval;) assignment_expression(arith *pval; int *is_uns)
: :
conditional_expression(pval) conditional_expression(pval, is_uns)
; ;
/* 7.15 */ /* 7.15 */
expression(arith *pval;) expression(arith *pval; int *is_uns)
{arith val1;} {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;} {*oper = DOT;}
; ;
constant(arith *pval;) : constant(arith *pval; int *is_uns) :
INTEGER INTEGER
{*pval = dot.tk_val;} {*pval = dot.tk_val;
*is_uns = dot.tk_unsigned;
}
; ;
constant_expression (arith *pval;) : constant_expression (arith *pval; int *is_uns) :
assignment_expression(pval) assignment_expression(pval, is_uns)
; ;

View file

@ -32,6 +32,7 @@ struct mkey {
}; };
char *strcpy(); char *strcpy();
char *sprint();
init_pp() init_pp()
{ {

View file

@ -12,6 +12,7 @@
#define INP_VAR finfo #define INP_VAR finfo
struct file_info finfo; struct file_info finfo;
#include <inp_pkg.body> #include <inp_pkg.body>
#include <alloc.h>
char * char *
getwdir(fn) getwdir(fn)

View file

@ -25,6 +25,8 @@ char bits[128];
#endif #endif
extern int InputLevel; extern int InputLevel;
extern char *sprint();
Xflush() Xflush()
{ {
sys_write(STDOUT, _obuf, OBUFSIZE); sys_write(STDOUT, _obuf, OBUFSIZE);
@ -46,7 +48,7 @@ static int pragma_nr;
do_pragma() do_pragma()
{ {
register int size = ITEXTSIZE; register int size = ITEXTSIZE;
char *cur_line = Malloc(size); char *cur_line = Malloc((unsigned)size);
register char *c_ptr = cur_line; register char *c_ptr = cur_line;
register int c = GetChar(); register int c = GetChar();
register int delim = 0; register int delim = 0;
@ -136,7 +138,7 @@ preprocess(fn)
register char *p = Xbuf; \ register char *p = Xbuf; \
sprint(Xbuf, "%s %d \"%s\"\n", \ sprint(Xbuf, "%s %d \"%s\"\n", \
LINE_PREFIX, \ LINE_PREFIX, \
LineNumber, \ (int)LineNumber, \
FileName); \ FileName); \
op--; \ op--; \
while (op >= _obuf \ while (op >= _obuf \

View file

@ -41,7 +41,7 @@ replace(idf)
if (idf->id_macro->mc_flag & NOREPLACE) if (idf->id_macro->mc_flag & NOREPLACE)
return 0; return 0;
repl = new_repl(); 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_args = new_args();
repl->r_idf = idf; repl->r_idf = idf;
if (!expand_macro(repl, idf)) if (!expand_macro(repl, idf))
@ -206,8 +206,8 @@ expand_defined(repl)
newarg(args) newarg(args)
struct args *args; struct args *args;
{ {
args->a_expptr = args->a_expbuf = Malloc(args->a_expsize = ARGBUF); args->a_expptr = args->a_expbuf = Malloc((unsigned)(args->a_expsize = ARGBUF));
args->a_rawptr = args->a_rawbuf = Malloc(args->a_rawsize = ARGBUF); args->a_rawptr = args->a_rawbuf = Malloc((unsigned)(args->a_rawsize = ARGBUF));
} }
getactuals(repl, idf) getactuals(repl, idf)
@ -302,14 +302,23 @@ actual(repl)
register int ch = 0; register int ch = 0;
register int level = 0, nostashraw = 0; register int level = 0, nostashraw = 0;
int lastch; int lastch;
static int Unstacked_missed;
while (1) { while (1) {
lastch = ch; lastch = ch;
ch = GetChar(); ch = GetChar();
if (nostashraw
&& nostashraw >= Unstacked_missed) {
nostashraw -= Unstacked_missed;
Unstacked_missed = 0;
}
if (Unstacked) { if (Unstacked) {
nostashraw -= Unstacked; nostashraw -= Unstacked;
if (nostashraw < 0) nostashraw = 0; if (nostashraw < 0) {
Unstacked_missed = -nostashraw;
nostashraw = 0;
}
EnableMacros(); EnableMacros();
} }
if (class(ch) == STIDF || class(ch) == STELL) { if (class(ch) == STIDF || class(ch) == STELL) {