modified the treatment of op=, ++ and -- operators
This commit is contained in:
parent
42112db262
commit
5af21dfc79
15 changed files with 421 additions and 601 deletions
|
@ -17,7 +17,8 @@ EMELIB = $(EM)/modules/lib/libeme.a
|
|||
STRLIB = $(EM)/modules/lib/libstr.a
|
||||
PRTLIB = $(EM)/modules/lib/libprint.a
|
||||
EMMESLIB = $(EM)/modules/lib/libem_mes.a
|
||||
CH3LIB = $(EM)/modules/lib/libch3.a
|
||||
#CH3LIB = $(EM)/modules/lib/libch3.a
|
||||
CH3LIB =
|
||||
LIBS = $(CH3LIB) $(EMMESLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) $(SYSLIB)
|
||||
ELIBS = $(CH3LIB) $(EMMESLIB) $(EMELIB) $(PRTLIB) $(STRLIB) $(SYSLIB)
|
||||
LIB_INCLUDES = $(EM)/modules/h
|
||||
|
|
|
@ -423,6 +423,10 @@ is_asgn_op(oper)
|
|||
case ANDAB:
|
||||
case ORAB:
|
||||
case XORAB:
|
||||
case PLUSPLUS:
|
||||
case POSTINCR:
|
||||
case MINMIN:
|
||||
case POSTDECR:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
/* $Header$ */
|
||||
/* B L O C K S T O R I N G A N D L O A D I N G */
|
||||
|
||||
#include <em.h>
|
||||
#include "arith.h"
|
||||
#include "sizes.h"
|
||||
#include "atw.h"
|
||||
#include <em.h>
|
||||
#include "arith.h"
|
||||
#include "sizes.h"
|
||||
#include "atw.h"
|
||||
#ifndef STB
|
||||
#include "label.h"
|
||||
#include "stack.h"
|
||||
#endif STB
|
||||
|
||||
/* Because EM does not support the loading and storing of
|
||||
objects having other sizes than word fragment and multiple,
|
||||
|
@ -38,17 +42,33 @@ store_block(sz, al)
|
|||
arith sz;
|
||||
int al;
|
||||
{
|
||||
/* Next condition contains Lots of Irritating Stupid Parentheses
|
||||
*/
|
||||
if (
|
||||
((sz == al) && (word_align % al == 0)) ||
|
||||
(
|
||||
(sz % word_size == 0 || word_size % sz == 0) &&
|
||||
(al % word_align == 0)
|
||||
)
|
||||
)
|
||||
) /* Lots of Irritating Stupid Parentheses */
|
||||
C_sti(sz);
|
||||
else {
|
||||
else {
|
||||
#ifndef STB
|
||||
arith src, dst, src_offs, dst_offs;
|
||||
|
||||
/* allocate two pointer temporaries */
|
||||
src = tmp_pointer_var(&src_offs);
|
||||
dst = tmp_pointer_var(&dst_offs);
|
||||
|
||||
/* load the addresses */
|
||||
C_lal(dst);
|
||||
C_sti(pointer_size);
|
||||
C_lor((arith)1); /* push current sp */
|
||||
C_lal(src);
|
||||
C_sti(pointer_size);
|
||||
copy_loop(sz, src, dst);
|
||||
C_asp(ATW(sz));
|
||||
free_tmp_var(dst_offs);
|
||||
free_tmp_var(src_offs);
|
||||
#else STB
|
||||
/* address of destination lies on the stack */
|
||||
|
||||
/* push address of first byte of block on stack onto
|
||||
|
@ -60,6 +80,7 @@ store_block(sz, al)
|
|||
C_loc(sz); /* number of bytes to transfer */
|
||||
C_cal("__stb"); /* call transfer routine */
|
||||
C_asp(pointer_size + pointer_size + int_size + ATW(sz));
|
||||
#endif STB
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +96,23 @@ load_block(sz, al)
|
|||
if (al % word_align == 0)
|
||||
C_loi(esz);
|
||||
else {
|
||||
/* do not try to understand this... */
|
||||
#ifndef STB
|
||||
arith src, dst, src_offs, dst_offs;
|
||||
|
||||
/* allocate two pointer temporaries */
|
||||
src = tmp_pointer_var(&src_offs);
|
||||
dst = tmp_pointer_var(&dst_offs);
|
||||
|
||||
C_lal(src);
|
||||
C_sti(pointer_size);
|
||||
C_asp(-esz); /* allocate stack block */
|
||||
C_lor((arith)1); /* push & of stack block as dst */
|
||||
C_lal(dst);
|
||||
C_sti(pointer_size);
|
||||
copy_loop(sz, src, dst);
|
||||
free_tmp_var(dst_offs);
|
||||
free_tmp_var(src_offs);
|
||||
#else STB
|
||||
C_asp(-(esz - pointer_size)); /* allocate stack block */
|
||||
C_lor((arith)1); /* push & of stack block as dst */
|
||||
C_dup(pointer_size); /* fetch source address */
|
||||
|
@ -84,5 +121,38 @@ load_block(sz, al)
|
|||
C_loc(sz); /* # bytes to copy */
|
||||
C_cal("__stb"); /* library copy routine */
|
||||
C_asp(int_size + pointer_size + pointer_size);
|
||||
#endif STB
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef STB
|
||||
copy_loop(sz, src, dst)
|
||||
arith sz, src, dst;
|
||||
{
|
||||
/* generate inline byte-copy loop */
|
||||
label l_cont = text_label(), l_stop = text_label();
|
||||
|
||||
C_loc(sz); /* amount of bytes */
|
||||
C_df_ilb(l_cont);
|
||||
C_dup(word_size);
|
||||
C_zle(l_stop);
|
||||
C_dec();
|
||||
C_lal(src);
|
||||
C_loi(pointer_size);
|
||||
C_dup(pointer_size);
|
||||
C_adp((arith)1);
|
||||
C_lal(src);
|
||||
C_sti(pointer_size);
|
||||
C_loi((arith)1);
|
||||
C_lal(dst);
|
||||
C_loi(pointer_size);
|
||||
C_dup(pointer_size);
|
||||
C_adp((arith)1);
|
||||
C_lal(dst);
|
||||
C_sti(pointer_size);
|
||||
C_sti((arith)1);
|
||||
C_bra(l_cont);
|
||||
C_df_ilb(l_stop);
|
||||
C_asp(word_size);
|
||||
}
|
||||
#endif STB
|
||||
|
|
|
@ -121,11 +121,9 @@ ch7sel(expp, oper, idf)
|
|||
intexpr(sd->sd_offset, INT));
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* oper == ARROW */
|
||||
else /* oper == ARROW */
|
||||
*expp = new_oper(sd->sd_type,
|
||||
*expp, oper, intexpr(sd->sd_offset, INT));
|
||||
}
|
||||
(*expp)->ex_lvalue = (sd->sd_type->tp_fund != ARRAY);
|
||||
}
|
||||
|
||||
|
@ -135,44 +133,7 @@ ch7incr(expp, oper)
|
|||
/* The monadic prefix/postfix incr/decr operator oper is
|
||||
applied to *expp.
|
||||
*/
|
||||
arith addend;
|
||||
struct expr *expr;
|
||||
register int fund = (*expp)->ex_type->tp_fund;
|
||||
|
||||
if (!(*expp)->ex_lvalue) {
|
||||
expr_error(*expp, "no lvalue with %s", symbol2str(oper));
|
||||
return;
|
||||
}
|
||||
if (fund == ENUM) {
|
||||
expr_warning(*expp, "%s on enum", symbol2str(oper));
|
||||
addend = (arith)1;
|
||||
}
|
||||
else
|
||||
if (is_arith_type((*expp)->ex_type))
|
||||
addend = (arith)1;
|
||||
else
|
||||
if (fund == POINTER)
|
||||
addend = size_of_type((*expp)->ex_type->tp_up, "object");
|
||||
#ifndef NOBITFIELD
|
||||
else
|
||||
if (fund == FIELD)
|
||||
addend = (arith)1;
|
||||
#endif NOBITFIELD
|
||||
else {
|
||||
expr_error(*expp, "%s on %s",
|
||||
symbol2str(oper),
|
||||
symbol2str((*expp)->ex_type->tp_fund)
|
||||
);
|
||||
return;
|
||||
}
|
||||
expr = intexpr(addend, INT);
|
||||
ch7cast(&expr, CAST, (*expp)->ex_type);
|
||||
#ifndef NOBITFIELD
|
||||
if (fund == FIELD)
|
||||
*expp = new_oper((*expp)->ex_type->tp_up, *expp, oper, expr);
|
||||
else
|
||||
#endif NOBITFIELD
|
||||
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
|
||||
ch7asgn(expp, oper, intexpr((arith)1, INT));
|
||||
}
|
||||
|
||||
ch7cast(expp, oper, tp)
|
||||
|
@ -293,10 +254,8 @@ ch7cast(expp, oper, tp)
|
|||
(*expp)->ex_type = tp;
|
||||
}
|
||||
else
|
||||
if (oldtp->tp_fund == ERRONEOUS) {
|
||||
/* we just won't look */
|
||||
(*expp)->ex_type = tp; /* brute force */
|
||||
}
|
||||
if (oldtp->tp_fund == ERRONEOUS) /* we just won't look */
|
||||
(*expp)->ex_type = tp; /* brute force */
|
||||
else
|
||||
if (oldtp->tp_size == tp->tp_size && oper == CAST) {
|
||||
expr_warning(*expp, "dubious conversion based on equal size");
|
||||
|
@ -365,7 +324,6 @@ ch7asgn(expp, oper, expr)
|
|||
else
|
||||
expr = extmp;
|
||||
}
|
||||
|
||||
#ifndef NOBITFIELD
|
||||
if (fund == FIELD)
|
||||
*expp = new_oper((*expp)->ex_type->tp_up, *expp, oper, expr);
|
||||
|
@ -374,7 +332,6 @@ ch7asgn(expp, oper, expr)
|
|||
#else NOBITFIELD
|
||||
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
|
||||
#endif NOBITFIELD
|
||||
|
||||
(*expp)->OP_TYPE = tp; /* for EVAL() */
|
||||
}
|
||||
|
||||
|
|
|
@ -82,16 +82,6 @@ ch7bin(expp, oper, expr)
|
|||
break;
|
||||
case '%':
|
||||
case MODAB:
|
||||
/*** NB "not float" means "integral" !!!
|
||||
fund = arithbalance(expp, oper, &expr);
|
||||
if (fund == DOUBLE) {
|
||||
expr_error(*expp, "floating operand to %s",
|
||||
symbol2str(oper));
|
||||
erroneous2int(expp);
|
||||
}
|
||||
else
|
||||
non_commutative_binop(expp, oper, expr);
|
||||
***/
|
||||
opnd2integral(expp, oper);
|
||||
opnd2integral(&expr, oper);
|
||||
fund = arithbalance(expp, oper, &expr);
|
||||
|
@ -111,21 +101,19 @@ ch7bin(expp, oper, expr)
|
|||
non_commutative_binop(expp, oper, expr);
|
||||
break;
|
||||
case '+':
|
||||
if (expr->ex_type->tp_fund == POINTER) {
|
||||
/* swap operands */
|
||||
if (expr->ex_type->tp_fund == POINTER) { /* swap operands */
|
||||
struct expr *etmp = expr;
|
||||
expr = *expp;
|
||||
*expp = etmp;
|
||||
}
|
||||
/*FALLTHROUGH*/
|
||||
case PLUSAB:
|
||||
case POSTINCR:
|
||||
case PLUSPLUS:
|
||||
if ((*expp)->ex_type->tp_fund == POINTER) {
|
||||
pointer_arithmetic(expp, oper, &expr);
|
||||
if ( expr->ex_type->tp_size !=
|
||||
(*expp)->ex_type->tp_size
|
||||
) {
|
||||
if (expr->ex_type->tp_size != (*expp)->ex_type->tp_size)
|
||||
ch7cast(&expr, CAST, (*expp)->ex_type);
|
||||
}
|
||||
pointer_binary(expp, oper, expr);
|
||||
}
|
||||
else {
|
||||
|
@ -138,6 +126,8 @@ ch7bin(expp, oper, expr)
|
|||
break;
|
||||
case '-':
|
||||
case MINAB:
|
||||
case POSTDECR:
|
||||
case MINMIN:
|
||||
if ((*expp)->ex_type->tp_fund == POINTER) {
|
||||
if (expr->ex_type->tp_fund == POINTER)
|
||||
pntminuspnt(expp, oper, expr);
|
||||
|
@ -231,13 +221,11 @@ ch7bin(expp, oper, expr)
|
|||
if ( is_struct_or_union((*expp)->ex_type->tp_fund)
|
||||
|| is_struct_or_union(expr->ex_type->tp_fund)
|
||||
) {
|
||||
if ((*expp)->ex_type != expr->ex_type) {
|
||||
if ((*expp)->ex_type != expr->ex_type)
|
||||
expr_error(*expp, "illegal balance");
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
relbalance(expp, oper, &expr);
|
||||
}
|
||||
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
|
||||
break;
|
||||
case '?':
|
||||
|
|
|
@ -28,16 +28,15 @@
|
|||
#include "atw.h"
|
||||
#include "assert.h"
|
||||
|
||||
static struct stmt_block *stmt_stack;
|
||||
|
||||
char *symbol2str();
|
||||
#ifndef NOFLOAT
|
||||
int fp_used;
|
||||
#endif NOFLOAT
|
||||
label lab_count = 1;
|
||||
label datlab_count = 1;
|
||||
|
||||
#ifndef NOFLOAT
|
||||
int fp_used;
|
||||
#endif NOFLOAT
|
||||
|
||||
extern char options[];
|
||||
char *symbol2str();
|
||||
|
||||
init_code(dst_file)
|
||||
char *dst_file;
|
||||
|
@ -112,16 +111,11 @@ prepend_scopes(dst_file)
|
|||
fatal("cannot create %s", dst_file ? dst_file : "stdout");
|
||||
famous_first_words();
|
||||
while (se != 0) {
|
||||
register struct idf *idf = se->se_idf;
|
||||
register struct def *def = idf->id_def;
|
||||
register struct idf *id = se->se_idf;
|
||||
register struct def *df = id->id_def;
|
||||
|
||||
if (def &&
|
||||
( def->df_initialized ||
|
||||
def->df_used ||
|
||||
def->df_alloc
|
||||
)
|
||||
)
|
||||
code_scope(idf->id_text, def);
|
||||
if (df && (df->df_initialized || df->df_used || df->df_alloc))
|
||||
code_scope(id->id_text, df);
|
||||
se = se->next;
|
||||
}
|
||||
C_close();
|
||||
|
@ -198,7 +192,6 @@ begin_proc(name, def) /* to be called when entering a procedure */
|
|||
}
|
||||
else
|
||||
func_res_label = 0;
|
||||
|
||||
/* Special arrangements if the function result doesn't fit in
|
||||
the function return area of the EM machine. The size of
|
||||
the function return area is implementation dependent.
|
||||
|
@ -206,15 +199,12 @@ begin_proc(name, def) /* to be called when entering a procedure */
|
|||
lab_count = (label) 1;
|
||||
return_label = text_label();
|
||||
return_expr_occurred = 0;
|
||||
|
||||
if (options['p']) { /* profiling */
|
||||
if (strcmp(last_fn_given, FileName) != 0) {
|
||||
/* previous function came from other file */
|
||||
C_df_dlb(file_name_label = data_label());
|
||||
C_con_scon(
|
||||
last_fn_given = FileName,
|
||||
(arith)(strlen(FileName) + 1)
|
||||
);
|
||||
C_con_scon(last_fn_given = FileName,
|
||||
(arith)(strlen(FileName) + 1));
|
||||
}
|
||||
/* enable debug trace of EM source */
|
||||
C_fil_dlb(file_name_label, (arith)0);
|
||||
|
@ -345,17 +335,14 @@ code_declaration(idf, expr, lvl, sc)
|
|||
}
|
||||
else
|
||||
if (lvl >= L_LOCAL) { /* local variable */
|
||||
/* they are STATIC, EXTERN, GLOBAL, IMPLICIT, AUTO or
|
||||
REGISTER
|
||||
*/
|
||||
/* STATIC, EXTERN, GLOBAL, IMPLICIT, AUTO or REGISTER */
|
||||
switch (def_sc) {
|
||||
case STATIC:
|
||||
/* they are handled on the spot and get an
|
||||
integer label in EM.
|
||||
*/
|
||||
C_df_dlb((label)def->df_address);
|
||||
if (expr) {
|
||||
/* there is an initialisation */
|
||||
if (expr) { /* there is an initialisation */
|
||||
do_ival(&(def->df_type), expr);
|
||||
free_expression(expr);
|
||||
}
|
||||
|
@ -364,8 +351,7 @@ code_declaration(idf, expr, lvl, sc)
|
|||
error("size of %s unknown", text);
|
||||
size = (arith)0;
|
||||
}
|
||||
C_bss_cst(align(size, word_align),
|
||||
(arith)0, 1);
|
||||
C_bss_cst(align(size, word_align), (arith)0, 1);
|
||||
}
|
||||
break;
|
||||
case EXTERN:
|
||||
|
@ -399,7 +385,6 @@ loc_init(expr, id)
|
|||
register struct type *tp = id->id_def->df_type;
|
||||
|
||||
ASSERT(id->id_def->df_sc != STATIC);
|
||||
/* automatic aggregates cannot be initialised. */
|
||||
switch (tp->tp_fund) {
|
||||
case ARRAY:
|
||||
case STRUCT:
|
||||
|
@ -408,7 +393,6 @@ loc_init(expr, id)
|
|||
free_expression(expr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ISCOMMA(expr)) { /* embraced: int i = {12}; */
|
||||
if (options['R']) {
|
||||
if (ISCOMMA(expr->OP_LEFT)) /* int i = {{1}} */
|
||||
|
@ -463,14 +447,15 @@ formal_cvt(df)
|
|||
*/
|
||||
register struct type *tp = df->df_type;
|
||||
|
||||
if (tp->tp_size != int_size)
|
||||
if (tp->tp_fund == CHAR || tp->tp_fund == SHORT) {
|
||||
C_lol(df->df_address);
|
||||
conversion(int_type, df->df_type);
|
||||
C_lal(df->df_address);
|
||||
C_sti(tp->tp_size);
|
||||
df->df_register = REG_NONE;
|
||||
}
|
||||
if (tp->tp_size != int_size &&
|
||||
(tp->tp_fund == CHAR || tp->tp_fund == SHORT)
|
||||
) {
|
||||
C_lol(df->df_address);
|
||||
/* conversion(int_type, df->df_type); ??? */
|
||||
C_lal(df->df_address);
|
||||
C_sti(tp->tp_size);
|
||||
df->df_register = REG_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
code_expr(expr, val, code, tlbl, flbl)
|
||||
|
@ -478,8 +463,7 @@ code_expr(expr, val, code, tlbl, flbl)
|
|||
label tlbl, flbl;
|
||||
{
|
||||
/* code_expr() is the parser's interface to the expression code
|
||||
generator.
|
||||
If line number trace is wanted, it generates a
|
||||
generator. If line number trace is wanted, it generates a
|
||||
lin instruction. EVAL() is called directly.
|
||||
*/
|
||||
if (options['p']) /* profiling */
|
||||
|
@ -493,6 +477,8 @@ code_expr(expr, val, code, tlbl, flbl)
|
|||
EM labels where a subsequent break or continue causes
|
||||
the program to jump to.
|
||||
*/
|
||||
static struct stmt_block *stmt_stack; /* top of statement stack */
|
||||
|
||||
/* code_break() generates EM code needed at the occurrence of "break":
|
||||
it generates a branch instruction to the break label of the
|
||||
innermost statement in which break has a meaning.
|
||||
|
@ -504,11 +490,10 @@ code_break()
|
|||
{
|
||||
register struct stmt_block *stmt_block = stmt_stack;
|
||||
|
||||
if (stmt_block) {
|
||||
if (stmt_block)
|
||||
C_bra(stmt_block->st_break);
|
||||
return;
|
||||
}
|
||||
error("break not inside for, while, do or switch");
|
||||
else
|
||||
error("break not inside for, while, do or switch");
|
||||
}
|
||||
|
||||
/* code_continue() generates EM code needed at the occurrence of
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $Header$ */
|
||||
/* D E C L A R A T O R M A N I P U L A T I O N */
|
||||
|
||||
#include "botch_free.h" /* UF */
|
||||
#include "botch_free.h"
|
||||
#include "alloc.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "parbufsize.h"
|
||||
#include "textsize.h"
|
||||
#include "idfsize.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "alloc.h"
|
||||
#include "class.h"
|
||||
|
@ -301,14 +300,10 @@ PRIVATE
|
|||
do_elif()
|
||||
{
|
||||
if (nestlevel < 0 || (ifstack[nestlevel])) {
|
||||
/* invalid elif encountered.. */
|
||||
lexerror("#elif without corresponding #if");
|
||||
SkipRestOfLine();
|
||||
}
|
||||
else {
|
||||
/* restart at this level as if a #if
|
||||
is detected.
|
||||
*/
|
||||
else { /* restart at this level as if a #if is detected. */
|
||||
nestlevel--;
|
||||
push_if();
|
||||
skip_block();
|
||||
|
@ -377,8 +372,7 @@ do_undef()
|
|||
if (id && id->id_macro) { /* forget the macro */
|
||||
free_macro(id->id_macro);
|
||||
id->id_macro = (struct macro *) 0;
|
||||
}
|
||||
/* else: don't complain */
|
||||
} /* else: don't complain */
|
||||
}
|
||||
else
|
||||
lexerror("illegal #undef construction");
|
||||
|
@ -470,8 +464,7 @@ macro_def(id, text, nformals, length, flags)
|
|||
if (macroeq(newdef->mc_text, text))
|
||||
return;
|
||||
lexwarning("redefine \"%s\"", id->id_text);
|
||||
}
|
||||
/* else: overwrite pre-definition */
|
||||
} /* else: overwrite pre-definition */
|
||||
}
|
||||
else
|
||||
id->id_macro = newdef = new_macro();
|
||||
|
|
|
@ -1,17 +1,6 @@
|
|||
/* $Header$ */
|
||||
/* EXPRESSION-CODE GENERATOR */
|
||||
|
||||
/* main functions :
|
||||
EVAL() -- expression tree evaluator
|
||||
tmp_pointer_var() -- deliver temporary pointer variable
|
||||
free_tmp_var() -- return the pointer var
|
||||
store_val() -- store primary expression
|
||||
load_val() -- load primary expression
|
||||
auxiliary functions:
|
||||
assop()
|
||||
compare()
|
||||
*/
|
||||
|
||||
#include "nofloat.h"
|
||||
#include <em.h>
|
||||
#include "debug.h"
|
||||
|
@ -40,45 +29,40 @@ char *symbol2str();
|
|||
char *long2str();
|
||||
arith tmp_pointer_var();
|
||||
|
||||
/* EVAL() serves as the main expression tree evaluator, which turns
|
||||
any legal expression tree into legal EM code.
|
||||
The parameters describe how EVAL should treat the expression tree:
|
||||
/* EVAL() is the main expression-tree evaluator, which turns
|
||||
any legal expression tree into EM code. Parameters:
|
||||
|
||||
struct expr *expr: pointer to root of the expression tree to
|
||||
be evaluated
|
||||
struct expr *expr
|
||||
pointer to root of the expression tree to be evaluated
|
||||
|
||||
int val: indicates whether the resulting expression
|
||||
is to be dereferenced (if val == RVAL and
|
||||
expr->ex_lvalue == 1) or not (val == LVAL).
|
||||
The latter case indicates that the resulting
|
||||
expression is an lvalue expression which should
|
||||
not be dereferenced by EVAL
|
||||
int val
|
||||
indicates whether the resulting expression is to be
|
||||
dereferenced (if val == RVAL and expr->ex_lvalue == 1)
|
||||
or not (val == LVAL). The latter case indicates that
|
||||
the resulting expression is an lvalue expression which
|
||||
should not be dereferenced by EVAL
|
||||
|
||||
int code: indicates whether the expression tree must be
|
||||
turned into EM code or not. E.g. the expression
|
||||
statement "12;" delivers the expression "12" to
|
||||
EVAL while this should not result in any EM
|
||||
code
|
||||
int code
|
||||
indicates whether the expression tree must be turned
|
||||
into EM code or not. E.g. the expression statement "12;"
|
||||
delivers the expression "12" to EVAL while this should
|
||||
not result in any EM code
|
||||
|
||||
label false_label:
|
||||
label true_label: if the expression is a logical or relational
|
||||
expression and if the loop of the program
|
||||
depends on the resulting value then EVAL
|
||||
generates jumps to the specified program
|
||||
labels, in case they are specified
|
||||
(i.e. are non-zero)
|
||||
label false_label, label true_label
|
||||
if the expression is a logical or relational expression
|
||||
and if the loop of the program depends on the resulting
|
||||
value then EVAL generates jumps to the specified program
|
||||
labels, in case they are specified (i.e. are non-zero)
|
||||
*/
|
||||
|
||||
EVAL(expr, val, code, true_label, false_label)
|
||||
register struct expr *expr; /* the expression tree itself */
|
||||
int val; /* either RVAL or LVAL */
|
||||
int code; /* generate explicit code or not */
|
||||
label true_label;
|
||||
label false_label; /* labels to jump to in logical expr's */
|
||||
register struct expr *expr;
|
||||
int val, code;
|
||||
label true_label, false_label;
|
||||
{
|
||||
register int gencode = (code == TRUE);
|
||||
|
||||
switch (expr->ex_class) {
|
||||
switch (expr->ex_class) {
|
||||
case Value: /* just a simple value */
|
||||
if (gencode)
|
||||
load_val(expr, val);
|
||||
|
@ -107,23 +91,22 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
case Oper: /* compound expression */
|
||||
{
|
||||
int oper = expr->OP_OPER;
|
||||
register struct expr *leftop = expr->OP_LEFT;
|
||||
register struct expr *rightop = expr->OP_RIGHT;
|
||||
register struct expr *left = expr->OP_LEFT;
|
||||
register struct expr *right = expr->OP_RIGHT;
|
||||
register struct type *tp = expr->OP_TYPE;
|
||||
|
||||
if (tp->tp_fund == ERRONEOUS) /* stop immediately */
|
||||
break;
|
||||
switch (oper) {
|
||||
switch (oper) {
|
||||
case '+':
|
||||
/* We have the following possibilities :
|
||||
int + int, pointer + int, pointer + long,
|
||||
long + long, double + double
|
||||
*/
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode) {
|
||||
switch (tp->tp_fund) {
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
if (tp->tp_unsigned)
|
||||
|
@ -132,7 +115,7 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
C_adi(tp->tp_size);
|
||||
break;
|
||||
case POINTER:
|
||||
C_ads(rightop->ex_type->tp_size);
|
||||
C_ads(right->ex_type->tp_size);
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case DOUBLE:
|
||||
|
@ -145,10 +128,10 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
}
|
||||
break;
|
||||
case '-':
|
||||
if (leftop == 0) { /* unary */
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (left == 0) { /* unary */
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode) {
|
||||
switch (tp->tp_fund) {
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
case POINTER:
|
||||
|
@ -165,16 +148,15 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
}
|
||||
break;
|
||||
}
|
||||
/* Binary: we have the following flavours:
|
||||
/* else binary; we have the following flavours:
|
||||
int - int, pointer - int, pointer - long,
|
||||
pointer - pointer, long - long, double - double
|
||||
*/
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (!gencode)
|
||||
break;
|
||||
switch (tp->tp_fund) {
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
if (tp->tp_unsigned)
|
||||
|
@ -183,11 +165,11 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
C_sbi(tp->tp_size);
|
||||
break;
|
||||
case POINTER:
|
||||
if (rightop->ex_type->tp_fund == POINTER)
|
||||
if (right->ex_type->tp_fund == POINTER)
|
||||
C_sbs(pointer_size);
|
||||
else {
|
||||
C_ngi(rightop->ex_type->tp_size);
|
||||
C_ads(rightop->ex_type->tp_size);
|
||||
else {
|
||||
C_ngi(right->ex_type->tp_size);
|
||||
C_ads(right->ex_type->tp_size);
|
||||
}
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
|
@ -200,13 +182,13 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
}
|
||||
break;
|
||||
case '*':
|
||||
if (leftop == 0) /* unary */
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
else { /* binary */
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (left == 0) /* unary */
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
else { /* binary */
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
switch (tp->tp_fund) {
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
case POINTER:
|
||||
|
@ -226,10 +208,10 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
}
|
||||
break;
|
||||
case '/':
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
switch (tp->tp_fund) {
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
case POINTER:
|
||||
|
@ -248,8 +230,8 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
}
|
||||
break;
|
||||
case '%':
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
ASSERT(tp->tp_fund==INT || tp->tp_fund==LONG);
|
||||
if (gencode)
|
||||
if (tp->tp_unsigned)
|
||||
|
@ -258,8 +240,8 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
C_rmi(tp->tp_size);
|
||||
break;
|
||||
case LEFT:
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
if (tp->tp_unsigned)
|
||||
C_slu(tp->tp_size);
|
||||
|
@ -267,8 +249,8 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
C_sli(tp->tp_size);
|
||||
break;
|
||||
case RIGHT:
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
if (tp->tp_unsigned)
|
||||
C_sru(tp->tp_size);
|
||||
|
@ -281,16 +263,16 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
case GREATEREQ:
|
||||
case EQUAL:
|
||||
case NOTEQUAL:
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode) {
|
||||
/* The operands have the same type */
|
||||
arith size = leftop->ex_type->tp_size;
|
||||
arith size = left->ex_type->tp_size;
|
||||
|
||||
switch (tp->tp_fund) {
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
if (leftop->ex_type->tp_unsigned)
|
||||
if (left->ex_type->tp_unsigned)
|
||||
C_cmu(size);
|
||||
else
|
||||
C_cmi(size);
|
||||
|
@ -310,11 +292,11 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
default:
|
||||
CRASH();
|
||||
}
|
||||
if (true_label != 0) {
|
||||
if (true_label != 0) {
|
||||
compare(oper, true_label);
|
||||
C_bra(false_label);
|
||||
}
|
||||
else {
|
||||
else {
|
||||
label l_true = text_label();
|
||||
label l_end = text_label();
|
||||
|
||||
|
@ -331,14 +313,14 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
case '|':
|
||||
case '^':
|
||||
/* both operands should have type int */
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode) {
|
||||
arith size = tp->tp_size;
|
||||
|
||||
if (size < word_size)
|
||||
size = word_size;
|
||||
switch (oper) {
|
||||
switch (oper) {
|
||||
case '&':
|
||||
C_and(size);
|
||||
break;
|
||||
|
@ -353,26 +335,21 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
break;
|
||||
case '=':
|
||||
#ifndef NOBITFIELD
|
||||
if (leftop->ex_type->tp_fund == FIELD) {
|
||||
/* assignment to bitfield variable
|
||||
*/
|
||||
if (left->ex_type->tp_fund == FIELD) {
|
||||
eval_field(expr, code);
|
||||
break;
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
C_dup(ATW(tp->tp_size));
|
||||
|
||||
if (leftop->ex_class != Value) {
|
||||
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
if (left->ex_class != Value) {
|
||||
EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
store_block(tp->tp_size, tp->tp_align);
|
||||
}
|
||||
else
|
||||
store_val(
|
||||
&(leftop->ex_object.ex_value),
|
||||
leftop->ex_type
|
||||
);
|
||||
store_val(&(left->ex_object.ex_value),
|
||||
left->ex_type);
|
||||
break;
|
||||
case PLUSAB:
|
||||
case MINAB:
|
||||
|
@ -384,47 +361,60 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
case ANDAB:
|
||||
case XORAB:
|
||||
case ORAB:
|
||||
case POSTINCR:
|
||||
case POSTDECR:
|
||||
case PLUSPLUS:
|
||||
case MINMIN:
|
||||
{
|
||||
arith old_offset;
|
||||
arith tmpvar = tmp_pointer_var(&old_offset);
|
||||
|
||||
arith old_offset, tmp;
|
||||
int compl; /* Complexity of left operand */
|
||||
#ifndef NOBITFIELD
|
||||
if (leftop->ex_type->tp_fund == FIELD) {
|
||||
if (left->ex_type->tp_fund == FIELD) {
|
||||
eval_field(expr, code);
|
||||
break;
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
if (leftop->ex_class != Value) {
|
||||
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_lal(tmpvar);
|
||||
C_sti(pointer_size);
|
||||
C_lal(tmpvar);
|
||||
C_loi(pointer_size);
|
||||
C_loi(leftop->ex_type->tp_size);
|
||||
if (left->ex_class == Value) {
|
||||
compl = 0; /* Value */
|
||||
load_val(left, RVAL);
|
||||
}
|
||||
else {
|
||||
load_val(leftop, RVAL);
|
||||
}
|
||||
conversion(leftop->ex_type, tp);
|
||||
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
assop(tp, oper);
|
||||
conversion(tp, leftop->ex_type);
|
||||
if (gencode)
|
||||
C_dup(toword(leftop->ex_type->tp_size));
|
||||
if (leftop->ex_class != Value) {
|
||||
C_lal(tmpvar);
|
||||
C_loi(pointer_size);
|
||||
C_sti(leftop->ex_type->tp_size);
|
||||
free_tmp_var(old_offset);
|
||||
else
|
||||
if (left->ex_depth == 1 && left->OP_OPER == ARROW) {
|
||||
compl = 1; /* Value->sel */
|
||||
ASSERT(left->OP_LEFT->ex_class == Value);
|
||||
EVAL(left, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
}
|
||||
else {
|
||||
store_val(
|
||||
&(leftop->ex_object.ex_value),
|
||||
leftop->ex_type
|
||||
);
|
||||
compl = 2; /* otherwise */
|
||||
tmp = tmp_pointer_var(&old_offset);
|
||||
EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_dup(pointer_size);
|
||||
C_lal(tmp);
|
||||
C_sti(pointer_size);
|
||||
C_loi(left->ex_type->tp_size);
|
||||
}
|
||||
conversion(left->ex_type, tp);
|
||||
if (gencode && (oper == POSTINCR || oper == POSTDECR))
|
||||
C_dup(tp->tp_size);
|
||||
EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
assop(tp, oper);
|
||||
if (gencode && oper != POSTINCR && oper != POSTDECR)
|
||||
C_dup(tp->tp_size);
|
||||
conversion(tp, left->ex_type);
|
||||
if (compl == 0)
|
||||
store_val(&(left->ex_object.ex_value),
|
||||
left->ex_type);
|
||||
else
|
||||
if (compl == 1) {
|
||||
EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_sti(left->ex_type->tp_size);
|
||||
}
|
||||
else {
|
||||
C_lal(tmp); /* always init'd */
|
||||
C_loi(pointer_size);
|
||||
C_sti(left->ex_type->tp_size);
|
||||
free_tmp_var(old_offset);
|
||||
}
|
||||
if (gencode)
|
||||
conversion(leftop->ex_type, expr->ex_type);
|
||||
break;
|
||||
}
|
||||
case '(':
|
||||
|
@ -432,7 +422,7 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
register struct expr *ex;
|
||||
arith ParSize = (arith)0;
|
||||
|
||||
if ((ex = rightop) != NILEXPR) {
|
||||
if ((ex = right) != NILEXPR) {
|
||||
/* function call with parameters*/
|
||||
while ( ex->ex_class == Oper &&
|
||||
ex->OP_OPER == PARCOMMA
|
||||
|
@ -445,24 +435,19 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
EVAL(ex, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
ParSize += ATW(ex->ex_type->tp_size);
|
||||
}
|
||||
if ( leftop->ex_class == Value
|
||||
&& leftop->VL_CLASS == Name
|
||||
) {
|
||||
/* just an example:
|
||||
main() { (*((int (*)())0))(); }
|
||||
*/
|
||||
C_cal(leftop->VL_IDF->id_text);
|
||||
if (left->ex_class == Value && left->VL_CLASS == Name) {
|
||||
/* e.g., main() { (*((int (*)())0))(); } */
|
||||
C_cal(left->VL_IDF->id_text);
|
||||
#ifdef DATAFLOW
|
||||
{ extern char options[];
|
||||
if (options['d'])
|
||||
DfaCallFunction(
|
||||
leftop->VL_IDF->id_text
|
||||
);
|
||||
left->VL_IDF->id_text);
|
||||
}
|
||||
#endif DATAFLOW
|
||||
}
|
||||
else {
|
||||
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
else {
|
||||
EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_cai();
|
||||
}
|
||||
/* remove parameters from stack */
|
||||
|
@ -479,124 +464,53 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
break;
|
||||
}
|
||||
case '.':
|
||||
EVAL(leftop, LVAL, code, NO_LABEL, NO_LABEL);
|
||||
ASSERT(is_cp_cst(rightop));
|
||||
EVAL(left, LVAL, code, NO_LABEL, NO_LABEL);
|
||||
ASSERT(is_cp_cst(right));
|
||||
if (gencode)
|
||||
C_adp(rightop->VL_VALUE);
|
||||
C_adp(right->VL_VALUE);
|
||||
break;
|
||||
case ARROW:
|
||||
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
ASSERT(is_cp_cst(rightop));
|
||||
EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
ASSERT(is_cp_cst(right));
|
||||
if (gencode)
|
||||
C_adp(rightop->VL_VALUE);
|
||||
C_adp(right->VL_VALUE);
|
||||
break;
|
||||
case ',':
|
||||
EVAL(leftop, RVAL, FALSE, NO_LABEL, NO_LABEL);
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(left, RVAL, FALSE, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
break;
|
||||
case '~':
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
C_com(tp->tp_size);
|
||||
break;
|
||||
case POSTINCR:
|
||||
case POSTDECR:
|
||||
case PLUSPLUS:
|
||||
case MINMIN:
|
||||
{
|
||||
arith old_offset, tmp;
|
||||
arith esize = tp->tp_size;
|
||||
int compl; /* Complexity of left operand */
|
||||
#ifndef NOBITFIELD
|
||||
if (leftop->ex_type->tp_fund == FIELD) {
|
||||
eval_field(expr, code);
|
||||
break;
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
if (leftop->ex_class == Value) {
|
||||
compl = 0; /* Value */
|
||||
load_val(leftop, RVAL);
|
||||
}
|
||||
else
|
||||
if (leftop->ex_depth == 1 && leftop->OP_OPER == ARROW) {
|
||||
compl = 1; /* Value->sel */
|
||||
ASSERT(leftop->OP_LEFT->ex_class == Value);
|
||||
EVAL(leftop, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
}
|
||||
else {
|
||||
compl = 2; /* otherwise */
|
||||
tmp = tmp_pointer_var(&old_offset);
|
||||
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_dup(pointer_size);
|
||||
C_lal(tmp);
|
||||
C_sti(pointer_size);
|
||||
C_loi(esize);
|
||||
}
|
||||
|
||||
/* We made the choice to put this stuff here
|
||||
and not to put the conversion in the expression
|
||||
tree because this conversion is EM dependent
|
||||
and not described in C
|
||||
*/
|
||||
if (esize < word_size) {
|
||||
conversion(tp, word_type);
|
||||
esize = word_size;
|
||||
}
|
||||
|
||||
if (gencode && (oper == POSTINCR || oper == POSTDECR))
|
||||
C_dup(esize);
|
||||
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
assop(tp, oper);
|
||||
if (gencode && (oper == PLUSPLUS || oper == MINMIN))
|
||||
C_dup(esize);
|
||||
if (tp->tp_size < word_size)
|
||||
conversion(word_type, tp);
|
||||
if (compl == 0) {
|
||||
store_val(
|
||||
&(leftop->ex_object.ex_value),
|
||||
leftop->ex_type
|
||||
);
|
||||
}
|
||||
else
|
||||
if (compl == 1) {
|
||||
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_sti(tp->tp_size);
|
||||
}
|
||||
else {
|
||||
C_lal(tmp); /* always init'd */
|
||||
C_loi(pointer_size);
|
||||
C_sti(tp->tp_size);
|
||||
free_tmp_var(old_offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '?': /* must be followed by ':' */
|
||||
{
|
||||
label l_true = text_label();
|
||||
label l_false = text_label();
|
||||
label l_end = text_label();
|
||||
|
||||
EVAL(leftop, RVAL, TRUE, l_true, l_false);
|
||||
EVAL(left, RVAL, TRUE, l_true, l_false);
|
||||
C_df_ilb(l_true);
|
||||
EVAL(rightop->OP_LEFT, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right->OP_LEFT, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
C_bra(l_end);
|
||||
C_df_ilb(l_false);
|
||||
EVAL(rightop->OP_RIGHT, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right->OP_RIGHT, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
C_df_ilb(l_end);
|
||||
break;
|
||||
}
|
||||
case AND:
|
||||
if (true_label == 0) {
|
||||
if (true_label == 0) {
|
||||
label l_true = text_label();
|
||||
label l_false = text_label();
|
||||
label l_maybe = text_label();
|
||||
label l_end = text_label();
|
||||
|
||||
EVAL(leftop, RVAL, TRUE, l_maybe, l_false);
|
||||
EVAL(left, RVAL, TRUE, l_maybe, l_false);
|
||||
C_df_ilb(l_maybe);
|
||||
if (gencode) {
|
||||
EVAL(rightop, RVAL, TRUE,
|
||||
l_true, l_false);
|
||||
if (gencode) {
|
||||
EVAL(right, RVAL, TRUE, l_true,
|
||||
l_false);
|
||||
C_df_ilb(l_true);
|
||||
C_loc((arith)1);
|
||||
C_bra(l_end);
|
||||
|
@ -605,32 +519,32 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
C_df_ilb(l_end);
|
||||
}
|
||||
else {
|
||||
EVAL(rightop, RVAL, FALSE, l_false,
|
||||
EVAL(right, RVAL, FALSE, l_false,
|
||||
l_false);
|
||||
C_df_ilb(l_false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
label l_maybe = text_label();
|
||||
|
||||
EVAL(leftop, RVAL, TRUE, l_maybe, false_label);
|
||||
EVAL(left, RVAL, TRUE, l_maybe, false_label);
|
||||
C_df_ilb(l_maybe);
|
||||
EVAL(rightop, RVAL, code, true_label,
|
||||
EVAL(right, RVAL, code, true_label,
|
||||
false_label);
|
||||
}
|
||||
break;
|
||||
case OR:
|
||||
if (true_label == 0) {
|
||||
if (true_label == 0) {
|
||||
label l_true = text_label();
|
||||
label l_false = text_label();
|
||||
label l_maybe = text_label();
|
||||
label l_end = text_label();
|
||||
|
||||
EVAL(leftop, RVAL, TRUE, l_true, l_maybe);
|
||||
EVAL(left, RVAL, TRUE, l_true, l_maybe);
|
||||
C_df_ilb(l_maybe);
|
||||
if (gencode) {
|
||||
EVAL(rightop, RVAL, TRUE,
|
||||
l_true, l_false);
|
||||
if (gencode) {
|
||||
EVAL(right, RVAL, TRUE, l_true,
|
||||
l_false);
|
||||
C_df_ilb(l_false);
|
||||
C_loc((arith)0);
|
||||
C_bra(l_end);
|
||||
|
@ -638,30 +552,30 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
C_loc((arith)1);
|
||||
C_df_ilb(l_end);
|
||||
}
|
||||
else {
|
||||
EVAL(rightop, RVAL, FALSE, l_true,
|
||||
else {
|
||||
EVAL(right, RVAL, FALSE, l_true,
|
||||
l_true);
|
||||
C_df_ilb(l_true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
label l_maybe = text_label();
|
||||
|
||||
EVAL(leftop, RVAL, TRUE, true_label, l_maybe);
|
||||
EVAL(left, RVAL, TRUE, true_label, l_maybe);
|
||||
C_df_ilb(l_maybe);
|
||||
EVAL(rightop, RVAL, code, true_label,
|
||||
EVAL(right, RVAL, code, true_label,
|
||||
false_label);
|
||||
}
|
||||
break;
|
||||
case '!':
|
||||
if (true_label == 0) {
|
||||
if (gencode) {
|
||||
if (true_label == 0) {
|
||||
if (gencode) {
|
||||
label l_true = text_label();
|
||||
label l_false = text_label();
|
||||
label l_end = text_label();
|
||||
|
||||
EVAL(rightop, RVAL, TRUE,
|
||||
l_false, l_true);
|
||||
EVAL(right, RVAL, TRUE, l_false,
|
||||
l_true);
|
||||
C_df_ilb(l_false);
|
||||
C_loc((arith)0);
|
||||
C_bra(l_end);
|
||||
|
@ -670,11 +584,11 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
C_df_ilb(l_end);
|
||||
}
|
||||
else
|
||||
EVAL(rightop, RVAL, FALSE,
|
||||
NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, FALSE, NO_LABEL,
|
||||
NO_LABEL);
|
||||
}
|
||||
else
|
||||
EVAL(rightop, RVAL, code, false_label,
|
||||
EVAL(right, RVAL, code, false_label,
|
||||
true_label);
|
||||
break;
|
||||
case INT2INT:
|
||||
|
@ -683,14 +597,13 @@ EVAL(expr, val, code, true_label, false_label)
|
|||
case FLOAT2INT:
|
||||
case FLOAT2FLOAT:
|
||||
#endif NOFLOAT
|
||||
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
conversion(rightop->ex_type, leftop->ex_type);
|
||||
conversion(right->ex_type, left->ex_type);
|
||||
break;
|
||||
default:
|
||||
crash("(EVAL) bad operator %s\n", symbol2str(oper));
|
||||
}
|
||||
|
||||
/* If the rvalue of the expression is required but
|
||||
only its lvalue is evaluated, its rvalue is
|
||||
loaded by the following statements:
|
||||
|
@ -710,7 +623,7 @@ compare(relop, lbl)
|
|||
int relop;
|
||||
label lbl;
|
||||
{
|
||||
switch (relop) {
|
||||
switch (relop) {
|
||||
case '<':
|
||||
C_zlt(lbl);
|
||||
break;
|
||||
|
@ -744,13 +657,13 @@ assop(type, oper)
|
|||
|
||||
if ((size = type->tp_size) < word_size)
|
||||
size = word_size;
|
||||
switch (type->tp_fund) {
|
||||
switch (type->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
case LONG:
|
||||
case ENUM:
|
||||
switch (oper) {
|
||||
switch (oper) {
|
||||
case PLUSAB:
|
||||
case PLUSPLUS:
|
||||
case POSTINCR:
|
||||
|
@ -811,7 +724,7 @@ assop(type, oper)
|
|||
#ifndef NOFLOAT
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
switch (oper) {
|
||||
switch (oper) {
|
||||
case PLUSAB:
|
||||
case PLUSPLUS:
|
||||
case POSTINCR:
|
||||
|
@ -888,21 +801,19 @@ store_val(vl, tp)
|
|||
register int indword;
|
||||
arith val = vl->vl_value;
|
||||
|
||||
if (vl->vl_class == Const) { /* absolute addressing */
|
||||
if (vl->vl_class == Const) { /* absolute addressing */
|
||||
load_cst(val, pointer_size);
|
||||
store_block(size, tpalign);
|
||||
return;
|
||||
}
|
||||
|
||||
al_on_word = (tpalign % word_align == 0);
|
||||
if (!(inword = (size == word_size && al_on_word)))
|
||||
indword = (size == dword_size && al_on_word);
|
||||
|
||||
if (vl->vl_class == Name) {
|
||||
if (vl->vl_class == Name) {
|
||||
register struct idf *id = vl->vl_data.vl_idf;
|
||||
register struct def *df = id->id_def;
|
||||
|
||||
if (df->df_level == L_GLOBAL) {
|
||||
if (df->df_level == L_GLOBAL) {
|
||||
if (inword)
|
||||
C_ste_dnam(id->id_text, val);
|
||||
else
|
||||
|
@ -920,7 +831,7 @@ store_val(vl, tp)
|
|||
else
|
||||
if (indword)
|
||||
C_sdl(df->df_address + val);
|
||||
else {
|
||||
else {
|
||||
C_lal(df->df_address + val);
|
||||
store_block(size, tpalign);
|
||||
df->df_register = REG_NONE;
|
||||
|
@ -965,8 +876,8 @@ load_val(expr, val)
|
|||
register int inword, indword;
|
||||
arith val = expr->VL_VALUE;
|
||||
|
||||
if (expr->VL_CLASS == Const) {
|
||||
if (rvalue) { /* absolute addressing */
|
||||
if (expr->VL_CLASS == Const) {
|
||||
if (rvalue) { /* absolute addressing */
|
||||
load_cst(val, pointer_size);
|
||||
load_block(size, tpalign);
|
||||
}
|
||||
|
@ -980,7 +891,7 @@ load_val(expr, val)
|
|||
indword = (size == dword_size && al_on_word);
|
||||
}
|
||||
if (expr->VL_CLASS == Label) {
|
||||
if (rvalue) {
|
||||
if (rvalue) {
|
||||
if (inword)
|
||||
C_loe_dlb(expr->VL_LBL, val);
|
||||
else
|
||||
|
@ -992,7 +903,7 @@ load_val(expr, val)
|
|||
}
|
||||
|
||||
}
|
||||
else {
|
||||
else {
|
||||
C_lae_dlb(expr->VL_LBL, (arith)0);
|
||||
C_adp(val);
|
||||
}
|
||||
|
@ -1010,8 +921,8 @@ load_val(expr, val)
|
|||
*/
|
||||
C_lpi(id->id_text);
|
||||
else
|
||||
if (df->df_level == L_GLOBAL) {
|
||||
if (rvalue) {
|
||||
if (df->df_level == L_GLOBAL) {
|
||||
if (rvalue) {
|
||||
if (inword)
|
||||
C_loe_dnam(id->id_text, val);
|
||||
else
|
||||
|
@ -1022,14 +933,14 @@ load_val(expr, val)
|
|||
load_block(size, tpalign);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
C_lae_dnam(id->id_text, (arith)0);
|
||||
C_adp(val);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
ASSERT(df->df_sc != STATIC);
|
||||
if (rvalue) {
|
||||
if (rvalue) {
|
||||
if (inword)
|
||||
C_lol(df->df_address + val);
|
||||
else
|
||||
|
@ -1041,7 +952,7 @@ load_val(expr, val)
|
|||
df->df_register = REG_NONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
C_lal(df->df_address);
|
||||
C_adp(val);
|
||||
df->df_register = REG_NONE;
|
||||
|
|
|
@ -92,14 +92,14 @@ rank_of(oper)
|
|||
}
|
||||
|
||||
int
|
||||
rank_of_expression(expr)
|
||||
register struct expr *expr;
|
||||
rank_of_expression(ex)
|
||||
register struct expr *ex;
|
||||
{
|
||||
/* Returns the rank of the top node in the expression.
|
||||
*/
|
||||
if (!expr || (expr->ex_flags & EX_PARENS) || expr->ex_class != Oper)
|
||||
if (!ex || (ex->ex_flags & EX_PARENS) || ex->ex_class != Oper)
|
||||
return 0;
|
||||
return rank_of(expr->OP_OPER);
|
||||
return rank_of(ex->OP_OPER);
|
||||
}
|
||||
|
||||
check_conditional(expr, oper, pos_descr)
|
||||
|
@ -158,15 +158,12 @@ idf2expr(expr)
|
|||
register struct def *def = idf->id_def;
|
||||
|
||||
if (def == 0) {
|
||||
if (AHEAD == '(') {
|
||||
/* Function call, so declare the name IMPLICITly. */
|
||||
/* See RM 13. */
|
||||
add_def(idf, IMPLICIT, funint_type, level);
|
||||
}
|
||||
if (AHEAD == '(') /* function call, declare name IMPLICITly */
|
||||
add_def(idf, IMPLICIT, funint_type, level); /* RM 13 */
|
||||
else {
|
||||
if (!is_anon_idf(idf))
|
||||
error("%s undefined", idf->id_text);
|
||||
/* Declare the idf anyway */
|
||||
/* declare idf anyway */
|
||||
add_def(idf, 0, error_type, level);
|
||||
}
|
||||
def = idf->id_def;
|
||||
|
@ -254,25 +251,24 @@ intexpr(ivalue, fund)
|
|||
clear((char *)expr, sizeof(struct expr));
|
||||
expr->ex_file = dot.tk_file;
|
||||
expr->ex_line = dot.tk_line;
|
||||
|
||||
fill_int_expr(expr, ivalue, fund);
|
||||
return expr;
|
||||
}
|
||||
|
||||
fill_int_expr(expr, ivalue, fund)
|
||||
register struct expr *expr;
|
||||
fill_int_expr(ex, ivalue, fund)
|
||||
register struct expr *ex;
|
||||
arith ivalue;
|
||||
int fund;
|
||||
{
|
||||
/* Details derived from ivalue and fund are put into the
|
||||
constant integer expression expr.
|
||||
constant integer expression ex.
|
||||
*/
|
||||
switch (fund) {
|
||||
case INT:
|
||||
expr->ex_type = int_type;
|
||||
ex->ex_type = int_type;
|
||||
break;
|
||||
case LONG:
|
||||
expr->ex_type = long_type;
|
||||
ex->ex_type = long_type;
|
||||
break;
|
||||
case UNSIGNED:
|
||||
/* We cannot make a test like
|
||||
|
@ -284,20 +280,18 @@ fill_int_expr(expr, ivalue, fund)
|
|||
answer. We assume that the type "unsigned long"
|
||||
is not part of portable C !
|
||||
*/
|
||||
expr->ex_type =
|
||||
(ivalue & ~max_unsigned) ? long_type : uint_type;
|
||||
ex->ex_type = (ivalue & ~max_unsigned) ? long_type : uint_type;
|
||||
break;
|
||||
case INTEGER:
|
||||
expr->ex_type = (ivalue <= max_int) ? int_type : long_type;
|
||||
ex->ex_type = (ivalue <= max_int) ? int_type : long_type;
|
||||
break;
|
||||
default:
|
||||
crash("(intexpr) bad fund %s\n", symbol2str(fund));
|
||||
}
|
||||
expr->ex_class = Value;
|
||||
expr->VL_CLASS = Const;
|
||||
expr->VL_VALUE = ivalue;
|
||||
|
||||
cut_size(expr);
|
||||
ex->ex_class = Value;
|
||||
ex->VL_CLASS = Const;
|
||||
ex->VL_VALUE = ivalue;
|
||||
cut_size(ex);
|
||||
}
|
||||
|
||||
struct expr *
|
||||
|
@ -344,8 +338,7 @@ new_oper(tp, e1, oper, e2)
|
|||
int e1_flags = e1 ? e1->ex_flags : 0;
|
||||
|
||||
expr->ex_depth =
|
||||
(e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth)
|
||||
+ 1;
|
||||
(e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + 1;
|
||||
expr->ex_flags = (e1_flags | e2->ex_flags) & ~EX_PARENS;
|
||||
}
|
||||
op = &expr->ex_object.ex_oper;
|
||||
|
@ -353,7 +346,6 @@ new_oper(tp, e1, oper, e2)
|
|||
op->op_oper = oper;
|
||||
op->op_left = e1;
|
||||
op->op_right = e2;
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
@ -397,17 +389,14 @@ chk_cst_expr(expp)
|
|||
#endif DEBUG
|
||||
if ( fund != CHAR && fund != SHORT && fund != INT &&
|
||||
fund != ENUM && fund != LONG
|
||||
) {
|
||||
)
|
||||
expr_error(expr, "non-numerical constant expression"), err++;
|
||||
}
|
||||
else
|
||||
if (!is_ld_cst(expr))
|
||||
expr_error(expr, "expression is not constant"), err++;
|
||||
|
||||
if (options['R']) {
|
||||
if (flags & EX_CAST)
|
||||
expr_warning(expr,
|
||||
"cast in constant expression");
|
||||
expr_warning(expr, "cast in constant expression");
|
||||
if (flags & EX_LOGICAL)
|
||||
expr_warning(expr,
|
||||
"logical operator in constant expression");
|
||||
|
@ -475,11 +464,11 @@ free_expression(expr)
|
|||
{
|
||||
/* The expression expr is freed recursively.
|
||||
*/
|
||||
if (!expr)
|
||||
return;
|
||||
if (expr->ex_class == Oper) {
|
||||
free_expression(expr->OP_LEFT);
|
||||
free_expression(expr->OP_RIGHT);
|
||||
if (expr) {
|
||||
if (expr->ex_class == Oper) {
|
||||
free_expression(expr->OP_LEFT);
|
||||
free_expression(expr->OP_RIGHT);
|
||||
}
|
||||
free_expr(expr);
|
||||
}
|
||||
free_expr(expr);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
#ifndef NOBITFIELD
|
||||
#include <em.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "idf.h"
|
||||
|
@ -27,39 +25,33 @@ char *symbol2str(); /* symbol2str.c */
|
|||
tree and are therefore dealt with in this function.
|
||||
The actions taken at any operation are described clearly by the
|
||||
code for this actions.
|
||||
Note: the bitfields are packed in target machine integers!
|
||||
Notes
|
||||
[1] the bitfields are packed in target machine integers!
|
||||
[2] op is either an assignment operator or an increment/
|
||||
decrement operator
|
||||
[3] atype: the type in which the bitfield arithmetic is done;
|
||||
and in which bitfields are stored!
|
||||
*/
|
||||
eval_field(expr, code)
|
||||
struct expr *expr;
|
||||
int code;
|
||||
{
|
||||
int op = expr->OP_OPER;
|
||||
struct expr *leftop = expr->OP_LEFT;
|
||||
struct expr *rightop = expr->OP_RIGHT;
|
||||
struct field *fd = leftop->ex_type->tp_field;
|
||||
register struct expr *leftop = expr->OP_LEFT;
|
||||
register struct expr *rightop = expr->OP_RIGHT;
|
||||
register struct field *fd = leftop->ex_type->tp_field;
|
||||
struct type *tp = leftop->ex_type->tp_up;
|
||||
arith old_offset, tmpvar;
|
||||
|
||||
/* The type in which the bitfield arithmetic is done;
|
||||
AND IN WHICH BITFIELDS ARE STORED!
|
||||
*/
|
||||
struct type *atype = tp->tp_unsigned ? uword_type : word_type;
|
||||
arith asize = atype->tp_size;
|
||||
|
||||
/* First some assertions to be sure that the rest is legal */
|
||||
ASSERT(asize == word_size); /* make sure that C_loc() is legal */
|
||||
ASSERT(leftop->ex_type->tp_fund == FIELD);
|
||||
|
||||
leftop->ex_type = atype; /* this is cheating but it works... */
|
||||
|
||||
/* Note that op is either an assignment operator or an increment/
|
||||
decrement operator
|
||||
*/
|
||||
if (op == '=') {
|
||||
/* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f)
|
||||
*/
|
||||
/* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f) */
|
||||
ASSERT(tp == rightop->ex_type);
|
||||
|
||||
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
conversion(tp, atype);
|
||||
C_loc(fd->fd_mask);
|
||||
|
@ -116,10 +108,9 @@ eval_field(expr, code)
|
|||
C_and(asize);
|
||||
if (code == TRUE && (op == POSTINCR || op == POSTDECR))
|
||||
C_dup(asize);
|
||||
|
||||
/* the 'op' operation: */
|
||||
conversion(atype, rightop->ex_type);
|
||||
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
/* the 'op' operation: */
|
||||
if (op == PLUSPLUS || op == POSTINCR)
|
||||
assop(rightop->ex_type, PLUSAB);
|
||||
else
|
||||
|
@ -128,7 +119,6 @@ eval_field(expr, code)
|
|||
else
|
||||
assop(rightop->ex_type, op);
|
||||
conversion(rightop->ex_type, atype);
|
||||
|
||||
C_loc(fd->fd_mask);
|
||||
C_and(asize);
|
||||
if (code == TRUE && op != POSTINCR && op != POSTDECR)
|
||||
|
|
|
@ -201,7 +201,6 @@ declare_idf(ds, dc, lvl)
|
|||
/* some additional work for formal definitions */
|
||||
if (lvl == L_FORMAL2) {
|
||||
switch (type->tp_fund) {
|
||||
|
||||
case FUNCTION:
|
||||
warning("%s is a function; cannot be formal",
|
||||
idf->id_text);
|
||||
|
@ -227,7 +226,6 @@ declare_idf(ds, dc, lvl)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The tests on types, postponed from do_decspecs(), can now
|
||||
be performed.
|
||||
*/
|
||||
|
@ -241,23 +239,15 @@ declare_idf(ds, dc, lvl)
|
|||
ds->ds_sc = sc = GLOBAL;
|
||||
}
|
||||
}
|
||||
else { /* non-FUNCTION */
|
||||
else /* non-FUNCTION */
|
||||
if (sc == 0)
|
||||
sc =
|
||||
lvl == L_GLOBAL ?
|
||||
GLOBAL :
|
||||
lvl == L_FORMAL1 || lvl == L_FORMAL2 ?
|
||||
FORMAL :
|
||||
AUTO;
|
||||
}
|
||||
|
||||
if (options['R']) {
|
||||
/* some special K & R tests */
|
||||
|
||||
sc = lvl == L_GLOBAL ? GLOBAL
|
||||
: lvl == L_FORMAL1 || lvl == L_FORMAL2 ? FORMAL
|
||||
: AUTO;
|
||||
if (options['R']) { /* some special K & R tests */
|
||||
/* is it also an enum? */
|
||||
if (idf->id_enum && idf->id_enum->tg_level == level)
|
||||
warning("%s is also an enum tag", idf->id_text);
|
||||
|
||||
/* is it a universal typedef? */
|
||||
if (def && def->df_level == L_UNIVERSAL)
|
||||
warning("redeclaring reserved word %s", idf->id_text);
|
||||
|
@ -299,15 +289,13 @@ declare_idf(ds, dc, lvl)
|
|||
*/
|
||||
if ( options['R'] &&
|
||||
(sc == STATIC && type->tp_fund == FUNCTION)
|
||||
) {
|
||||
)
|
||||
if (!is_anon_idf(idf))
|
||||
warning("non-global static function %s",
|
||||
idf->id_text);
|
||||
}
|
||||
declare_idf(ds, dc, L_GLOBAL);
|
||||
}
|
||||
else {
|
||||
/* fill in the def block */
|
||||
else { /* fill in the def block */
|
||||
register struct def *newdef = new_def();
|
||||
|
||||
clear((char *)newdef, sizeof(struct def));
|
||||
|
@ -315,24 +303,19 @@ declare_idf(ds, dc, lvl)
|
|||
newdef->df_level = lvl;
|
||||
newdef->df_type = type;
|
||||
newdef->df_sc = sc;
|
||||
|
||||
/* link it into the name list in the proper place */
|
||||
idf->id_def = newdef;
|
||||
update_ahead(idf);
|
||||
stack_idf(idf, stl);
|
||||
|
||||
/* We now calculate the address.
|
||||
Globals have names and don't get addresses, they
|
||||
get numbers instead (through data_label()).
|
||||
Formals are handled by declare_formals().
|
||||
So here we hand out local addresses only.
|
||||
*/
|
||||
|
||||
if (lvl >= L_LOCAL) {
|
||||
ASSERT(sc);
|
||||
switch (sc) {
|
||||
case 0:
|
||||
crash("local sc == 0");
|
||||
break;
|
||||
case REGISTER:
|
||||
case AUTO:
|
||||
if (type->tp_size == (arith)-1) {
|
||||
|
@ -341,8 +324,8 @@ declare_idf(ds, dc, lvl)
|
|||
/** type = idf->id_def->df_type = int_type; **/
|
||||
}
|
||||
idf->id_def->df_register =
|
||||
(sc == REGISTER)
|
||||
? REG_BONUS : REG_DEFAULT;
|
||||
(sc == REGISTER) ? REG_BONUS
|
||||
: REG_DEFAULT;
|
||||
idf->id_def->df_address =
|
||||
stl->sl_max_block =
|
||||
stl->sl_local_offset =
|
||||
|
@ -358,17 +341,17 @@ declare_idf(ds, dc, lvl)
|
|||
}
|
||||
|
||||
actual_declaration(sc, tp)
|
||||
int sc;
|
||||
struct type *tp;
|
||||
{
|
||||
/* An actual_declaration needs space, right here and now.
|
||||
*/
|
||||
register int fund = tp->tp_fund;
|
||||
|
||||
/* virtual declarations */
|
||||
if (sc == ENUM || sc == TYPEDEF)
|
||||
if (sc == ENUM || sc == TYPEDEF) /* virtual declarations */
|
||||
return 0;
|
||||
/* allocation solved in other ways */
|
||||
if (fund == FUNCTION || fund == ARRAY)
|
||||
/* allocation solved in other ways */
|
||||
return 0;
|
||||
/* to be allocated */
|
||||
return 1;
|
||||
|
@ -388,7 +371,6 @@ global_redecl(idf, new_sc, tp)
|
|||
|
||||
if (tp != def->df_type) {
|
||||
register struct type *otp = def->df_type;
|
||||
|
||||
if ( tp->tp_fund != ARRAY || otp->tp_fund != ARRAY ||
|
||||
tp->tp_up != otp->tp_up
|
||||
) {
|
||||
|
@ -409,9 +391,8 @@ global_redecl(idf, new_sc, tp)
|
|||
error("inconsistent size in redeclaration of array %s",
|
||||
idf->id_text);
|
||||
}
|
||||
|
||||
/* Now we may be able to update the storage class. */
|
||||
/* Clean out this mess as soon as we know all the possibilities
|
||||
/* Now we may be able to update the storage class.
|
||||
Clean out this mess as soon as we know all the possibilities
|
||||
for new_sc.
|
||||
For now we have:
|
||||
EXTERN: we have seen the word "extern"
|
||||
|
@ -424,7 +405,6 @@ global_redecl(idf, new_sc, tp)
|
|||
*/
|
||||
if (new_sc == IMPLICIT)
|
||||
return; /* no new information */
|
||||
|
||||
switch (def->df_sc) { /* the old storage class */
|
||||
case EXTERN:
|
||||
switch (new_sc) { /* the new storage class */
|
||||
|
@ -456,10 +436,9 @@ global_redecl(idf, new_sc, tp)
|
|||
case GLOBAL:
|
||||
break;
|
||||
case STATIC:
|
||||
if (def->df_initialized) {
|
||||
if (def->df_initialized)
|
||||
error("cannot redeclare %s to static",
|
||||
idf->id_text);
|
||||
}
|
||||
else {
|
||||
if (options['R'])
|
||||
warning("%s redeclared to static",
|
||||
|
@ -475,10 +454,9 @@ global_redecl(idf, new_sc, tp)
|
|||
case STATIC:
|
||||
switch (new_sc) { /* the new storage class */
|
||||
case EXTERN:
|
||||
if (def->df_initialized) {
|
||||
if (def->df_initialized)
|
||||
error("cannot redeclare %s to extern",
|
||||
idf->id_text);
|
||||
}
|
||||
else {
|
||||
warning("%s redeclared to extern",
|
||||
idf->id_text);
|
||||
|
@ -531,11 +509,9 @@ good_formal(def, idf)
|
|||
/* Succeeds if def is a proper L_FORMAL1 definition and
|
||||
gives an error message otherwise.
|
||||
*/
|
||||
if (!def || def->df_level != L_FORMAL1) {
|
||||
/* not in parameter list */
|
||||
if (!def || def->df_level != L_FORMAL1) { /* not in parameter list */
|
||||
if (!is_anon_idf(idf))
|
||||
error("%s not in parameter list",
|
||||
idf->id_text);
|
||||
error("%s not in parameter list", idf->id_text);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
@ -610,17 +586,12 @@ declare_formals(fp)
|
|||
register struct def *def = se->se_idf->id_def;
|
||||
|
||||
def->df_address = f_offset;
|
||||
|
||||
/* the alignment convention for parameters is: align on
|
||||
word boundaries, i.e. take care that the following
|
||||
parameter starts on a new word boundary.
|
||||
*/
|
||||
f_offset = align(f_offset + def->df_type->tp_size, word_align);
|
||||
|
||||
/* the following is absurd: any char or short formal
|
||||
must be converted from integer to that type
|
||||
*/
|
||||
formal_cvt(def);
|
||||
formal_cvt(def); /* cvt int to char or short, if necessary */
|
||||
se = se->next;
|
||||
}
|
||||
*fp = f_offset;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
char *symbol2str();
|
||||
char *long2str();
|
||||
|
||||
struct expr *do_array(), *do_struct(), *IVAL();
|
||||
|
||||
/* do_ival() performs the initialisation of a global variable
|
||||
|
@ -58,26 +57,23 @@ IVAL(tpp, ex)
|
|||
register struct type *tp = *tpp;
|
||||
|
||||
switch (tp->tp_fund) {
|
||||
case ARRAY:
|
||||
/* array initialisation */
|
||||
case ARRAY: /* array initialisation */
|
||||
if (valid_type(tp->tp_up, "array element") == 0)
|
||||
return 0;
|
||||
if (ISCOMMA(ex)) /* list of initialisation expressions */
|
||||
return do_array(ex, tpp);
|
||||
/* catch initialisations like char s[] = "I am a string" */
|
||||
if (tp->tp_up->tp_fund == CHAR && ex->ex_class == String)
|
||||
/* initialisation like char s[] = "I am a string" */
|
||||
ch_array(tpp, ex);
|
||||
else /* " int i[24] = 12;" */
|
||||
check_and_pad(ex, tpp);
|
||||
break;
|
||||
case STRUCT:
|
||||
/* struct initialisation */
|
||||
case STRUCT: /* struct initialisation */
|
||||
if (valid_type(tp, "struct") == 0)
|
||||
return 0;
|
||||
if (ISCOMMA(ex)) /* list of initialisation expressions */
|
||||
return do_struct(ex, tp);
|
||||
/* "struct foo f = 12;" */
|
||||
check_and_pad(ex, tpp);
|
||||
check_and_pad(ex, tpp); /* "struct foo f = 12;" */
|
||||
break;
|
||||
case UNION:
|
||||
error("union initialisation not allowed");
|
||||
|
@ -85,7 +81,7 @@ IVAL(tpp, ex)
|
|||
case ERRONEOUS:
|
||||
break;
|
||||
default: /* fundamental type */
|
||||
if (ISCOMMA(ex)) { /* " int i = {12};" */
|
||||
if (ISCOMMA(ex)) { /* " int i = {12};" */
|
||||
if (IVAL(tpp, ex->OP_LEFT) != 0)
|
||||
too_many_initialisers(ex);
|
||||
/* return remainings of the list for the
|
||||
|
@ -94,8 +90,7 @@ IVAL(tpp, ex)
|
|||
*/
|
||||
return ex->OP_RIGHT;
|
||||
}
|
||||
/* "int i = 12;" */
|
||||
check_ival(ex, tp);
|
||||
check_ival(ex, tp); /* "int i = 12;" */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -131,8 +126,7 @@ do_array(ex, tpp)
|
|||
is completely foolish, we did it!! (no applause, thank you)
|
||||
*/
|
||||
if (tp->tp_up->tp_fund == CHAR) {
|
||||
register struct expr *f = ex->OP_LEFT;
|
||||
register struct expr *g = 0;
|
||||
register struct expr *f = ex->OP_LEFT, *g = NILEXPR;
|
||||
|
||||
while (ISCOMMA(f)) { /* eat the brackets!!! */
|
||||
g = f;
|
||||
|
@ -150,8 +144,7 @@ do_array(ex, tpp)
|
|||
/* declared with unknown size: [] */
|
||||
for (elem_count = 0; ex; elem_count++) {
|
||||
/* eat whole initialisation expression */
|
||||
if (ISCOMMA(ex->OP_LEFT)) {
|
||||
/* the member expression is embraced */
|
||||
if (ISCOMMA(ex->OP_LEFT)) { /* embraced member */
|
||||
if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0)
|
||||
too_many_initialisers(ex);
|
||||
ex = ex->OP_RIGHT;
|
||||
|
@ -172,15 +165,13 @@ do_array(ex, tpp)
|
|||
arith dim = tp->tp_size / tp->tp_up->tp_size;
|
||||
|
||||
for (elem_count = 0; elem_count < dim && ex; elem_count++) {
|
||||
if (ISCOMMA(ex->OP_LEFT)) {
|
||||
/* embraced member initialisation */
|
||||
if (ISCOMMA(ex->OP_LEFT)) { /* embraced member */
|
||||
if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0)
|
||||
too_many_initialisers(ex);
|
||||
ex = ex->OP_RIGHT;
|
||||
}
|
||||
else {
|
||||
if (aggregate_type(tp->tp_up))
|
||||
/* the member is an aggregate */
|
||||
ex = IVAL(&(tp->tp_up), ex);
|
||||
else {
|
||||
check_ival(ex->OP_LEFT, tp->tp_up);
|
||||
|
@ -194,7 +185,7 @@ do_array(ex, tpp)
|
|||
is returned
|
||||
*/
|
||||
return ex;
|
||||
if ((ex == 0) && elem_count < dim) {
|
||||
if ((ex == 0) && elem_count < dim)
|
||||
/* the expression tree is completely absorbed
|
||||
but there are still members which must be
|
||||
initialised with zeroes
|
||||
|
@ -202,7 +193,6 @@ do_array(ex, tpp)
|
|||
do
|
||||
pad(tp->tp_up);
|
||||
while (++elem_count < dim);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -245,16 +235,14 @@ do_struct(ex, tp)
|
|||
definition.
|
||||
*/
|
||||
put_bf(sd->sd_type, (arith)0);
|
||||
else {
|
||||
/* fundamental type, not embraced */
|
||||
else { /* fundamental type, not embraced */
|
||||
check_ival(ex->OP_LEFT, sd->sd_type);
|
||||
ex = ex->OP_RIGHT;
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
}
|
||||
}
|
||||
/* align upto the next selector boundary */
|
||||
if (sd->sd_sdef)
|
||||
if (sd->sd_sdef) /* align upto the next selector boundary */
|
||||
bytes_upto_here += zero_bytes(sd);
|
||||
if (last_offset != sd->sd_offset) {
|
||||
/* don't take the field-width more than once */
|
||||
|
@ -266,9 +254,7 @@ do_struct(ex, tp)
|
|||
}
|
||||
/* perfect fit if (ex && (sd == 0)) holds */
|
||||
if ((ex == 0) && (sd != 0)) {
|
||||
/* there are selectors left which must be padded with
|
||||
zeroes
|
||||
*/
|
||||
/* there are selectors left which must be padded with zeroes */
|
||||
do {
|
||||
pad(sd->sd_type);
|
||||
/* take care of the alignment restrictions */
|
||||
|
@ -307,7 +293,7 @@ check_and_pad(ex, tpp)
|
|||
*/
|
||||
tp = *tpp = construct_type(ARRAY, tp->tp_up, (arith)1);
|
||||
else {
|
||||
register dim = tp->tp_size / tp->tp_up->tp_size;
|
||||
register int dim = tp->tp_size / tp->tp_up->tp_size;
|
||||
/* pad remaining members with zeroes */
|
||||
while (--dim > 0)
|
||||
pad(tp->tp_up);
|
||||
|
@ -320,7 +306,7 @@ check_and_pad(ex, tpp)
|
|||
if (valid_type(tp, "struct") == 0)
|
||||
return;
|
||||
check_and_pad(ex, &(sd->sd_type));
|
||||
/* Next selector is aligned by adding extra zeroes */
|
||||
/* next selector is aligned by adding extra zeroes */
|
||||
if (sd->sd_sdef)
|
||||
zero_bytes(sd);
|
||||
while (sd = sd->sd_sdef) { /* pad remaining selectors */
|
||||
|
@ -346,10 +332,8 @@ pad(tp)
|
|||
|
||||
if (valid_type(tp->tp_up, "array element") == 0)
|
||||
return;
|
||||
|
||||
dim = tp->tp_size / tp->tp_up->tp_size;
|
||||
|
||||
/* Assume the dimension is known */
|
||||
/* assume dimension is known */
|
||||
while (dim-- > 0)
|
||||
pad(tp->tp_up);
|
||||
break;
|
||||
|
@ -360,7 +344,6 @@ pad(tp)
|
|||
|
||||
if (valid_type(tp, "struct") == 0)
|
||||
return;
|
||||
|
||||
do {
|
||||
pad(sdef->sd_type);
|
||||
if (sdef->sd_sdef)
|
||||
|
@ -462,10 +445,8 @@ check_ival(ex, tp)
|
|||
/* float f = 1; */
|
||||
ex = ex->OP_RIGHT;
|
||||
if (is_cp_cst(ex))
|
||||
C_con_fcon(
|
||||
long2str((long)ex->VL_VALUE, 10),
|
||||
tp->tp_size
|
||||
);
|
||||
C_con_fcon(long2str((long)ex->VL_VALUE, 10),
|
||||
tp->tp_size);
|
||||
else
|
||||
illegal_init_cst(ex);
|
||||
}
|
||||
|
@ -509,7 +490,7 @@ ch_array(tpp, ex)
|
|||
|
||||
ASSERT(ex->ex_class == String);
|
||||
length = ex->SG_LEN;
|
||||
if (tp->tp_size == (arith)-1) {
|
||||
if (tp->tp_size == (arith)-1) {
|
||||
/* set the dimension */
|
||||
tp = *tpp = construct_type(ARRAY, tp->tp_up, length);
|
||||
ntopad = align(tp->tp_size, word_align) - tp->tp_size;
|
||||
|
@ -591,8 +572,7 @@ zero_bytes(sd)
|
|||
/* fills the space between a selector of a struct
|
||||
and the next selector of that struct with zero-bytes.
|
||||
*/
|
||||
register int n =
|
||||
sd->sd_sdef->sd_offset - sd->sd_offset -
|
||||
register int n = sd->sd_sdef->sd_offset - sd->sd_offset -
|
||||
size_of_type(sd->sd_type, "struct member");
|
||||
register count = n;
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "debug.h" /* UF */
|
||||
#include "pathlength.h" /* UF */
|
||||
#include "strsize.h" /* UF */
|
||||
|
||||
#include "alloc.h"
|
||||
#include "idf.h"
|
||||
#include "input.h"
|
||||
|
@ -52,13 +51,11 @@ replace(idef)
|
|||
}
|
||||
actpars = getactuals(idef); /* get act.param. list */
|
||||
}
|
||||
if ((flags & PREDEF) && (UnknownIdIsZero == 0))
|
||||
/* don't replace this one... */
|
||||
return 0;
|
||||
if ((flags & PREDEF) && (UnknownIdIsZero == 0)) /* don't replace */
|
||||
return 0;
|
||||
if (flags & FUNC) /* this macro leads to special action */
|
||||
macro_func(idef);
|
||||
/* create and input buffer */
|
||||
reptext = macro2buffer(idef, actpars, &size);
|
||||
reptext = macro2buffer(idef, actpars, &size); /* create input buffer */
|
||||
InsertText(reptext, size);
|
||||
return 1;
|
||||
}
|
||||
|
@ -74,8 +71,7 @@ macro_func(idef)
|
|||
replacement texts must be evaluated at the time they are
|
||||
used.
|
||||
*/
|
||||
/* This switch is very blunt... */
|
||||
switch (idef->id_text[2]) {
|
||||
switch (idef->id_text[2]) { /* This switch is very blunt... */
|
||||
case 'F' : /* __FILE__ */
|
||||
FilNamBuf[0] = '"';
|
||||
strcpy(&FilNamBuf[1], FileName);
|
||||
|
@ -126,8 +122,7 @@ macro2buffer(idef, actpars, siztext)
|
|||
for (p = actpars[n - 1]; *p; p++) {
|
||||
text[pos++] = *p;
|
||||
if (pos == size)
|
||||
text = Srealloc(text,
|
||||
size += RSTRSIZE);
|
||||
text = Srealloc(text, size += RSTRSIZE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -27,7 +27,6 @@ static struct switch_hdr *switch_stack = 0;
|
|||
- the expression E in "switch(E)" is cast to 'int' (RM 9.7)
|
||||
- the expression E in "case E:" must be 'int' (RM 9.7)
|
||||
- the values in the CSA/CSB tables are words (EM 7.4)
|
||||
|
||||
For simplicity, we suppose int_size == word_size.
|
||||
*/
|
||||
|
||||
|
@ -42,7 +41,7 @@ code_startswitch(expp)
|
|||
register struct switch_hdr *sh = new_switch_hdr();
|
||||
int fund = any2arith(expp, SWITCH); /* INT, LONG or DOUBLE */
|
||||
|
||||
switch (fund) {
|
||||
switch (fund) {
|
||||
case LONG:
|
||||
if (options['R'])
|
||||
warning("long in switch (cast to int)");
|
||||
|
@ -55,7 +54,6 @@ code_startswitch(expp)
|
|||
break;
|
||||
#endif NOFLOAT
|
||||
}
|
||||
|
||||
stack_stmt(l_break, NO_LABEL);
|
||||
sh->sh_break = l_break;
|
||||
sh->sh_default = 0;
|
||||
|
@ -66,8 +64,8 @@ code_startswitch(expp)
|
|||
sh->sh_entries = (struct case_entry *) 0; /* case-entry list */
|
||||
sh->next = switch_stack; /* push onto switch-stack */
|
||||
switch_stack = sh;
|
||||
/* evaluate the switch expr. */
|
||||
code_expr(*expp, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
/* evaluate the switch expr. */
|
||||
C_bra(l_table); /* goto start of switch_table */
|
||||
}
|
||||
|
||||
|
@ -93,7 +91,7 @@ code_endswitch()
|
|||
ce = sh->sh_entries;
|
||||
for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
|
||||
ASSERT(ce);
|
||||
if (val == ce->ce_value) {
|
||||
if (val == ce->ce_value) {
|
||||
C_rom_ilb(ce->ce_label);
|
||||
ce = ce->next;
|
||||
}
|
||||
|
@ -103,9 +101,9 @@ code_endswitch()
|
|||
C_lae_dlb(tablabel, (arith)0); /* perform the switch */
|
||||
C_csa(sh->sh_type->tp_size);
|
||||
}
|
||||
else { /* CSB */
|
||||
else { /* CSB */
|
||||
C_rom_cst((arith)sh->sh_nrofentries);
|
||||
for (ce = sh->sh_entries; ce; ce = ce->next) {
|
||||
for (ce = sh->sh_entries; ce; ce = ce->next) {
|
||||
/* generate the entries: value + prog.label */
|
||||
C_rom_cst(ce->ce_value);
|
||||
C_rom_ilb(ce->ce_label);
|
||||
|
@ -115,11 +113,9 @@ code_endswitch()
|
|||
}
|
||||
C_df_ilb(sh->sh_break);
|
||||
switch_stack = sh->next; /* unstack the switch descriptor */
|
||||
|
||||
/* free the allocated switch structure */
|
||||
ce = sh->sh_entries;
|
||||
while (ce) {
|
||||
for (ce = sh->sh_entries; ce;) { /* free allocated switch structure */
|
||||
register struct case_entry *tmp = ce->next;
|
||||
|
||||
free_case_entry(ce);
|
||||
ce = tmp;
|
||||
}
|
||||
|
@ -135,28 +131,23 @@ code_case(expr)
|
|||
register struct switch_hdr *sh = switch_stack;
|
||||
|
||||
ASSERT(is_cp_cst(expr));
|
||||
if (sh == 0) {
|
||||
if (sh == 0) {
|
||||
error("case statement not in switch");
|
||||
return;
|
||||
}
|
||||
if (expr->ex_flags & EX_ERROR) {
|
||||
/* is probably 0 anyway */
|
||||
if (expr->ex_flags & EX_ERROR) /* is probably 0 anyway */
|
||||
return;
|
||||
}
|
||||
ch7cast(&expr, SWITCH, sh->sh_type);
|
||||
ce = new_case_entry();
|
||||
C_df_ilb(ce->ce_label = text_label());
|
||||
ce->ce_value = val = expr->VL_VALUE;
|
||||
if (sh->sh_entries == 0) {
|
||||
/* first case entry */
|
||||
if (sh->sh_entries == 0) { /* first case entry */
|
||||
ce->next = (struct case_entry *) 0;
|
||||
sh->sh_entries = ce;
|
||||
sh->sh_lowerbd = sh->sh_upperbd = val;
|
||||
sh->sh_nrofentries = 1;
|
||||
}
|
||||
else {
|
||||
/* second etc. case entry */
|
||||
/* find the proper place to put ce into the list */
|
||||
else { /* second etc. case entry; put ce into proper place */
|
||||
register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
|
||||
|
||||
if (val < sh->sh_lowerbd)
|
||||
|
@ -164,37 +155,34 @@ code_case(expr)
|
|||
else
|
||||
if (val > sh->sh_upperbd)
|
||||
sh->sh_upperbd = val;
|
||||
while (c1 && c1->ce_value < ce->ce_value) {
|
||||
while (c1 && c1->ce_value < ce->ce_value) {
|
||||
c2 = c1;
|
||||
c1 = c1->next;
|
||||
}
|
||||
/* At this point three cases are possible:
|
||||
1: c1 != 0 && c2 != 0:
|
||||
insert ce somewhere in the middle
|
||||
2: c1 != 0 && c2 == 0:
|
||||
insert ce right after the head
|
||||
3: c1 == 0 && c2 != 0:
|
||||
append ce to last element
|
||||
1: c1 != 0 && c2 != 0: insert ce somewhere in the middle
|
||||
2: c1 != 0 && c2 == 0: insert ce right after the head
|
||||
3: c1 == 0 && c2 != 0: append ce to last element
|
||||
The case c1 == 0 && c2 == 0 cannot occur, since
|
||||
the list is guaranteed not to be empty.
|
||||
the list is guaranteed to be non-empty.
|
||||
*/
|
||||
if (c1) {
|
||||
if (c1->ce_value == ce->ce_value) {
|
||||
if (c1) {
|
||||
if (c1->ce_value == ce->ce_value) {
|
||||
error("multiple case entry for value %ld",
|
||||
ce->ce_value);
|
||||
free_case_entry(ce);
|
||||
return;
|
||||
}
|
||||
if (c2) {
|
||||
if (c2) {
|
||||
ce->next = c2->next;
|
||||
c2->next = ce;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
ce->next = sh->sh_entries;
|
||||
sh->sh_entries = ce;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
ASSERT(c2);
|
||||
ce->next = (struct case_entry *) 0;
|
||||
c2->next = ce;
|
||||
|
@ -207,13 +195,11 @@ code_default()
|
|||
{
|
||||
register struct switch_hdr *sh = switch_stack;
|
||||
|
||||
if (sh == 0) {
|
||||
if (sh == 0)
|
||||
error("default not in switch");
|
||||
return;
|
||||
}
|
||||
if (sh->sh_default != 0) {
|
||||
else
|
||||
if (sh->sh_default != 0)
|
||||
error("multiple entry for default in switch");
|
||||
return;
|
||||
}
|
||||
C_df_ilb(sh->sh_default = text_label());
|
||||
else
|
||||
C_df_ilb(sh->sh_default = text_label());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue