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