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 */
{ /* 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;

View file

@ -15,7 +15,10 @@ struct token {
int tok_symb; /* the token itself */
union {
char *tok_str;
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;

View 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;
}

View 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 '~':

View 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)) {

View 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
{

View 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)
;

View file

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

View file

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

View 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 \

View 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) {