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:
parent
007a63d529
commit
15950f9c95
|
@ -117,11 +117,6 @@
|
|||
/*#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
|
||||
#define GSTATIC /* for large global "static" arrays */
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "Lpars.h"
|
||||
#include "class.h"
|
||||
#include "sizes.h"
|
||||
#include "type.h" /* no_long_long() */
|
||||
#include "error.h"
|
||||
#include "domacro.h"
|
||||
#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_DOTSEEN 0x02 /* certainly a floating point number */
|
||||
extern arith full_mask[];
|
||||
|
||||
#ifdef LINT
|
||||
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)
|
||||
{
|
||||
register char* cp = intbuf;
|
||||
int base = 10;
|
||||
arith val = 0, dig, ubound;
|
||||
int uns_flg = 0, lng_flg = 0, malformed = 0, ovfl = 0;
|
||||
int fund;
|
||||
int base = 10, dig;
|
||||
unsigned writh val = 0, ubound;
|
||||
int uns_flg = 0, lng_flg = 0, lnglng_flg = 0;
|
||||
int malformed = 0, ovfl = 0;
|
||||
unsigned writh uint_mask, ulng_mask, ulnglng_mask;
|
||||
int cut, fund;
|
||||
|
||||
assert(*cp != '-');
|
||||
if (*cp == '0')
|
||||
|
@ -611,11 +613,8 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
|||
else
|
||||
base = 8;
|
||||
}
|
||||
/* The upperbound will be the same as when computed with
|
||||
* max_unsigned_arith / base (since base is even). The problem here
|
||||
* is that unsigned arith is not accepted by all compilers.
|
||||
*/
|
||||
ubound = max_arith / (base / 2);
|
||||
/* The upperbound checks if val * base would overflow. */
|
||||
ubound = ~(unsigned writh)0 / base;
|
||||
|
||||
while (is_hex(*cp))
|
||||
{
|
||||
|
@ -626,10 +625,10 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (val < 0 || val > ubound)
|
||||
if (val > ubound)
|
||||
ovfl++;
|
||||
val *= base;
|
||||
if (val < 0 && val + dig >= 0)
|
||||
if (val > val + dig)
|
||||
ovfl++;
|
||||
val += dig;
|
||||
}
|
||||
|
@ -639,7 +638,16 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
|||
while (*cp)
|
||||
{
|
||||
if (*cp == 'l' || *cp == 'L')
|
||||
lng_flg++;
|
||||
{
|
||||
if (*cp == *(cp + 1))
|
||||
{
|
||||
/* 'll' or 'LL' */
|
||||
lnglng_flg++;
|
||||
cp++;
|
||||
}
|
||||
else
|
||||
lng_flg++;
|
||||
}
|
||||
else if (*cp == 'u' || *cp == 'U')
|
||||
uns_flg++;
|
||||
else
|
||||
|
@ -658,51 +666,83 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (lng_flg > 1)
|
||||
if (lng_flg + lnglng_flg > 1)
|
||||
lexerror("only one long suffix allowed");
|
||||
if (uns_flg > 1)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else if (int_size == long_size)
|
||||
{
|
||||
fund = UNSIGNED;
|
||||
}
|
||||
else if (base == 10 && !uns_flg)
|
||||
fund = LONG;
|
||||
{
|
||||
if ((val & (ulng_mask >> 1)) == val)
|
||||
fund = LONG;
|
||||
else
|
||||
fund = ULONG;
|
||||
}
|
||||
else
|
||||
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;
|
||||
else
|
||||
fund = ULONG;
|
||||
}
|
||||
else
|
||||
{ /* sizeof(arith) is greater than long_size */
|
||||
assert(arith_size > long_size);
|
||||
lexwarning("constant too large for target machine");
|
||||
/* cut the size to prevent further complaints */
|
||||
val &= full_mask[(int)long_size];
|
||||
fund = ULONG;
|
||||
}
|
||||
if (lng_flg)
|
||||
else if (lnglng_flg && (val & ulnglng_mask) == val)
|
||||
{
|
||||
/* fund can't be INT */
|
||||
if (fund == UNSIGNED)
|
||||
if ((val & (ulnglng_mask >> 1)) == val)
|
||||
fund = LNGLNG;
|
||||
else
|
||||
fund = ULNGLNG;
|
||||
}
|
||||
else if (lnglng_flg && no_long_long())
|
||||
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 = ULONG;
|
||||
val &= ulng_mask;
|
||||
}
|
||||
}
|
||||
if (uns_flg)
|
||||
{
|
||||
|
@ -710,7 +750,9 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
|||
fund = UNSIGNED;
|
||||
else if (fund == LONG)
|
||||
fund = ULONG;
|
||||
else if (fund == LNGLNG)
|
||||
fund = ULNGLNG;
|
||||
}
|
||||
ptok->tk_fund = fund;
|
||||
ptok->tk_ival = val;
|
||||
ptok->tk_ival = (writh)val;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ struct token {
|
|||
char *tok_bts; /* row of bytes */
|
||||
int tok_len; /* length of row of bytes */
|
||||
} tok_string;
|
||||
arith tok_ival; /* for INTEGER */
|
||||
writh tok_ival; /* for INTEGER */
|
||||
char *tok_fval; /* for FLOATING */
|
||||
} tok_data;
|
||||
};
|
||||
|
|
|
@ -117,11 +117,6 @@
|
|||
/*#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
|
||||
#define GSTATIC /* for large global "static" arrays */
|
||||
|
||||
|
|
|
@ -371,8 +371,7 @@ int int2int(struct expr **expp, register struct type *tp)
|
|||
unsigned int x = ~0;
|
||||
unsigned int y = -1;
|
||||
*/
|
||||
extern long full_mask[];
|
||||
long remainder = exp->VL_VALUE &
|
||||
writh remainder = exp->VL_VALUE &
|
||||
~full_mask[(int)(tp->tp_size)];
|
||||
|
||||
if (remainder == 0 ||
|
||||
|
@ -389,6 +388,16 @@ int int2int(struct expr **expp, register struct type *tp)
|
|||
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
|
||||
* only when necessary in eval.c.
|
||||
*/
|
||||
|
@ -400,10 +409,10 @@ void int2float(register struct expr **expp, struct type *tp)
|
|||
register struct expr *exp = *expp;
|
||||
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_class = Float;
|
||||
flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH), uns);
|
||||
flt_arith2flt((arith)exp->VL_VALUE, &(exp->FL_ARITH), uns);
|
||||
}
|
||||
else {
|
||||
fp_used = 1;
|
||||
|
@ -417,24 +426,35 @@ void float2int(struct expr **expp, struct type *tp)
|
|||
converted to the integral type tp.
|
||||
*/
|
||||
register struct expr *ex = *expp;
|
||||
|
||||
|
||||
if (is_fp_cst(ex)) {
|
||||
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)
|
||||
expr_warning(ex,"overflow in float to int conversion");
|
||||
else if (flt_status == FLT_UNFL)
|
||||
expr_warning(ex,"underflow in float to unsigned conversion");
|
||||
ex->ex_type = tp;
|
||||
/* The following lines are copied from fill_int_expr */
|
||||
ex->ex_class = Value;
|
||||
ex->VL_CLASS = Const;
|
||||
ex->VL_VALUE = ar;
|
||||
cut_size(ex);
|
||||
} else {
|
||||
fp_used = 1;
|
||||
*expp = arith2arith(tp, FLOAT2INT, ex);
|
||||
#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;
|
||||
/* The following lines are copied from fill_int_expr */
|
||||
ex->ex_class = Value;
|
||||
ex->VL_CLASS = Const;
|
||||
ex->VL_VALUE = (writh)ar;
|
||||
cut_size(ex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fp_used = 1;
|
||||
*expp = arith2arith(tp, FLOAT2INT, ex);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -5,30 +5,25 @@
|
|||
/* $Id$ */
|
||||
/* COMPILER ARITHMETIC */
|
||||
|
||||
/* Normally the compiler does its internal arithmetics in longs
|
||||
native to the source machine, which is always good for local
|
||||
compilations, and generally OK too for cross compilations
|
||||
downwards and sidewards. For upwards cross compilation and
|
||||
to save storage on small machines, SPECIAL_ARITHMETICS will
|
||||
be handy.
|
||||
/* The compiler uses 2 types, arith and writh, for its internal
|
||||
arithmetic. Type arith is normally long, and may be too
|
||||
narrow for long long values. We can't change arith to a wider
|
||||
type, because both <em_arith.h> (pulled by <em.h>) and
|
||||
<flt_arith.h> define arith.
|
||||
|
||||
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_
|
||||
#define ARITH_H_
|
||||
|
||||
#include "parameters.h"
|
||||
|
||||
#ifndef SPECIAL_ARITHMETICS
|
||||
|
||||
#include <em_arith.h> /* obtain definition of "arith" */
|
||||
#include <flt_arith.h>
|
||||
|
||||
#else /* SPECIAL_ARITHMETICS */
|
||||
|
||||
/* All preprocessor arithmetic should be done in longs.
|
||||
*/
|
||||
#define arith long /* dummy */
|
||||
|
||||
#endif /* SPECIAL_ARITHMETICS */
|
||||
#define writh long long
|
||||
/* The compiler also uses "unsigned writh". */
|
||||
|
||||
struct expr;
|
||||
struct type;
|
||||
|
@ -37,6 +32,8 @@ struct type;
|
|||
#define arith_sign ((arith) 1 << (arith_size * 8 - 1))
|
||||
#define max_arith (~arith_sign)
|
||||
|
||||
extern writh full_mask[]; /* cstoper.c */
|
||||
|
||||
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 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 field2arith(register struct expr **expp);
|
||||
void switch_sign_fp(register struct expr *expr);
|
||||
char *writh2str(writh val, int uns);
|
||||
|
||||
#endif /* ARITH_H_ */
|
||||
|
|
|
@ -320,7 +320,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp)
|
|||
}
|
||||
if (oldtp->tp_up->tp_fund == VOID
|
||||
&& is_cp_cst(exp)
|
||||
&& exp->VL_VALUE == (arith)0)
|
||||
&& exp->VL_VALUE == 0)
|
||||
break; /* switch */
|
||||
}
|
||||
/* falltrough */
|
||||
|
@ -366,7 +366,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp)
|
|||
case NOTEQUAL:
|
||||
case '=':
|
||||
case RETURN:
|
||||
if (is_cp_cst(exp) && exp->VL_VALUE == (arith)0)
|
||||
if (is_cp_cst(exp) && exp->VL_VALUE == 0)
|
||||
break;
|
||||
default:
|
||||
expr_strict(exp,
|
||||
|
|
|
@ -206,7 +206,7 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr)
|
|||
where o1 == (*expp)->VL_VALUE;
|
||||
and ((oper == AND) || (oper == OR))
|
||||
*/
|
||||
if ((oper == AND) == (ex->VL_VALUE != (arith)0)) {
|
||||
if ((oper == AND) == (ex->VL_VALUE != 0)) {
|
||||
*expp = expr;
|
||||
}
|
||||
else {
|
||||
|
@ -224,13 +224,13 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr)
|
|||
where o2 == expr->VL_VALUE
|
||||
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;
|
||||
free_expression(expr);
|
||||
}
|
||||
else {
|
||||
if (oper == OR)
|
||||
expr->VL_VALUE = (arith)1;
|
||||
expr->VL_VALUE = 1;
|
||||
ch3bin(expp, ',', expr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
|
||||
extern char options[];
|
||||
extern arith full_mask[/*MAXSIZE + 1*/]; /* cstoper.c */
|
||||
char *symbol2str();
|
||||
|
||||
void ch3mon(int oper, register struct expr **expp)
|
||||
|
@ -122,7 +121,7 @@ void ch3mon(int oper, register struct expr **expp)
|
|||
case '-':
|
||||
any2arith(expp, oper);
|
||||
if (is_cp_cst(*expp)) {
|
||||
arith o1 = (*expp)->VL_VALUE;
|
||||
writh o1 = (*expp)->VL_VALUE;
|
||||
|
||||
(*expp)->VL_VALUE = (oper == '-') ? -o1 :
|
||||
((*expp)->ex_type->tp_unsigned ?
|
||||
|
|
|
@ -602,7 +602,7 @@ void loc_init(struct expr *expr, struct idf *id)
|
|||
EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
vl.vl_class = Name;
|
||||
vl.vl_data.vl_idf = id;
|
||||
vl.vl_value = (arith)0;
|
||||
vl.vl_value = 0;
|
||||
store_val(&vl, tp);
|
||||
}
|
||||
#else /* LINT */
|
||||
|
|
|
@ -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
|
||||
&& to_cnvtype != T_FLOATING
|
||||
) {
|
||||
extern arith full_mask[];
|
||||
|
||||
if (to_cnvtype == T_SIGNED) {
|
||||
C_loc(to_type->tp_size);
|
||||
C_loc(word_size);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "error.h"
|
||||
|
||||
/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
|
||||
arith full_mask[MAXSIZE + 1];
|
||||
writh full_mask[MAXSIZE + 1];
|
||||
#ifndef NOCROSS
|
||||
arith max_int; /* maximum integer 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
|
||||
*expp.
|
||||
*/
|
||||
register arith o1 = (*expp)->VL_VALUE;
|
||||
register arith o2 = expr->VL_VALUE;
|
||||
unsigned writh o1 = (unsigned writh)(*expp)->VL_VALUE;
|
||||
unsigned writh o2 = (unsigned writh)expr->VL_VALUE;
|
||||
int uns = (*expp)->ex_type->tp_unsigned;
|
||||
|
||||
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;
|
||||
}
|
||||
if (uns)
|
||||
o1 /= (unsigned arith) o2;
|
||||
else
|
||||
o1 /= o2;
|
||||
else
|
||||
o1 = (unsigned writh)((writh)o1 / (writh)o2);
|
||||
break;
|
||||
case '%':
|
||||
if (o2 == 0) {
|
||||
|
@ -62,9 +62,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
|||
break;
|
||||
}
|
||||
if (uns)
|
||||
o1 %= (unsigned arith) o2;
|
||||
else
|
||||
o1 %= o2;
|
||||
else
|
||||
o1 = (unsigned writh)((writh)o1 % (writh)o2);
|
||||
break;
|
||||
case '+':
|
||||
o1 += o2;
|
||||
|
@ -78,15 +78,14 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
|||
case RIGHT:
|
||||
if (o2 == 0)
|
||||
break;
|
||||
if (uns) {
|
||||
o1 = (o1 >> 1) & ~arith_sign;
|
||||
o1 >>= (o2 - 1);
|
||||
}
|
||||
else o1 >>= o2;
|
||||
if (uns)
|
||||
o1 >>= o2;
|
||||
else
|
||||
o1 = (unsigned writh)((writh)o1 >> (writh)o2);
|
||||
break;
|
||||
case '<':
|
||||
{
|
||||
arith tmp = o1;
|
||||
writh tmp = o1;
|
||||
|
||||
o1 = o2;
|
||||
o2 = tmp;
|
||||
|
@ -94,13 +93,13 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
|||
/* Fall through */
|
||||
case '>':
|
||||
if (uns)
|
||||
o1 = (unsigned arith) o1 > (unsigned arith) o2;
|
||||
else
|
||||
o1 = o1 > o2;
|
||||
else
|
||||
o1 = (writh)o1 > (writh)o2;
|
||||
break;
|
||||
case LESSEQ:
|
||||
{
|
||||
arith tmp = o1;
|
||||
writh tmp = o1;
|
||||
|
||||
o1 = o2;
|
||||
o2 = tmp;
|
||||
|
@ -108,9 +107,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
|||
/* Fall through */
|
||||
case GREATEREQ:
|
||||
if (uns)
|
||||
o1 = (unsigned arith) o1 >= (unsigned arith) o2;
|
||||
else
|
||||
o1 = o1 >= o2;
|
||||
else
|
||||
o1 = (writh)o1 >= (writh)o2;
|
||||
break;
|
||||
case EQUAL:
|
||||
o1 = o1 == o2;
|
||||
|
@ -128,7 +127,7 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
|||
o1 ^= o2;
|
||||
break;
|
||||
}
|
||||
(*expp)->VL_VALUE = o1;
|
||||
(*expp)->VL_VALUE = (writh)o1;
|
||||
cut_size(*expp);
|
||||
(*expp)->ex_flags |= expr->ex_flags;
|
||||
(*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
|
||||
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 size = (int) expr->ex_type->tp_size;
|
||||
|
||||
|
@ -159,8 +158,8 @@ void cut_size(register struct expr *expr)
|
|||
o1 &= full_mask[size];
|
||||
}
|
||||
else {
|
||||
int nbits = (int) (arith_size - size) * 8;
|
||||
arith remainder = o1 & ~full_mask[size];
|
||||
int nbits = (int) (sizeof(o1) - size) * 8;
|
||||
writh remainder = o1 & ~full_mask[size];
|
||||
|
||||
if (remainder != 0 && remainder != ~full_mask[size])
|
||||
if (!ResultKnown)
|
||||
|
@ -173,22 +172,20 @@ void cut_size(register struct expr *expr)
|
|||
void init_cst(void)
|
||||
{
|
||||
register int i = 0;
|
||||
register arith bt = (arith)0;
|
||||
unsigned writh bt = 0;
|
||||
|
||||
/* FIXME arith is insufficient for long long. We ignore
|
||||
this problem and write masks up to full_mask[8], but
|
||||
masks are wrong after bt < 0.
|
||||
*/
|
||||
while (!(bt < 0) || i < 8) {
|
||||
while (!((writh)bt < 0)) {
|
||||
bt = (bt << 8) + 0377, i++;
|
||||
if (i > MAXSIZE)
|
||||
fatal("array full_mask too small for this machine");
|
||||
full_mask[i] = bt;
|
||||
}
|
||||
if ((int)long_size > arith_size)
|
||||
fatal("sizeof (arith) insufficient on this machine");
|
||||
/* signed comparison; lnglng_size might be -1 */
|
||||
if (long_size > (arith)sizeof(writh) ||
|
||||
lnglng_size > (arith)sizeof(writh))
|
||||
fatal("sizeof(writh) insufficient on this machine");
|
||||
#ifndef NOCROSS
|
||||
max_int = full_mask[(int)int_size] & ~(1L << ((int)int_size * 8 - 1));
|
||||
max_unsigned = full_mask[(int)int_size];
|
||||
max_int = (arith)((unsigned writh)full_mask[(int)int_size] >> 1);
|
||||
max_unsigned = (arith)full_mask[(int)int_size];
|
||||
#endif /* NOCROSS */
|
||||
}
|
||||
|
|
|
@ -343,7 +343,7 @@ arrayer(arith *sizep;)
|
|||
constant_expression(&expr)
|
||||
{
|
||||
check_array_subscript(expr);
|
||||
*sizep = expr->VL_VALUE;
|
||||
*sizep = (arith)expr->VL_VALUE;
|
||||
free_expression(expr);
|
||||
}
|
||||
]?
|
||||
|
@ -430,7 +430,7 @@ enumerator(struct type *tp; arith *lp;)
|
|||
'='
|
||||
constant_expression(&expr)
|
||||
{
|
||||
*lp = expr->VL_VALUE;
|
||||
*lp = (arith)expr->VL_VALUE;
|
||||
free_expression(expr);
|
||||
}
|
||||
]?
|
||||
|
@ -548,7 +548,7 @@ bit_expression(struct field **fd;)
|
|||
':'
|
||||
constant_expression(&expr)
|
||||
{
|
||||
(*fd)->fd_width = expr->VL_VALUE;
|
||||
(*fd)->fd_width = (arith)expr->VL_VALUE;
|
||||
free_expression(expr);
|
||||
#ifdef NOBITFIELD
|
||||
error("bitfields are not implemented");
|
||||
|
|
|
@ -118,11 +118,11 @@ void reject_params(register struct declarator *dc)
|
|||
|
||||
void check_array_subscript(register struct expr *expr)
|
||||
{
|
||||
arith size = expr->VL_VALUE;
|
||||
writh size = expr->VL_VALUE;
|
||||
|
||||
if (size < 0) {
|
||||
error("array size is negative");
|
||||
expr->VL_VALUE = (arith)1;
|
||||
expr->VL_VALUE = 1;
|
||||
}
|
||||
else
|
||||
if (size == 0) {
|
||||
|
@ -131,6 +131,6 @@ void check_array_subscript(register struct expr *expr)
|
|||
else
|
||||
if (size & ~max_unsigned) { /* absolutely ridiculous */
|
||||
expr_error(expr, "overflow in array size");
|
||||
expr->VL_VALUE = (arith)1;
|
||||
expr->VL_VALUE = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
/* DUMP ROUTINES */
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "parameters.h"
|
||||
#ifdef DEBUG
|
||||
#include <ack_string.h>
|
||||
#include <alloc.h>
|
||||
#include <flt_arith.h>
|
||||
|
@ -442,8 +442,8 @@ static void p1_expr(int lvl, register struct expr *expr)
|
|||
print("(Unknown) ");
|
||||
break;
|
||||
}
|
||||
print(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n",
|
||||
expr->VL_VALUE);
|
||||
print("%s\n", writh2str(expr->VL_VALUE,
|
||||
expr->ex_type->tp_unsigned));
|
||||
break;
|
||||
case String:
|
||||
{
|
||||
|
|
|
@ -106,7 +106,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
|
|||
case String: /* a string constant */
|
||||
if (gencode) {
|
||||
string2pointer(expr);
|
||||
C_lae_dlb(expr->VL_LBL, expr->VL_VALUE);
|
||||
C_lae_dlb(expr->VL_LBL, (arith)expr->VL_VALUE);
|
||||
}
|
||||
break;
|
||||
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);
|
||||
assert(is_cp_cst(right));
|
||||
if (gencode) {
|
||||
C_adp(right->VL_VALUE);
|
||||
C_adp((arith)right->VL_VALUE);
|
||||
}
|
||||
break;
|
||||
case ',':
|
||||
|
@ -858,10 +858,11 @@ void store_val(register struct value *vl, register struct type *tp)
|
|||
{
|
||||
register int inword = 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 */
|
||||
load_cst(val, pointer_size);
|
||||
load_cst(wval, pointer_size);
|
||||
store_block(tp->tp_size, tp->tp_align);
|
||||
return;
|
||||
}
|
||||
|
@ -930,7 +931,8 @@ void load_val(register struct expr *expr, int rlval)
|
|||
register struct type *tp = expr->ex_type;
|
||||
int rvalue = (rlval == RVAL && expr->ex_lvalue != 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
|
||||
|| expr->ex_type->tp_fund == DOUBLE
|
||||
|
@ -938,11 +940,11 @@ void load_val(register struct expr *expr, int rlval)
|
|||
fp_used = 1;
|
||||
if (expr->VL_CLASS == Const) {
|
||||
if (rvalue) { /* absolute addressing */
|
||||
load_cst(val, pointer_size);
|
||||
load_cst(wval, pointer_size);
|
||||
load_block(tp->tp_size, tp->tp_align);
|
||||
}
|
||||
else /* integer, unsigned, long, enum etc */
|
||||
load_cst(val, tp->tp_size);
|
||||
load_cst(wval, tp->tp_size);
|
||||
return;
|
||||
}
|
||||
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.
|
||||
Such a constant must go into rom.
|
||||
|
@ -1036,7 +1038,7 @@ void load_cst(arith val, arith siz)
|
|||
label datlab;
|
||||
|
||||
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_loi(siz);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
|
||||
#include <em.h>
|
||||
#include "arith.h" /* writh */
|
||||
|
||||
struct expr;
|
||||
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 load_val(register struct expr *expr, int rlval);
|
||||
void load_cst(arith val, arith siz);
|
||||
void load_cst(writh val, arith siz);
|
||||
|
||||
#endif /* LINT */
|
||||
|
||||
|
|
|
@ -184,21 +184,21 @@ void idf2expr(register struct expr *expr)
|
|||
if (def->df_sc == ENUM)
|
||||
{
|
||||
expr->VL_CLASS = Const;
|
||||
expr->VL_VALUE = def->df_address;
|
||||
expr->VL_VALUE = (writh)def->df_address;
|
||||
}
|
||||
#ifndef LINT
|
||||
else if (def->df_sc == STATIC && def->df_level >= L_LOCAL)
|
||||
{
|
||||
expr->VL_CLASS = Label;
|
||||
expr->VL_LBL = def->df_address;
|
||||
expr->VL_VALUE = (arith) 0;
|
||||
expr->VL_VALUE = 0;
|
||||
}
|
||||
#endif /* LINT */
|
||||
else
|
||||
{
|
||||
expr->VL_CLASS = Name;
|
||||
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_line = dot.tk_line;
|
||||
fill_int_expr(expr, ivalue, fund);
|
||||
fill_int_expr(expr, (writh)ivalue, fund);
|
||||
return expr;
|
||||
}
|
||||
|
||||
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
|
||||
constant integer expression ex.
|
||||
|
@ -294,6 +294,16 @@ arith ivalue, int fund)
|
|||
case ULONG:
|
||||
ex->ex_type = ulong_type;
|
||||
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:
|
||||
crash("(fill_int_expr) bad fund %s\n", symbol2str(fund));
|
||||
/*NOTREACHED*/
|
||||
|
@ -406,6 +416,7 @@ void chk_cst_expr(struct expr **expp)
|
|||
case INT:
|
||||
case ENUM:
|
||||
case LONG:
|
||||
case LNGLNG:
|
||||
if (is_ld_cst(expr))
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
struct value {
|
||||
int vl_class; /* Const, Name or Label */
|
||||
arith vl_value; /* constant value or offset */
|
||||
writh vl_value; /* constant value or offset */
|
||||
union {
|
||||
struct idf *vl_idf; /* external name */
|
||||
label vl_lbl; /* compiler-generated label */
|
||||
|
@ -100,8 +100,6 @@ struct expr {
|
|||
#define ISNAME(e) ((e)->ex_class == Value && (e)->VL_CLASS == Name)
|
||||
#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
|
||||
|
||||
extern struct expr *intexpr(), *new_oper();
|
||||
|
||||
/* ALLOCDEF "expr" 20 */
|
||||
|
||||
|
||||
|
@ -113,7 +111,7 @@ void string2expr(register struct expr **expp, char *str, int len);
|
|||
void int2expr(struct expr *expr);
|
||||
void float2expr(register struct expr *expr);
|
||||
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,
|
||||
register struct expr *e2);
|
||||
void chk_cst_expr(struct expr **expp);
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include "eval.h"
|
||||
|
||||
|
||||
extern arith full_mask[]; /* cstoper.c */
|
||||
|
||||
/* Eval_field() evaluates expressions involving bit fields.
|
||||
The various instructions are not yet optimised in the expression
|
||||
tree and are therefore dealt with in this function.
|
||||
|
@ -136,6 +134,8 @@ void store_field(
|
|||
register struct expr *leftop,
|
||||
arith tmpvar)
|
||||
{
|
||||
arith high_mask;
|
||||
|
||||
C_loc(fd->fd_mask);
|
||||
C_and(word_size);
|
||||
if (code == TRUE)
|
||||
|
@ -145,7 +145,8 @@ void store_field(
|
|||
C_slu(word_size);
|
||||
else
|
||||
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 */
|
||||
load_val(leftop, RVAL);
|
||||
C_and(word_size);
|
||||
|
|
|
@ -544,11 +544,11 @@ void check_ival(struct expr **expp, register struct type *tp)
|
|||
if (idf->id_def->df_type->tp_fund == FUNCTION)
|
||||
C_con_pnam(idf->id_text);
|
||||
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 {
|
||||
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;
|
||||
case FLOAT:
|
||||
|
@ -595,7 +595,7 @@ and also to prevent runtime coercions for compile-time constants.
|
|||
print_expr("init-expr after cast", expr);
|
||||
#endif /* DEBUG */
|
||||
if (is_cp_cst(expr))
|
||||
put_bf(tp, expr->VL_VALUE);
|
||||
put_bf(tp, (arith)expr->VL_VALUE);
|
||||
else
|
||||
illegal_init_cst(expr);
|
||||
break;
|
||||
|
@ -701,7 +701,7 @@ void put_bf(struct type *tp, arith val)
|
|||
field |= (val & fd->fd_mask) << fd->fd_shift;
|
||||
if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) {
|
||||
/* the selector was the last stored at this address */
|
||||
exp.VL_VALUE = field;
|
||||
exp.VL_VALUE = (writh)field;
|
||||
con_int(&exp);
|
||||
field = (arith)0;
|
||||
offset = (arith)-1;
|
||||
|
@ -739,11 +739,11 @@ void con_int(register struct expr *ex)
|
|||
|
||||
assert(is_cp_cst(ex));
|
||||
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)
|
||||
C_con_cst(ex->VL_VALUE);
|
||||
C_con_cst((arith)ex->VL_VALUE);
|
||||
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)
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
#include "level.h"
|
||||
#include "print.h"
|
||||
|
||||
extern long full_mask[];
|
||||
|
||||
#define INCR_SIZE 64
|
||||
|
||||
static struct db_str
|
||||
|
|
|
@ -147,7 +147,7 @@ if_statement
|
|||
/* The comparison has been optimized
|
||||
to a 0 or 1.
|
||||
*/
|
||||
if (expr->VL_VALUE == (arith)0) {
|
||||
if (expr->VL_VALUE == 0) {
|
||||
C_bra(l_false);
|
||||
}
|
||||
/* else fall through */
|
||||
|
@ -210,7 +210,7 @@ while_statement
|
|||
{
|
||||
opnd2test(&expr, WHILE);
|
||||
if (is_cp_cst(expr)) {
|
||||
if (expr->VL_VALUE == (arith)0) {
|
||||
if (expr->VL_VALUE == 0) {
|
||||
C_bra(l_break);
|
||||
}
|
||||
}
|
||||
|
@ -264,11 +264,11 @@ do_statement
|
|||
{
|
||||
opnd2test(&expr, WHILE);
|
||||
if (is_cp_cst(expr)) {
|
||||
if (expr->VL_VALUE == (arith)1) {
|
||||
if (expr->VL_VALUE == 1) {
|
||||
C_bra(l_body);
|
||||
}
|
||||
#ifdef LINT
|
||||
end_do_stmt(1, expr->VL_VALUE != (arith)0);
|
||||
end_do_stmt(1, expr->VL_VALUE != 0);
|
||||
#endif /* LINT */
|
||||
}
|
||||
else {
|
||||
|
@ -313,7 +313,7 @@ for_statement
|
|||
{
|
||||
opnd2test(&e_test, FOR);
|
||||
if (is_cp_cst(e_test)) {
|
||||
if (e_test->VL_VALUE == (arith)0) {
|
||||
if (e_test->VL_VALUE == 0) {
|
||||
C_bra(l_break);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,13 +32,13 @@ extern char options[];
|
|||
|
||||
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,
|
||||
the test "up-low < 0" might also not work to detect this
|
||||
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)));
|
||||
}
|
||||
|
@ -117,10 +117,10 @@ void code_endswitch(void)
|
|||
C_rom_ilb(sh->sh_default);
|
||||
if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
|
||||
/* CSA */
|
||||
register arith val;
|
||||
writh val;
|
||||
|
||||
C_rom_icon(long2str((long)sh->sh_lowerbd,10), size);
|
||||
C_rom_icon(long2str((long)(sh->sh_upperbd - sh->sh_lowerbd),10),
|
||||
C_rom_icon(writh2str(sh->sh_lowerbd, 0), size);
|
||||
C_rom_icon(writh2str(sh->sh_upperbd - sh->sh_lowerbd, 0),
|
||||
size);
|
||||
ce = sh->sh_entries;
|
||||
for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
|
||||
|
@ -136,10 +136,10 @@ void code_endswitch(void)
|
|||
C_csa(size);
|
||||
}
|
||||
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) {
|
||||
/* 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_lae_dlb(tablabel, (arith)0); /* perform the switch */
|
||||
|
@ -162,7 +162,7 @@ void code_endswitch(void)
|
|||
|
||||
void code_case(struct expr *expr)
|
||||
{
|
||||
register arith val;
|
||||
writh val;
|
||||
register struct case_entry *ce;
|
||||
register struct switch_hdr *sh = switch_stack;
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ struct switch_hdr {
|
|||
int sh_nrofentries;
|
||||
struct type *sh_type;
|
||||
struct expr *sh_expr;
|
||||
arith sh_lowerbd;
|
||||
arith sh_upperbd;
|
||||
writh sh_lowerbd;
|
||||
writh sh_upperbd;
|
||||
struct case_entry *sh_entries;
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,7 @@ struct switch_hdr {
|
|||
struct case_entry {
|
||||
struct case_entry *next;
|
||||
label ce_label;
|
||||
arith ce_value;
|
||||
writh ce_value;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "case_entry" 20 */
|
||||
|
|
|
@ -107,6 +107,7 @@ struct tokenname tkfunny[] = { /* internal keywords */
|
|||
{LNGLNG, "long long"},
|
||||
{LNGDBL, "long double"},
|
||||
{ULONG, "unsigned long"},
|
||||
{ULNGLNG, "unsigned long long"},
|
||||
|
||||
{ARRAY, "array"},
|
||||
{FUNCTION, "function"},
|
||||
|
|
Loading…
Reference in a new issue