Add long long literals like 123LL to ACK C.

For now, a long long literal must have the 'LL' or 'll' suffix.  A
literal without 'LL' or 'll' acts as before: it may become unsigned
long but not long long.  (For targets where int and long have the same
size, some literals change from unsigned int to unsigned long.)

Type `arith` may be too narrow for long long values.  Add a second
type `writh` for wide arithmetic, and change some variables from arith
to writh.  This may cause bugs if I forget to use writh, or if a
conversion from writh to arith overflows.  I mark some conversions
with (arith) or (writh) casts.

 - BigPars, SmallPars: Remove SPECIAL_ARITHMETICS.  This feature
   would change arith to a different type, but can't work, because it
   would conflict with definitions of arith in both <em_arith.h> and
   <flt_arith.h>.
 - LLlex.c: Understand 'LL' or 'll' suffix.  Cut size of constant when
   it overflows writh, not only when it overflows the target machine's
   types.  (This cut might not be necessary, because we might cut it
   again later.)  When picking signed long or unsigned long, check the
   target's long type, not the compiler's arith type; the old check
   for `val >= 0` was broken where sizeof(arith) > 4.
 - LLlex.h: Change struct token's tok_ival to writh, so it can hold a
   long long literal.
 - arith.c: Adjust to VL_VALUE being writh.  Don't convert between
   float and integer at compile-time if the integer might be too wide
   for <flt_arith.h>.  Add writh2str(), because writh might be too
   wide for long2str().
 - arith.h: Remove SPECIAL_ARITHMETICS.  Declare full_mask[] here,
   not in several *.c files.  Declare writh2str().
 - ch3.c, ch3bin.c, ch3mon.c, declarator.c, statement.g: Remove
   obsolete casts.  Adjust to VL_VALUE being writh.
 - conversion.c, stab.c: Don't declare full_mask[].
 - cstoper.c: Use writh for constant operations on VL_VALUE, and for
   full_mask[].
 - declar., field.c, ival.g: Add casts.
 - dumpidf.c: Need to #include "parameters.h" before checking DEBUG.
   Use writh2str, because "%ld" might not work.
 - eval.c, eval.h: Add casts.  Use writh when writing a wide constant
   in EM.
 - expr.c: Add and remove casts.  In fill_int_expr(), make expression
   from long long literal.  In chk_cst_expr(), allow long long as
   constant expression, so the compiler may accept `case 123LL:` in a
   switch statement.
 - expr.str: Change struct value's vl_value and struct expr's VL_VALUE
   to writh, so an expression may have a long long value at compile
   time.
 - statement.g: Remove obsolete casts.
 - switch.c, switch.str: Use writh in case entries for switch
   statements, so `switch (ll) {...}` with long long ll works.
 - tokenname.c: Add ULNGLNG so LLlex.c can use it for literals.
This commit is contained in:
George Koehler 2019-09-04 22:14:38 -04:00
parent 007a63d529
commit 15950f9c95
26 changed files with 258 additions and 180 deletions

View file

@ -117,11 +117,6 @@
/*#define NOBITFIELD 1 *//* if NOT defined, implement bitfields */ /*#define NOBITFIELD 1 *//* if NOT defined, implement bitfields */
!File: spec_arith.h
/* describes internal compiler arithmetics */
#undef SPECIAL_ARITHMETICS /* something different from native long */
!File: static.h !File: static.h
#define GSTATIC /* for large global "static" arrays */ #define GSTATIC /* for large global "static" arrays */

View file

@ -17,6 +17,7 @@
#include "Lpars.h" #include "Lpars.h"
#include "class.h" #include "class.h"
#include "sizes.h" #include "sizes.h"
#include "type.h" /* no_long_long() */
#include "error.h" #include "error.h"
#include "domacro.h" #include "domacro.h"
#include "specials.h" /* registration of special identifiers */ #include "specials.h" /* registration of special identifiers */
@ -37,7 +38,6 @@ int LexSave = 0; /* last character read by GetChar */
#define FLG_ESEEN 0x01 /* possibly a floating point number */ #define FLG_ESEEN 0x01 /* possibly a floating point number */
#define FLG_DOTSEEN 0x02 /* certainly a floating point number */ #define FLG_DOTSEEN 0x02 /* certainly a floating point number */
extern arith full_mask[];
#ifdef LINT #ifdef LINT
extern int lint_skip_comment; extern int lint_skip_comment;
@ -594,10 +594,12 @@ static void strflt2tok(char fltbuf[], struct token* ptok)
static void strint2tok(char intbuf[], struct token* ptok) static void strint2tok(char intbuf[], struct token* ptok)
{ {
register char* cp = intbuf; register char* cp = intbuf;
int base = 10; int base = 10, dig;
arith val = 0, dig, ubound; unsigned writh val = 0, ubound;
int uns_flg = 0, lng_flg = 0, malformed = 0, ovfl = 0; int uns_flg = 0, lng_flg = 0, lnglng_flg = 0;
int fund; int malformed = 0, ovfl = 0;
unsigned writh uint_mask, ulng_mask, ulnglng_mask;
int cut, fund;
assert(*cp != '-'); assert(*cp != '-');
if (*cp == '0') if (*cp == '0')
@ -611,11 +613,8 @@ static void strint2tok(char intbuf[], struct token* ptok)
else else
base = 8; base = 8;
} }
/* The upperbound will be the same as when computed with /* The upperbound checks if val * base would overflow. */
* max_unsigned_arith / base (since base is even). The problem here ubound = ~(unsigned writh)0 / base;
* is that unsigned arith is not accepted by all compilers.
*/
ubound = max_arith / (base / 2);
while (is_hex(*cp)) while (is_hex(*cp))
{ {
@ -626,10 +625,10 @@ static void strint2tok(char intbuf[], struct token* ptok)
} }
else else
{ {
if (val < 0 || val > ubound) if (val > ubound)
ovfl++; ovfl++;
val *= base; val *= base;
if (val < 0 && val + dig >= 0) if (val > val + dig)
ovfl++; ovfl++;
val += dig; val += dig;
} }
@ -639,7 +638,16 @@ static void strint2tok(char intbuf[], struct token* ptok)
while (*cp) while (*cp)
{ {
if (*cp == 'l' || *cp == 'L') if (*cp == 'l' || *cp == 'L')
{
if (*cp == *(cp + 1))
{
/* 'll' or 'LL' */
lnglng_flg++;
cp++;
}
else
lng_flg++; lng_flg++;
}
else if (*cp == 'u' || *cp == 'U') else if (*cp == 'u' || *cp == 'U')
uns_flg++; uns_flg++;
else else
@ -658,51 +666,83 @@ static void strint2tok(char intbuf[], struct token* ptok)
} }
else else
{ {
if (lng_flg > 1) if (lng_flg + lnglng_flg > 1)
lexerror("only one long suffix allowed"); lexerror("only one long suffix allowed");
if (uns_flg > 1) if (uns_flg > 1)
lexerror("only one unsigned suffix allowed"); lexerror("only one unsigned suffix allowed");
} }
/* Get masks like 0XFFFF, 0XFFFFFFFF as unsigned values. */
uint_mask = (unsigned writh)full_mask[(int)int_size];
ulng_mask = (unsigned writh)full_mask[(int)long_size];
if (lnglng_size < 0)
ulnglng_mask = 0;
else
ulnglng_mask = (unsigned writh)full_mask[(int)lnglng_size];
/* If a decimal literal with no suffix is too big for int
and long, then C89 tries unsigned long, but C99 tries
long long (WG14, Rationale for C99, C99RationaleV5.10.pdf,
6.4.4.1 Integer constants).
This compiler follows C89 when the literal has no
long long suffix.
*/
cut = 0;
if (ovfl) if (ovfl)
{ {
lexwarning("overflow in constant"); lexwarning("overflow in constant");
fund = ULONG; cut = 1; /* cut the size of the constant */
} }
else if (!lng_flg && (val & full_mask[(int)int_size]) == val) else if (!lng_flg && !lnglng_flg && (val & uint_mask) == val)
{
if (val >= 0 && val <= max_int)
{ {
if ((val & (uint_mask >> 1)) == val)
fund = INT; fund = INT;
}
else if (int_size == long_size)
{
fund = UNSIGNED;
}
else if (base == 10 && !uns_flg) else if (base == 10 && !uns_flg)
{
if ((val & (ulng_mask >> 1)) == val)
fund = LONG; fund = LONG;
else
fund = ULONG;
}
else else
fund = UNSIGNED; fund = UNSIGNED;
} }
else if ((val & full_mask[(int)long_size]) == val) else if (!lnglng_flg && (val & ulng_mask) == val)
{ {
if (val >= 0) if ((val & (ulng_mask >> 1)) == val)
fund = LONG; fund = LONG;
else else
fund = ULONG; fund = ULONG;
} }
else else if (lnglng_flg && (val & ulnglng_mask) == val)
{ /* sizeof(arith) is greater than long_size */ {
assert(arith_size > long_size); if ((val & (ulnglng_mask >> 1)) == val)
lexwarning("constant too large for target machine"); fund = LNGLNG;
/* cut the size to prevent further complaints */ else
val &= full_mask[(int)long_size]; fund = ULNGLNG;
fund = ULONG; }
} else if (lnglng_flg && no_long_long())
if (lng_flg) fund = ERRONEOUS;
else
{
assert(sizeof(val) > long_size ||
(lnglng_size >= 0 && sizeof(val) > lnglng_size));
lexwarning("constant too large for target machine");
cut = 1;
}
if (cut)
{
/* cut the size to prevent further complaints */
if (lnglng_flg)
{
fund = ULNGLNG;
val &= ulnglng_mask;
}
else
{ {
/* fund can't be INT */
if (fund == UNSIGNED)
fund = ULONG; fund = ULONG;
val &= ulng_mask;
}
} }
if (uns_flg) if (uns_flg)
{ {
@ -710,7 +750,9 @@ static void strint2tok(char intbuf[], struct token* ptok)
fund = UNSIGNED; fund = UNSIGNED;
else if (fund == LONG) else if (fund == LONG)
fund = ULONG; fund = ULONG;
else if (fund == LNGLNG)
fund = ULNGLNG;
} }
ptok->tk_fund = fund; ptok->tk_fund = fund;
ptok->tk_ival = val; ptok->tk_ival = (writh)val;
} }

View file

@ -26,7 +26,7 @@ struct token {
char *tok_bts; /* row of bytes */ char *tok_bts; /* row of bytes */
int tok_len; /* length of row of bytes */ int tok_len; /* length of row of bytes */
} tok_string; } tok_string;
arith tok_ival; /* for INTEGER */ writh tok_ival; /* for INTEGER */
char *tok_fval; /* for FLOATING */ char *tok_fval; /* for FLOATING */
} tok_data; } tok_data;
}; };

View file

@ -117,11 +117,6 @@
/*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */ /*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */
!File: spec_arith.h
/* describes internal compiler arithmetics */
#undef SPECIAL_ARITHMETICS /* something different from native long */
!File: static.h !File: static.h
#define GSTATIC /* for large global "static" arrays */ #define GSTATIC /* for large global "static" arrays */

View file

@ -371,8 +371,7 @@ int int2int(struct expr **expp, register struct type *tp)
unsigned int x = ~0; unsigned int x = ~0;
unsigned int y = -1; unsigned int y = -1;
*/ */
extern long full_mask[]; writh remainder = exp->VL_VALUE &
long remainder = exp->VL_VALUE &
~full_mask[(int)(tp->tp_size)]; ~full_mask[(int)(tp->tp_size)];
if (remainder == 0 || if (remainder == 0 ||
@ -389,6 +388,16 @@ int int2int(struct expr **expp, register struct type *tp)
return exp->ex_type->tp_fund; return exp->ex_type->tp_fund;
} }
static int fit4(writh val, int uns)
{
/* Does this value fit in 4 bytes? */
unsigned writh u = (unsigned writh)val;
if (!uns)
u += 0x80000000UL;
return (u & full_mask[4]) == u;
}
/* With compile-time constants, we don't set fp_used, since this is done /* With compile-time constants, we don't set fp_used, since this is done
* only when necessary in eval.c. * only when necessary in eval.c.
*/ */
@ -400,10 +409,10 @@ void int2float(register struct expr **expp, struct type *tp)
register struct expr *exp = *expp; register struct expr *exp = *expp;
int uns = exp->ex_type->tp_unsigned; int uns = exp->ex_type->tp_unsigned;
if (is_cp_cst(exp)) { if (is_cp_cst(exp) && fit4(exp->VL_VALUE, uns)) {
exp->ex_type = tp; exp->ex_type = tp;
exp->ex_class = Float; exp->ex_class = Float;
flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH), uns); flt_arith2flt((arith)exp->VL_VALUE, &(exp->FL_ARITH), uns);
} }
else { else {
fp_used = 1; fp_used = 1;
@ -420,22 +429,33 @@ void float2int(struct expr **expp, struct type *tp)
if (is_fp_cst(ex)) { if (is_fp_cst(ex)) {
arith ar = flt_flt2arith(&ex->FL_ARITH, tp->tp_unsigned); arith ar = flt_flt2arith(&ex->FL_ARITH, tp->tp_unsigned);
#ifdef NOTDEF
/* Historically, we always did the conversion at
compile time. This is now wrong if type arith is
too narrow for an 8-byte integer.
*/
if (flt_status == FLT_OVFL) if (flt_status == FLT_OVFL)
expr_warning(ex,"overflow in float to int conversion"); expr_warning(ex,"overflow in float to int conversion");
else if (flt_status == FLT_UNFL) else if (flt_status == FLT_UNFL)
expr_warning(ex,"underflow in float to unsigned conversion"); expr_warning(ex,"underflow in float to unsigned conversion");
#endif /* NOTDEF */
/* Now, we defer the conversion until run time
unless it fits in 4 bytes.
*/
if (flt_status != FLT_OVFL && flt_status != FLT_UNFL &&
fit4((writh)ar, tp->tp_unsigned)) {
ex->ex_type = tp; ex->ex_type = tp;
/* The following lines are copied from fill_int_expr */ /* The following lines are copied from fill_int_expr */
ex->ex_class = Value; ex->ex_class = Value;
ex->VL_CLASS = Const; ex->VL_CLASS = Const;
ex->VL_VALUE = ar; ex->VL_VALUE = (writh)ar;
cut_size(ex); cut_size(ex);
} else { return;
}
}
fp_used = 1; fp_used = 1;
*expp = arith2arith(tp, FLOAT2INT, ex); *expp = arith2arith(tp, FLOAT2INT, ex);
} }
}
void float2float(register struct expr **expp, struct type *tp) void float2float(register struct expr **expp, struct type *tp)
{ {
@ -640,3 +660,25 @@ void switch_sign_fp(register struct expr *expr)
{ {
flt_umin(&(expr->FL_ARITH)); flt_umin(&(expr->FL_ARITH));
} }
char *writh2str(writh val, int uns)
{
/* Converts val to a decimal string, like
long2str(val, 10), but allows wider values.
*/
static char buf[NUMSIZE + 1];
char *cp = &buf[NUMSIZE + 1];
int negative = (!uns && val < 0);
unsigned writh u = (unsigned writh)val;
if (negative)
u = -u;
*--cp = '\0';
do {
*--cp = '0' + (u % 10);
u /= 10;
} while (u != 0);
if (negative)
*--cp = '-';
return cp;
}

View file

@ -5,30 +5,25 @@
/* $Id$ */ /* $Id$ */
/* COMPILER ARITHMETIC */ /* COMPILER ARITHMETIC */
/* Normally the compiler does its internal arithmetics in longs /* The compiler uses 2 types, arith and writh, for its internal
native to the source machine, which is always good for local arithmetic. Type arith is normally long, and may be too
compilations, and generally OK too for cross compilations narrow for long long values. We can't change arith to a wider
downwards and sidewards. For upwards cross compilation and type, because both <em_arith.h> (pulled by <em.h>) and
to save storage on small machines, SPECIAL_ARITHMETICS will <flt_arith.h> define arith.
be handy.
Type writh (wide arithmetic) is for values that might not fit
in arith. Normally writh is the long long native to the
source machine, which is always good for local compilations,
and generally OK too for cross compilations downwards and
sidewards.
*/ */
#ifndef ARITH_H_ #ifndef ARITH_H_
#define ARITH_H_ #define ARITH_H_
#include "parameters.h"
#ifndef SPECIAL_ARITHMETICS
#include <em_arith.h> /* obtain definition of "arith" */ #include <em_arith.h> /* obtain definition of "arith" */
#include <flt_arith.h>
#else /* SPECIAL_ARITHMETICS */ #define writh long long
/* The compiler also uses "unsigned writh". */
/* All preprocessor arithmetic should be done in longs.
*/
#define arith long /* dummy */
#endif /* SPECIAL_ARITHMETICS */
struct expr; struct expr;
struct type; struct type;
@ -37,6 +32,8 @@ struct type;
#define arith_sign ((arith) 1 << (arith_size * 8 - 1)) #define arith_sign ((arith) 1 << (arith_size * 8 - 1))
#define max_arith (~arith_sign) #define max_arith (~arith_sign)
extern writh full_mask[]; /* cstoper.c */
void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p); void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p);
void relbalance(register struct expr **e1p, int oper, register struct expr **e2p); void relbalance(register struct expr **e1p, int oper, register struct expr **e2p);
void ch3pointer(struct expr **expp, int oper, register struct type *tp); void ch3pointer(struct expr **expp, int oper, register struct type *tp);
@ -57,5 +54,6 @@ void any2opnd(register struct expr **expp, int oper);
void any2parameter(register struct expr **expp); void any2parameter(register struct expr **expp);
void field2arith(register struct expr **expp); void field2arith(register struct expr **expp);
void switch_sign_fp(register struct expr *expr); void switch_sign_fp(register struct expr *expr);
char *writh2str(writh val, int uns);
#endif /* ARITH_H_ */ #endif /* ARITH_H_ */

View file

@ -320,7 +320,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp)
} }
if (oldtp->tp_up->tp_fund == VOID if (oldtp->tp_up->tp_fund == VOID
&& is_cp_cst(exp) && is_cp_cst(exp)
&& exp->VL_VALUE == (arith)0) && exp->VL_VALUE == 0)
break; /* switch */ break; /* switch */
} }
/* falltrough */ /* falltrough */
@ -366,7 +366,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp)
case NOTEQUAL: case NOTEQUAL:
case '=': case '=':
case RETURN: case RETURN:
if (is_cp_cst(exp) && exp->VL_VALUE == (arith)0) if (is_cp_cst(exp) && exp->VL_VALUE == 0)
break; break;
default: default:
expr_strict(exp, expr_strict(exp,

View file

@ -206,7 +206,7 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr)
where o1 == (*expp)->VL_VALUE; where o1 == (*expp)->VL_VALUE;
and ((oper == AND) || (oper == OR)) and ((oper == AND) || (oper == OR))
*/ */
if ((oper == AND) == (ex->VL_VALUE != (arith)0)) { if ((oper == AND) == (ex->VL_VALUE != 0)) {
*expp = expr; *expp = expr;
} }
else { else {
@ -224,13 +224,13 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr)
where o2 == expr->VL_VALUE where o2 == expr->VL_VALUE
and ((oper == AND) || (oper == OR)) and ((oper == AND) || (oper == OR))
*/ */
if ((oper == AND) == (expr->VL_VALUE != (arith)0)) { if ((oper == AND) == (expr->VL_VALUE != 0)) {
(*expp)->ex_flags |= expr->ex_flags | EX_ILVALUE; (*expp)->ex_flags |= expr->ex_flags | EX_ILVALUE;
free_expression(expr); free_expression(expr);
} }
else { else {
if (oper == OR) if (oper == OR)
expr->VL_VALUE = (arith)1; expr->VL_VALUE = 1;
ch3bin(expp, ',', expr); ch3bin(expp, ',', expr);
} }
} }

View file

@ -22,7 +22,6 @@
extern char options[]; extern char options[];
extern arith full_mask[/*MAXSIZE + 1*/]; /* cstoper.c */
char *symbol2str(); char *symbol2str();
void ch3mon(int oper, register struct expr **expp) void ch3mon(int oper, register struct expr **expp)
@ -122,7 +121,7 @@ void ch3mon(int oper, register struct expr **expp)
case '-': case '-':
any2arith(expp, oper); any2arith(expp, oper);
if (is_cp_cst(*expp)) { if (is_cp_cst(*expp)) {
arith o1 = (*expp)->VL_VALUE; writh o1 = (*expp)->VL_VALUE;
(*expp)->VL_VALUE = (oper == '-') ? -o1 : (*expp)->VL_VALUE = (oper == '-') ? -o1 :
((*expp)->ex_type->tp_unsigned ? ((*expp)->ex_type->tp_unsigned ?

View file

@ -602,7 +602,7 @@ void loc_init(struct expr *expr, struct idf *id)
EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
vl.vl_class = Name; vl.vl_class = Name;
vl.vl_data.vl_idf = id; vl.vl_data.vl_idf = id;
vl.vl_value = (arith)0; vl.vl_value = 0;
store_val(&vl, tp); store_val(&vl, tp);
} }
#else /* LINT */ #else /* LINT */

View file

@ -112,8 +112,6 @@ void conversion(register struct type *from_type, register struct type *to_type)
if ((int)(to_type->tp_size) < (int)word_size if ((int)(to_type->tp_size) < (int)word_size
&& to_cnvtype != T_FLOATING && to_cnvtype != T_FLOATING
) { ) {
extern arith full_mask[];
if (to_cnvtype == T_SIGNED) { if (to_cnvtype == T_SIGNED) {
C_loc(to_type->tp_size); C_loc(to_type->tp_size);
C_loc(word_size); C_loc(word_size);

View file

@ -18,7 +18,7 @@
#include "error.h" #include "error.h"
/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */ /* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
arith full_mask[MAXSIZE + 1]; writh full_mask[MAXSIZE + 1];
#ifndef NOCROSS #ifndef NOCROSS
arith max_int; /* maximum integer on target machine */ arith max_int; /* maximum integer on target machine */
arith max_unsigned; /* maximum unsigned on target machine */ arith max_unsigned; /* maximum unsigned on target machine */
@ -31,8 +31,8 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
expressions *expp(ld) and expr(ct), and the result restored in expressions *expp(ld) and expr(ct), and the result restored in
*expp. *expp.
*/ */
register arith o1 = (*expp)->VL_VALUE; unsigned writh o1 = (unsigned writh)(*expp)->VL_VALUE;
register arith o2 = expr->VL_VALUE; unsigned writh o2 = (unsigned writh)expr->VL_VALUE;
int uns = (*expp)->ex_type->tp_unsigned; int uns = (*expp)->ex_type->tp_unsigned;
assert(is_ld_cst(*expp) && is_cp_cst(expr)); assert(is_ld_cst(*expp) && is_cp_cst(expr));
@ -49,9 +49,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
break; break;
} }
if (uns) if (uns)
o1 /= (unsigned arith) o2;
else
o1 /= o2; o1 /= o2;
else
o1 = (unsigned writh)((writh)o1 / (writh)o2);
break; break;
case '%': case '%':
if (o2 == 0) { if (o2 == 0) {
@ -62,9 +62,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
break; break;
} }
if (uns) if (uns)
o1 %= (unsigned arith) o2;
else
o1 %= o2; o1 %= o2;
else
o1 = (unsigned writh)((writh)o1 % (writh)o2);
break; break;
case '+': case '+':
o1 += o2; o1 += o2;
@ -78,15 +78,14 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
case RIGHT: case RIGHT:
if (o2 == 0) if (o2 == 0)
break; break;
if (uns) { if (uns)
o1 = (o1 >> 1) & ~arith_sign; o1 >>= o2;
o1 >>= (o2 - 1); else
} o1 = (unsigned writh)((writh)o1 >> (writh)o2);
else o1 >>= o2;
break; break;
case '<': case '<':
{ {
arith tmp = o1; writh tmp = o1;
o1 = o2; o1 = o2;
o2 = tmp; o2 = tmp;
@ -94,13 +93,13 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
/* Fall through */ /* Fall through */
case '>': case '>':
if (uns) if (uns)
o1 = (unsigned arith) o1 > (unsigned arith) o2;
else
o1 = o1 > o2; o1 = o1 > o2;
else
o1 = (writh)o1 > (writh)o2;
break; break;
case LESSEQ: case LESSEQ:
{ {
arith tmp = o1; writh tmp = o1;
o1 = o2; o1 = o2;
o2 = tmp; o2 = tmp;
@ -108,9 +107,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
/* Fall through */ /* Fall through */
case GREATEREQ: case GREATEREQ:
if (uns) if (uns)
o1 = (unsigned arith) o1 >= (unsigned arith) o2;
else
o1 = o1 >= o2; o1 = o1 >= o2;
else
o1 = (writh)o1 >= (writh)o2;
break; break;
case EQUAL: case EQUAL:
o1 = o1 == o2; o1 = o1 == o2;
@ -128,7 +127,7 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
o1 ^= o2; o1 ^= o2;
break; break;
} }
(*expp)->VL_VALUE = o1; (*expp)->VL_VALUE = (writh)o1;
cut_size(*expp); cut_size(*expp);
(*expp)->ex_flags |= expr->ex_flags; (*expp)->ex_flags |= expr->ex_flags;
(*expp)->ex_flags &= ~EX_PARENS; (*expp)->ex_flags &= ~EX_PARENS;
@ -140,7 +139,7 @@ void cut_size(register struct expr *expr)
/* The constant value of the expression expr is made to /* The constant value of the expression expr is made to
conform to the size of the type of the expression. conform to the size of the type of the expression.
*/ */
register arith o1 = expr->VL_VALUE; writh o1 = expr->VL_VALUE;
int uns = expr->ex_type->tp_unsigned; int uns = expr->ex_type->tp_unsigned;
int size = (int) expr->ex_type->tp_size; int size = (int) expr->ex_type->tp_size;
@ -159,8 +158,8 @@ void cut_size(register struct expr *expr)
o1 &= full_mask[size]; o1 &= full_mask[size];
} }
else { else {
int nbits = (int) (arith_size - size) * 8; int nbits = (int) (sizeof(o1) - size) * 8;
arith remainder = o1 & ~full_mask[size]; writh remainder = o1 & ~full_mask[size];
if (remainder != 0 && remainder != ~full_mask[size]) if (remainder != 0 && remainder != ~full_mask[size])
if (!ResultKnown) if (!ResultKnown)
@ -173,22 +172,20 @@ void cut_size(register struct expr *expr)
void init_cst(void) void init_cst(void)
{ {
register int i = 0; register int i = 0;
register arith bt = (arith)0; unsigned writh bt = 0;
/* FIXME arith is insufficient for long long. We ignore while (!((writh)bt < 0)) {
this problem and write masks up to full_mask[8], but
masks are wrong after bt < 0.
*/
while (!(bt < 0) || i < 8) {
bt = (bt << 8) + 0377, i++; bt = (bt << 8) + 0377, i++;
if (i > MAXSIZE) if (i > MAXSIZE)
fatal("array full_mask too small for this machine"); fatal("array full_mask too small for this machine");
full_mask[i] = bt; full_mask[i] = bt;
} }
if ((int)long_size > arith_size) /* signed comparison; lnglng_size might be -1 */
fatal("sizeof (arith) insufficient on this machine"); if (long_size > (arith)sizeof(writh) ||
lnglng_size > (arith)sizeof(writh))
fatal("sizeof(writh) insufficient on this machine");
#ifndef NOCROSS #ifndef NOCROSS
max_int = full_mask[(int)int_size] & ~(1L << ((int)int_size * 8 - 1)); max_int = (arith)((unsigned writh)full_mask[(int)int_size] >> 1);
max_unsigned = full_mask[(int)int_size]; max_unsigned = (arith)full_mask[(int)int_size];
#endif /* NOCROSS */ #endif /* NOCROSS */
} }

View file

@ -343,7 +343,7 @@ arrayer(arith *sizep;)
constant_expression(&expr) constant_expression(&expr)
{ {
check_array_subscript(expr); check_array_subscript(expr);
*sizep = expr->VL_VALUE; *sizep = (arith)expr->VL_VALUE;
free_expression(expr); free_expression(expr);
} }
]? ]?
@ -430,7 +430,7 @@ enumerator(struct type *tp; arith *lp;)
'=' '='
constant_expression(&expr) constant_expression(&expr)
{ {
*lp = expr->VL_VALUE; *lp = (arith)expr->VL_VALUE;
free_expression(expr); free_expression(expr);
} }
]? ]?
@ -548,7 +548,7 @@ bit_expression(struct field **fd;)
':' ':'
constant_expression(&expr) constant_expression(&expr)
{ {
(*fd)->fd_width = expr->VL_VALUE; (*fd)->fd_width = (arith)expr->VL_VALUE;
free_expression(expr); free_expression(expr);
#ifdef NOBITFIELD #ifdef NOBITFIELD
error("bitfields are not implemented"); error("bitfields are not implemented");

View file

@ -118,11 +118,11 @@ void reject_params(register struct declarator *dc)
void check_array_subscript(register struct expr *expr) void check_array_subscript(register struct expr *expr)
{ {
arith size = expr->VL_VALUE; writh size = expr->VL_VALUE;
if (size < 0) { if (size < 0) {
error("array size is negative"); error("array size is negative");
expr->VL_VALUE = (arith)1; expr->VL_VALUE = 1;
} }
else else
if (size == 0) { if (size == 0) {
@ -131,6 +131,6 @@ void check_array_subscript(register struct expr *expr)
else else
if (size & ~max_unsigned) { /* absolutely ridiculous */ if (size & ~max_unsigned) { /* absolutely ridiculous */
expr_error(expr, "overflow in array size"); expr_error(expr, "overflow in array size");
expr->VL_VALUE = (arith)1; expr->VL_VALUE = 1;
} }
} }

View file

@ -6,8 +6,8 @@
/* DUMP ROUTINES */ /* DUMP ROUTINES */
#ifdef DEBUG
#include "parameters.h" #include "parameters.h"
#ifdef DEBUG
#include <ack_string.h> #include <ack_string.h>
#include <alloc.h> #include <alloc.h>
#include <flt_arith.h> #include <flt_arith.h>
@ -442,8 +442,8 @@ static void p1_expr(int lvl, register struct expr *expr)
print("(Unknown) "); print("(Unknown) ");
break; break;
} }
print(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n", print("%s\n", writh2str(expr->VL_VALUE,
expr->VL_VALUE); expr->ex_type->tp_unsigned));
break; break;
case String: case String:
{ {

View file

@ -106,7 +106,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
case String: /* a string constant */ case String: /* a string constant */
if (gencode) { if (gencode) {
string2pointer(expr); string2pointer(expr);
C_lae_dlb(expr->VL_LBL, expr->VL_VALUE); C_lae_dlb(expr->VL_LBL, (arith)expr->VL_VALUE);
} }
break; break;
case Float: /* a floating constant */ case Float: /* a floating constant */
@ -575,7 +575,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
NO_LABEL, NO_LABEL); NO_LABEL, NO_LABEL);
assert(is_cp_cst(right)); assert(is_cp_cst(right));
if (gencode) { if (gencode) {
C_adp(right->VL_VALUE); C_adp((arith)right->VL_VALUE);
} }
break; break;
case ',': case ',':
@ -858,10 +858,11 @@ void store_val(register struct value *vl, register struct type *tp)
{ {
register int inword = 0; register int inword = 0;
register int indword = 0; register int indword = 0;
arith val = vl->vl_value; writh wval = vl->vl_value;
arith val = (arith)wval;
if (vl->vl_class == Const) { /* absolute addressing */ if (vl->vl_class == Const) { /* absolute addressing */
load_cst(val, pointer_size); load_cst(wval, pointer_size);
store_block(tp->tp_size, tp->tp_align); store_block(tp->tp_size, tp->tp_align);
return; return;
} }
@ -930,7 +931,8 @@ void load_val(register struct expr *expr, int rlval)
register struct type *tp = expr->ex_type; register struct type *tp = expr->ex_type;
int rvalue = (rlval == RVAL && expr->ex_lvalue != 0); int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
register int inword = 0, indword = 0; register int inword = 0, indword = 0;
register arith val = expr->VL_VALUE; writh wval = expr->VL_VALUE;
arith val = (arith)wval;
if (expr->ex_type->tp_fund == FLOAT if (expr->ex_type->tp_fund == FLOAT
|| expr->ex_type->tp_fund == DOUBLE || expr->ex_type->tp_fund == DOUBLE
@ -938,11 +940,11 @@ void load_val(register struct expr *expr, int rlval)
fp_used = 1; fp_used = 1;
if (expr->VL_CLASS == Const) { if (expr->VL_CLASS == Const) {
if (rvalue) { /* absolute addressing */ if (rvalue) { /* absolute addressing */
load_cst(val, pointer_size); load_cst(wval, pointer_size);
load_block(tp->tp_size, tp->tp_align); load_block(tp->tp_size, tp->tp_align);
} }
else /* integer, unsigned, long, enum etc */ else /* integer, unsigned, long, enum etc */
load_cst(val, tp->tp_size); load_cst(wval, tp->tp_size);
return; return;
} }
if (rvalue) { if (rvalue) {
@ -1022,7 +1024,7 @@ void load_val(register struct expr *expr, int rlval)
} }
} }
void load_cst(arith val, arith siz) void load_cst(writh val, arith siz)
{ {
/* EM can't encode ldc with constant over 4 bytes. /* EM can't encode ldc with constant over 4 bytes.
Such a constant must go into rom. Such a constant must go into rom.
@ -1036,7 +1038,7 @@ void load_cst(arith val, arith siz)
label datlab; label datlab;
C_df_dlb(datlab = data_label()); C_df_dlb(datlab = data_label());
C_rom_icon(long2str((long)val, 10), siz); C_rom_icon(writh2str(val, 0), siz);
C_lae_dlb(datlab, (arith)0); C_lae_dlb(datlab, (arith)0);
C_loi(siz); C_loi(siz);
} }

View file

@ -12,6 +12,7 @@
#include <em.h> #include <em.h>
#include "arith.h" /* writh */
struct expr; struct expr;
struct value; struct value;
@ -30,7 +31,7 @@ void assop(register struct type *type, int oper);
*/ */
void store_val(register struct value *vl, register struct type *tp); void store_val(register struct value *vl, register struct type *tp);
void load_val(register struct expr *expr, int rlval); void load_val(register struct expr *expr, int rlval);
void load_cst(arith val, arith siz); void load_cst(writh val, arith siz);
#endif /* LINT */ #endif /* LINT */

View file

@ -184,21 +184,21 @@ void idf2expr(register struct expr *expr)
if (def->df_sc == ENUM) if (def->df_sc == ENUM)
{ {
expr->VL_CLASS = Const; expr->VL_CLASS = Const;
expr->VL_VALUE = def->df_address; expr->VL_VALUE = (writh)def->df_address;
} }
#ifndef LINT #ifndef LINT
else if (def->df_sc == STATIC && def->df_level >= L_LOCAL) else if (def->df_sc == STATIC && def->df_level >= L_LOCAL)
{ {
expr->VL_CLASS = Label; expr->VL_CLASS = Label;
expr->VL_LBL = def->df_address; expr->VL_LBL = def->df_address;
expr->VL_VALUE = (arith) 0; expr->VL_VALUE = 0;
} }
#endif /* LINT */ #endif /* LINT */
else else
{ {
expr->VL_CLASS = Name; expr->VL_CLASS = Name;
expr->VL_IDF = idf; expr->VL_IDF = idf;
expr->VL_VALUE = (arith) 0; expr->VL_VALUE = 0;
} }
} }
@ -270,12 +270,12 @@ arith ivalue, int fund)
expr->ex_file = dot.tk_file; expr->ex_file = dot.tk_file;
expr->ex_line = dot.tk_line; expr->ex_line = dot.tk_line;
fill_int_expr(expr, ivalue, fund); fill_int_expr(expr, (writh)ivalue, fund);
return expr; return expr;
} }
void fill_int_expr(register struct expr *ex, void fill_int_expr(register struct expr *ex,
arith ivalue, int fund) writh ivalue, int fund)
{ {
/* Details derived from ivalue and fund are put into the /* Details derived from ivalue and fund are put into the
constant integer expression ex. constant integer expression ex.
@ -294,6 +294,16 @@ arith ivalue, int fund)
case ULONG: case ULONG:
ex->ex_type = ulong_type; ex->ex_type = ulong_type;
break; break;
case LNGLNG:
ex->ex_type = lnglng_type;
break;
case ULNGLNG:
ex->ex_type = ulnglng_type;
break;
case ERRONEOUS: /* 123LL when no_long_long() */
ex->ex_type = error_type;
ex->ex_flags |= EX_ERROR;
break;
default: default:
crash("(fill_int_expr) bad fund %s\n", symbol2str(fund)); crash("(fill_int_expr) bad fund %s\n", symbol2str(fund));
/*NOTREACHED*/ /*NOTREACHED*/
@ -406,6 +416,7 @@ void chk_cst_expr(struct expr **expp)
case INT: case INT:
case ENUM: case ENUM:
case LONG: case LONG:
case LNGLNG:
if (is_ld_cst(expr)) if (is_ld_cst(expr))
{ {
return; return;

View file

@ -23,7 +23,7 @@
struct value { struct value {
int vl_class; /* Const, Name or Label */ int vl_class; /* Const, Name or Label */
arith vl_value; /* constant value or offset */ writh vl_value; /* constant value or offset */
union { union {
struct idf *vl_idf; /* external name */ struct idf *vl_idf; /* external name */
label vl_lbl; /* compiler-generated label */ label vl_lbl; /* compiler-generated label */
@ -100,8 +100,6 @@ struct expr {
#define ISNAME(e) ((e)->ex_class == Value && (e)->VL_CLASS == Name) #define ISNAME(e) ((e)->ex_class == Value && (e)->VL_CLASS == Name)
#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA) #define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
extern struct expr *intexpr(), *new_oper();
/* ALLOCDEF "expr" 20 */ /* ALLOCDEF "expr" 20 */
@ -113,7 +111,7 @@ void string2expr(register struct expr **expp, char *str, int len);
void int2expr(struct expr *expr); void int2expr(struct expr *expr);
void float2expr(register struct expr *expr); void float2expr(register struct expr *expr);
struct expr* intexpr(arith ivalue, int fund); struct expr* intexpr(arith ivalue, int fund);
void fill_int_expr(register struct expr *ex,arith ivalue, int fund); void fill_int_expr(register struct expr *ex, writh ivalue, int fund);
struct expr *new_oper(struct type *tp, register struct expr *e1, int oper, struct expr *new_oper(struct type *tp, register struct expr *e1, int oper,
register struct expr *e2); register struct expr *e2);
void chk_cst_expr(struct expr **expp); void chk_cst_expr(struct expr **expp);

View file

@ -28,8 +28,6 @@
#include "eval.h" #include "eval.h"
extern arith full_mask[]; /* cstoper.c */
/* Eval_field() evaluates expressions involving bit fields. /* Eval_field() evaluates expressions involving bit fields.
The various instructions are not yet optimised in the expression The various instructions are not yet optimised in the expression
tree and are therefore dealt with in this function. tree and are therefore dealt with in this function.
@ -136,6 +134,8 @@ void store_field(
register struct expr *leftop, register struct expr *leftop,
arith tmpvar) arith tmpvar)
{ {
arith high_mask;
C_loc(fd->fd_mask); C_loc(fd->fd_mask);
C_and(word_size); C_and(word_size);
if (code == TRUE) if (code == TRUE)
@ -145,7 +145,8 @@ void store_field(
C_slu(word_size); C_slu(word_size);
else else
C_sli(word_size); C_sli(word_size);
C_loc(~((fd->fd_mask << fd->fd_shift) | ~full_mask[(int)word_size])); high_mask = (arith)~full_mask[(int)word_size];
C_loc(~((fd->fd_mask << fd->fd_shift) | high_mask));
if (leftop->ex_depth == 0) { /* simple case */ if (leftop->ex_depth == 0) { /* simple case */
load_val(leftop, RVAL); load_val(leftop, RVAL);
C_and(word_size); C_and(word_size);

View file

@ -544,11 +544,11 @@ void check_ival(struct expr **expp, register struct type *tp)
if (idf->id_def->df_type->tp_fund == FUNCTION) if (idf->id_def->df_type->tp_fund == FUNCTION)
C_con_pnam(idf->id_text); C_con_pnam(idf->id_text);
else /* e.g., int a; int *p = &a; */ else /* e.g., int a; int *p = &a; */
C_con_dnam(idf->id_text, expr->VL_VALUE); C_con_dnam(idf->id_text, (arith)expr->VL_VALUE);
} }
else { else {
assert(expr->VL_CLASS == Label); assert(expr->VL_CLASS == Label);
C_con_dlb(expr->VL_LBL, expr->VL_VALUE); C_con_dlb(expr->VL_LBL, (arith)expr->VL_VALUE);
} }
break; break;
case FLOAT: case FLOAT:
@ -595,7 +595,7 @@ and also to prevent runtime coercions for compile-time constants.
print_expr("init-expr after cast", expr); print_expr("init-expr after cast", expr);
#endif /* DEBUG */ #endif /* DEBUG */
if (is_cp_cst(expr)) if (is_cp_cst(expr))
put_bf(tp, expr->VL_VALUE); put_bf(tp, (arith)expr->VL_VALUE);
else else
illegal_init_cst(expr); illegal_init_cst(expr);
break; break;
@ -701,7 +701,7 @@ void put_bf(struct type *tp, arith val)
field |= (val & fd->fd_mask) << fd->fd_shift; field |= (val & fd->fd_mask) << fd->fd_shift;
if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) { if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) {
/* the selector was the last stored at this address */ /* the selector was the last stored at this address */
exp.VL_VALUE = field; exp.VL_VALUE = (writh)field;
con_int(&exp); con_int(&exp);
field = (arith)0; field = (arith)0;
offset = (arith)-1; offset = (arith)-1;
@ -739,11 +739,11 @@ void con_int(register struct expr *ex)
assert(is_cp_cst(ex)); assert(is_cp_cst(ex));
if (tp->tp_unsigned) if (tp->tp_unsigned)
C_con_ucon(long2str((long)ex->VL_VALUE, -10), tp->tp_size); C_con_ucon(writh2str(ex->VL_VALUE, 1), tp->tp_size);
else if (tp->tp_size == word_size) else if (tp->tp_size == word_size)
C_con_cst(ex->VL_VALUE); C_con_cst((arith)ex->VL_VALUE);
else else
C_con_icon(long2str((long)ex->VL_VALUE, 10), tp->tp_size); C_con_icon(writh2str(ex->VL_VALUE, 0), tp->tp_size);
} }
void illegal_init_cst(struct expr *ex) void illegal_init_cst(struct expr *ex)

View file

@ -32,8 +32,6 @@
#include "level.h" #include "level.h"
#include "print.h" #include "print.h"
extern long full_mask[];
#define INCR_SIZE 64 #define INCR_SIZE 64
static struct db_str static struct db_str

View file

@ -147,7 +147,7 @@ if_statement
/* The comparison has been optimized /* The comparison has been optimized
to a 0 or 1. to a 0 or 1.
*/ */
if (expr->VL_VALUE == (arith)0) { if (expr->VL_VALUE == 0) {
C_bra(l_false); C_bra(l_false);
} }
/* else fall through */ /* else fall through */
@ -210,7 +210,7 @@ while_statement
{ {
opnd2test(&expr, WHILE); opnd2test(&expr, WHILE);
if (is_cp_cst(expr)) { if (is_cp_cst(expr)) {
if (expr->VL_VALUE == (arith)0) { if (expr->VL_VALUE == 0) {
C_bra(l_break); C_bra(l_break);
} }
} }
@ -264,11 +264,11 @@ do_statement
{ {
opnd2test(&expr, WHILE); opnd2test(&expr, WHILE);
if (is_cp_cst(expr)) { if (is_cp_cst(expr)) {
if (expr->VL_VALUE == (arith)1) { if (expr->VL_VALUE == 1) {
C_bra(l_body); C_bra(l_body);
} }
#ifdef LINT #ifdef LINT
end_do_stmt(1, expr->VL_VALUE != (arith)0); end_do_stmt(1, expr->VL_VALUE != 0);
#endif /* LINT */ #endif /* LINT */
} }
else { else {
@ -313,7 +313,7 @@ for_statement
{ {
opnd2test(&e_test, FOR); opnd2test(&e_test, FOR);
if (is_cp_cst(e_test)) { if (is_cp_cst(e_test)) {
if (e_test->VL_VALUE == (arith)0) { if (e_test->VL_VALUE == 0) {
C_bra(l_break); C_bra(l_break);
} }
} }

View file

@ -32,13 +32,13 @@ extern char options[];
int density = DENSITY; int density = DENSITY;
static int compact(int nr, arith low, arith up) static int compact(int nr, writh low, writh up)
{ {
/* Careful! up - low might not fit in an arith. And then, /* Careful! up - low might not fit in an arith. And then,
the test "up-low < 0" might also not work to detect this the test "up-low < 0" might also not work to detect this
situation! Or is this just a bug in the M68020/M68000? situation! Or is this just a bug in the M68020/M68000?
*/ */
arith diff = up - low; writh diff = up - low;
return (nr == 0 || (diff >= 0 && diff / nr <= (density - 1))); return (nr == 0 || (diff >= 0 && diff / nr <= (density - 1)));
} }
@ -117,10 +117,10 @@ void code_endswitch(void)
C_rom_ilb(sh->sh_default); C_rom_ilb(sh->sh_default);
if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) { if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
/* CSA */ /* CSA */
register arith val; writh val;
C_rom_icon(long2str((long)sh->sh_lowerbd,10), size); C_rom_icon(writh2str(sh->sh_lowerbd, 0), size);
C_rom_icon(long2str((long)(sh->sh_upperbd - sh->sh_lowerbd),10), C_rom_icon(writh2str(sh->sh_upperbd - sh->sh_lowerbd, 0),
size); size);
ce = sh->sh_entries; ce = sh->sh_entries;
for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) { for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
@ -136,10 +136,10 @@ void code_endswitch(void)
C_csa(size); C_csa(size);
} }
else { /* CSB */ else { /* CSB */
C_rom_icon(long2str((long)sh->sh_nrofentries,10),size); C_rom_icon(writh2str(sh->sh_nrofentries, 0), size);
for (ce = sh->sh_entries; ce; ce = ce->next) { for (ce = sh->sh_entries; ce; ce = ce->next) {
/* generate the entries: value + prog.label */ /* generate the entries: value + prog.label */
C_rom_icon(long2str((long)ce->ce_value,10),size); C_rom_icon(writh2str(ce->ce_value, 0), size);
C_rom_ilb(ce->ce_label); C_rom_ilb(ce->ce_label);
} }
C_lae_dlb(tablabel, (arith)0); /* perform the switch */ C_lae_dlb(tablabel, (arith)0); /* perform the switch */
@ -162,7 +162,7 @@ void code_endswitch(void)
void code_case(struct expr *expr) void code_case(struct expr *expr)
{ {
register arith val; writh val;
register struct case_entry *ce; register struct case_entry *ce;
register struct switch_hdr *sh = switch_stack; register struct switch_hdr *sh = switch_stack;

View file

@ -22,8 +22,8 @@ struct switch_hdr {
int sh_nrofentries; int sh_nrofentries;
struct type *sh_type; struct type *sh_type;
struct expr *sh_expr; struct expr *sh_expr;
arith sh_lowerbd; writh sh_lowerbd;
arith sh_upperbd; writh sh_upperbd;
struct case_entry *sh_entries; struct case_entry *sh_entries;
}; };
@ -32,7 +32,7 @@ struct switch_hdr {
struct case_entry { struct case_entry {
struct case_entry *next; struct case_entry *next;
label ce_label; label ce_label;
arith ce_value; writh ce_value;
}; };
/* ALLOCDEF "case_entry" 20 */ /* ALLOCDEF "case_entry" 20 */

View file

@ -107,6 +107,7 @@ struct tokenname tkfunny[] = { /* internal keywords */
{LNGLNG, "long long"}, {LNGLNG, "long long"},
{LNGDBL, "long double"}, {LNGDBL, "long double"},
{ULONG, "unsigned long"}, {ULONG, "unsigned long"},
{ULNGLNG, "unsigned long long"},
{ARRAY, "array"}, {ARRAY, "array"},
{FUNCTION, "function"}, {FUNCTION, "function"},