Improved constant arithmetic: had several bugs
This commit is contained in:
parent
eb375db4d6
commit
6fc94eb375
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 '~':
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
;
|
||||
|
|
|
@ -32,6 +32,7 @@ struct mkey {
|
|||
};
|
||||
|
||||
char *strcpy();
|
||||
char *sprint();
|
||||
|
||||
init_pp()
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define INP_VAR finfo
|
||||
struct file_info finfo;
|
||||
#include <inp_pkg.body>
|
||||
#include <alloc.h>
|
||||
|
||||
char *
|
||||
getwdir(fn)
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue