blob: 1779ceb04df061034a8884a53e75d9049f13f6f6 [file] [log] [blame]
/* $VER: vbcc (statements.c) $Revision: 1.30 $ */
#include "vbcc_cpp.h"
#include "vbc.h"
static char FILE_[]=__FILE__;
int cont_label=0;
int test_assignment(type *,np);
static int switchbreak;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
#define cr()
#ifndef cr
void cr(void)
/* tested Registerbelegung */
{
int i;
for(i=0;i<=MAXR;i++)
if(regs[i]!=regsa[i]) {error(149,regnames[i]);regs[i]=regsa[i];}
}
#endif
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
void statement(void)
/* bearbeitet ein statement */
{
token mtok;
#ifdef HAVE_MISRA
/* removed */
#endif
cr();
killsp();
if(ctok->type==LBRA){
enter_block();
if(nesting>0) local_offset[nesting]=local_offset[nesting-1];
compound_statement();
leave_block();
return;
}
if(ctok->type==NAME){
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
#ifndef HAVE_MISRA
if(!strcmp("if",ctok->name)){next_token();if_statement(); return;}
if(!strcmp("switch",ctok->name)){next_token();switch_statement(); return;}
if(!strcmp("for",ctok->name)){next_token();for_statement(); return;}
if(!strcmp("while",ctok->name)){next_token();while_statement(); return;}
if(!strcmp("do",ctok->name)){next_token();do_statement(); return;}
if(!strcmp("goto",ctok->name)){next_token();goto_statement(); return;}
if(!strcmp("continue",ctok->name)){next_token();continue_statement(); return;}
if(!strcmp("break",ctok->name)){next_token();break_statement(); return;}
if(!strcmp("return",ctok->name)){next_token();return_statement(); return;}
if(!strcmp("case",ctok->name)){next_token(); labeled_statement(); return;}
if(!strcmp("default",ctok->name)){cpbez(buff,0);next_token();labeled_statement(); return;}
#endif
}
cpbez(buff,1);
copy_token(&mtok,ctok);
next_token();killsp();
if(ctok->type==T_COLON){labeled_statement();return;}
push_token(&mtok);
free(mtok.name);
expression_statement(); /* if there is an expression statement set misra_last_break to false */
}
void labeled_statement(void)
/* bearbeitet labeled_statement */
{
llist *lp;int def=0;
nocode=0;
if(ctok->type==T_COLON){
next_token();
if(!*buff){
error(130);
return;
}
if(!strcmp("default",buff)){
def=1;
lp=0;
} else lp=find_label(buff);
if(lp&&lp->flags&LABELDEFINED){
error(131,buff);
return;
}
if(!lp) lp=add_label(buff);
lp->flags|=LABELDEFINED;
lp->switch_count=0;
if(def){
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
#endif
if(switch_act==0) error(150);
lp->flags|=LABELDEFAULT;
lp->switch_count=switch_act;
}else {
#ifdef HAVE_MISRA
/* removed */
#endif
}
gen_label(lp->label);
afterlabel=0;
}else{
/* case */
np tree;llist *lp;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
tree=expression();
killsp();
if(ctok->type==T_COLON){
next_token();
killsp();
} else error(70);
if(!switch_count){
error(132);
} else {
if(!tree||!type_expression(tree,0))
{
} else {
if(tree->flags!=CEXPR||tree->sidefx){
error(133);
} else {
if(!ISINT(tree->ntyp->flags)){
error(134);
} else {
lp=add_label(empty);
lp->flags=LABELDEFINED;
lp->switch_count=switch_act;
eval_constn(tree);
insert_const(&lp->val,switch_typ);
gen_label(lp->label);
}
}
}
}
if(tree) free_expression(tree);
}
cr();
killsp();
if(ctok->type!=RBRA) statement();
}
void if_statement(void)
/* bearbeitet if_statement */
{
int ltrue,lfalse,lout,cexpr=0,cm,tm,merk_elseneed;
np tree;IC *new;
static int elseneed;
merk_elseneed=elseneed;
elseneed=0;
killsp();
if(ctok->type==LPAR) next_token(); else error(151);
killsp();cm=nocode;
tree=expression();
if(!tree){
error(135);
}else{
#ifdef HAVE_MISRA
/* removed */
#endif
ltrue=++label;lfalse=++label;
simple_alg_opt(tree);
if(type_expression(tree,andcomp(tree,0))){
tree=makepointer(tree);
if(!ISARITH(tree->ntyp->flags)&&!ISPOINTER(tree->ntyp->flags)){
error(136);
}else{
if(tree->flags==ASSIGN&&tree->right->flags!=CALL) error(164);
gen_IC(tree,ltrue,lfalse);
if(tree->flags==CEXPR){
eval_const(&tree->val,tree->ntyp->flags&NU);
if(zldeqto(vldouble,d2zld(0.0))&&zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))) cexpr=2; else cexpr=1;
}else
cexpr=0;
if((tree->o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&cexpr) free_reg(tree->o.reg);
if(tree->o.flags&&!cexpr){
gen_test(&tree->o,tree->ntyp->flags,BEQ,lfalse);
#if 0
new=new_IC();
new->code=TEST;
new->q1=tree->o;
new->q2.flags=new->z.flags=0;
new->typf=tree->ntyp->flags;
add_IC(new);
new=new_IC();
new->code=BEQ;
new->typf=lfalse;
add_IC(new);
#endif
}
if(cexpr==2){
new=new_IC();
new->code=BRA;
new->typf=lfalse;
add_IC(new);
}
}
}
tm=tree->o.flags;
free_expression(tree);
}
killsp(); if(ctok->type==RPAR) next_token(); else error(59);
if(cexpr==2) nocode=1;
if(!cexpr&&!tm) gen_label(ltrue);
#ifdef HAVE_MISRA
/* removed */
#endif
statement();
killsp();
if(ctok->type!=NAME||strcmp("else",ctok->name)){
#ifdef HAVE_MISRA
/* removed */
#endif
nocode=cm;
if(cexpr!=1) gen_label(lfalse);
elseneed=merk_elseneed;
return;
}
next_token();
lout=++label;
if(cexpr!=2){
new=new_IC();
new->code=BRA;
new->typf=lout;
add_IC(new);
}
if(cexpr!=1) {nocode=cm;gen_label(lfalse);}
if(cexpr==1) nocode=1; else nocode=cm;
if(ctok->type!=LBRA){
if(ctok->type!=NAME||strcmp("if",ctok->name)) {
#ifdef HAVE_MISRA
/* removed */
#endif
}
else
elseneed=1;
}
statement();
elseneed=merk_elseneed;
nocode=cm;
if(cexpr!=2) gen_label(lout);
cr();
}
void switch_statement(void)
/* bearbeitet switch_statement */
{
np tree;int merk_typ,merk_count,merk_break,num_cases;
IC *merk_fic,*merk_lic,*new;llist *lp,*l1,*l2;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
nocode=0;
killsp();
if(ctok->type==LPAR){
next_token();killsp();
} else error(151);
tree=expression(); killsp();
if(ctok->type==RPAR){
next_token();killsp();
} else error(59);
merk_typ=switch_typ;merk_count=switch_act;merk_break=break_label;
if(!tree){
error(137);
} else {
if(!type_expression(tree,0)){
}else{
if(!ISINT(tree->ntyp->flags)){
error(138);
} else {
int m1,m2,m3,def=0,rm,rm1,rm2,minflag;
zmax l,ml,s;zumax ul,mul,us;
if(tree->flags==ASSIGN&&tree->right->flags!=CALL) error(164);
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
m3=break_label=++label;m1=switch_act=++switch_count;
m2=switch_typ=tree->ntyp->flags&NU;
gen_IC(tree,0,0);
if((SWITCHSUBS&&!shortcut(SUB,m2))||(!SWITCHSUBS&&!shortcut(COMPARE,m2))){
switch_typ=m2=int_erw(m2);
convert(tree,m2);
}
if((tree->o.flags&(DREFOBJ|SCRATCH))!=SCRATCH){
new=new_IC();
new->code=ASSIGN;
new->q1=tree->o;
new->q2.flags=0;
new->q2.val.vmax=sizetab[m2&NQ];
get_scratch(&new->z,m2,0,0);
new->typf=m2;
tree->o=new->z;
add_IC(new);
}
if((tree->o.flags&(SCRATCH|REG))==(SCRATCH|REG)){
int r=tree->o.reg;
rm=regs[r];
regs[r]=regsa[r];
if(reg_pair(r,&rp)){
rm1=regs[rp.r1];
rm2=regs[rp.r2];
regs[rp.r1]=regsa[rp.r1];
regs[rp.r2]=regsa[rp.r2];
}
}
merk_fic=first_ic;merk_lic=last_ic;
first_ic=last_ic=0;
{
int merk_sb=switchbreak;
switchbreak=1;
statement();
switchbreak=merk_sb;
}
if((tree->o.flags&(SCRATCH|REG))==(SCRATCH|REG)){
int r=tree->o.reg;
regs[r]=rm;
if(reg_pair(r,&rp)){
regs[rp.r1]=rm1;
regs[rp.r2]=rm2;
}
}
minflag=0;s=l2zm(0L);us=ul2zum(0UL);
num_cases=0;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
for(l1=first_llist;l1;l1=l1->next)
if(l1->switch_count==m1) num_cases++;
for(l1=first_llist;l1;l1=l1->next){
if(l1->switch_count!=m1) continue;
if(l1->flags&LABELDEFAULT){
if(def) error(139);
def=l1->label;
continue;
}
lp=0;minflag&=~1;
for(l2=first_llist;l2;l2=l2->next){
if(l2->switch_count!=m1) continue;
if(l2->flags&LABELDEFAULT) continue;
eval_const(&l2->val,m2);
if(minflag&2){
if(m2&UNSIGNED){
if(zumleq(vumax,mul)||zumeqto(vumax,mul)) continue;
}else{
if(zmleq(vmax,ml)||zmeqto(vmax,ml)) continue;
}
}
if(minflag&1){
if(m2&UNSIGNED){
if(!(minflag&4)&&zumeqto(vumax,ul)){
error(201);
minflag|=4;
}
if(zumleq(vumax,ul)){
lp=l2;
ul=vumax;
}
}else{
if(!(minflag&4)&&zmeqto(vmax,l)){ error(201);minflag|=4;}
if(zmleq(vmax,l)){lp=l2;l=vmax;}
}
}else{
minflag|=1;
l=vmax;
ul=vumax;
lp=l2;
}
}
if(!lp) continue;
ml=l;mul=ul;minflag|=2;
if(SWITCHSUBS&&num_cases<JUMP_TABLE_LENGTH){
new=new_IC();
new->line=0;
new->file=0;
new->typf=m2;
new->code=SUB;
new->q1=tree->o;
new->z=tree->o;
new->q2.flags=KONST;
eval_const(&lp->val,m2);
if(m2&UNSIGNED){
gval.vumax=zumsub(vumax,us);
eval_const(&gval,UNSIGNED|MAXINT);
}else{
gval.vmax=zmsub(vmax,s);
eval_const(&gval,MAXINT);
}
insert_const(&new->q2.val,m2);
new->q1.am=new->q2.am=new->z.am=0;
s=l;us=ul;
new->prev=merk_lic;
if(merk_lic) merk_lic->next=new; else merk_fic=new;
merk_lic=new;
new=new_IC();
new->line=0;
new->file=0;
new->typf=m2;
new->code=TEST;
new->q1=tree->o;
new->q2.flags=new->z.flags=0;
new->prev=merk_lic;
new->q1.am=new->q2.am=new->z.am=0;
if(merk_lic) merk_lic->next=new; else merk_fic=new;
merk_lic=new;
}else{
new=new_IC();
new->line=0;
new->file=0;
new->code=COMPARE;
new->typf=m2;
new->q1=tree->o;
new->q2.flags=KONST;
new->q2.val=lp->val;
new->z.flags=0;
new->prev=merk_lic;
new->q1.am=new->q2.am=new->z.am=0;
if(merk_lic) merk_lic->next=new; else merk_fic=new;
merk_lic=new;
}
new=new_IC();
new->line=0;
new->file=0;
new->code=BEQ;
new->typf=lp->label;
new->q1.flags=new->q2.flags=new->z.flags=0;
new->prev=merk_lic;
new->q1.am=new->q2.am=new->z.am=0;
merk_lic->next=new;
merk_lic=new;
}
if((tree->o.flags&(SCRATCH|REG))==(SCRATCH|REG)){ /* free_reg(tree->o.reg); */
new=new_IC();
new->line=0;
new->file=0;
new->code=FREEREG;new->typf=0;
new->q2.flags=new->z.flags=0;
new->q1.flags=REG;
new->q1.reg=tree->o.reg;
new->prev=merk_lic;
new->q1.am=new->q2.am=new->z.am=0;
if(merk_lic) merk_lic->next=new; else merk_fic=new;
merk_lic=new;
regs[tree->o.reg]=regsa[tree->o.reg];
if(reg_pair(tree->o.reg,&rp)){ regs[rp.r1]=regsa[rp.r1];regs[rp.r2]=regsa[rp.r2];}
}
new=new_IC();
new->line=0;
new->file=0;
new->code=BRA;
if(def) new->typf=def; else {
#ifdef HAVE_MISRA
/* removed */
#endif
new->typf=m3;
}
new->q1.flags=new->q2.flags=new->z.flags=0;
if(merk_lic) merk_lic->next=new; else merk_fic=new;
new->prev=merk_lic;
if(first_ic){
first_ic->prev=new;
new->next=first_ic;
}else{
last_ic=new;
new->next=first_ic;
}
new->q1.am=new->q2.am=new->z.am=0;
first_ic=merk_fic;
gen_label(m3);
}
}
}
switch_typ=merk_typ;switch_act=merk_count;break_label=merk_break;
if(tree) free_expression(tree);
cr();
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
#endif
}
void repair_tree(np p)
/* Bearbeitet einen Ausdruckbaum so, dass er ein zweites Mal */
/* mit gen_IC erzeugt werden kann. */
{
if(p->left) repair_tree(p->left);
if(p->right) repair_tree(p->right);
if(p->flags==IDENTIFIER||p->flags==(IDENTIFIER|256))
p->o.v=find_var(p->identifier,0);
if(p->flags==CALL){
argument_list *al=p->alist;
while(al){
repair_tree(al->arg);
al=al->next;
}
}
}
void while_statement(void)
/* bearbeitet while_statement */
{
np tree;int lloop,lin,lout,cm,cexpr,contm,breakm;
IC *new,*mic; int line,tvalid;char *file;
killsp();
if(ctok->type==LPAR) {next_token();killsp();} else error(151);
tree=expression();
cexpr=0;
if(tree){
simple_alg_opt(tree);
if(tvalid=type_expression(tree,andcomp(tree,0))){
#ifdef HAVE_MISRA
/* removed */
#endif
tree=makepointer(tree);
if(!ISARITH(tree->ntyp->flags)&&!ISPOINTER(tree->ntyp->flags)){
error(140);
cexpr=-1;
}else{
if(tree->flags==ASSIGN&&tree->right->flags!=CALL) error(164);
if(tree->flags==CEXPR){
eval_const(&tree->val,tree->ntyp->flags);
if(zldeqto(vldouble,d2zld(0.0))&&zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))) cexpr=1; else cexpr=2;
if(cexpr==1) error(152);
}
}
}else cexpr=-1;
} else error(141);
lloop=++label;lin=++label;lout=++label;cm=nocode;
contm=cont_label;breakm=break_label;
if(!cexpr||tree->sidefx) cont_label=lin; else cont_label=lloop;
if(!cexpr||tree->sidefx){
if(c_flags_val[0].l&2){ /* bei Optimierung */
if(tvalid){
gen_IC(tree,lloop,lout);
if(tree->o.flags){
gen_test(&tree->o,tree->ntyp->flags,BEQ,lout);
#if 0
new=new_IC();
new->code=TEST;
new->typf=tree->ntyp->flags;
new->q1=tree->o;
new->q2.flags=new->z.flags=0;
add_IC(new);
new=new_IC();
new->code=BEQ;
new->typf=lout;
add_IC(new);
#endif
}
repair_tree(tree);
}
}else{
new=new_IC();
new->code=BRA;
new->typf=lin;
new->flags|=LOOP_COND_TRUE;
add_IC(new);
}
}
if(cexpr==1){
new=new_IC();
new->code=BRA;
new->typf=lout;
add_IC(new);
}else{
gen_label(lloop);
last_ic->flags|=LOOP_COND_TRUE;
}
line=last_ic->line;file=last_ic->file;
cm=nocode;break_label=lout;
if(cexpr==1) nocode=1;
currentpri*=looppri;
killsp();
if(ctok->type==RPAR) {next_token();killsp();} else error(59);
{
int merk_sb=switchbreak;
#ifdef HAVE_MISRA
/* removed */
#endif
switchbreak=0;
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
statement();
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
switchbreak=merk_sb;
}
mic=last_ic;
nocode=cm;cont_label=contm;break_label=breakm;
if(!cexpr||tree->sidefx) gen_label(lin);
/* correct if mic was a branch to label lin and eliminated */
if(last_ic->prev!=mic) mic=last_ic;
if(tree&&cexpr>=0){
if(cexpr!=1||tree->sidefx){
gen_IC(tree,lloop,lout);
if((tree->o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&cexpr) free_reg(tree->o.reg);
}
if(tree->o.flags&&!cexpr){
gen_test(&tree->o,tree->ntyp->flags,BNE,lloop);
#if 0
new=new_IC();
new->code=TEST;
new->typf=tree->ntyp->flags;
new->q1=tree->o;
new->q2.flags=new->z.flags=0;
add_IC(new);
new=new_IC();
new->code=BNE;
new->typf=lloop;
add_IC(new);
#endif
}
if(cexpr==2){
new=new_IC();
new->code=BRA;
new->typf=lloop;
add_IC(new);
}
}
if(tree) free_expression(tree);
for(mic=mic->next;mic;mic=mic->next){
mic->line=line;mic->file=file;
}
gen_label(lout);
currentpri/=looppri;
cr();
}
void for_statement(void)
/* bearbeitet for_statement */
{
np tree1=0,tree2=0,tree3=0;int lloop,lin,lout,cm,cexpr=0,contm,breakm,with_decl,tvalid;
IC *new,*mic;int line;char *file;
killsp();
if(ctok->type==LPAR) {next_token();killsp();} else error(59);
#ifdef HAVE_MISRA
/* removed */
#endif
if(c99&&declaration(0)){
with_decl=1;
enter_block();
if(nesting>0) local_offset[nesting]=local_offset[nesting-1];
for_decl=1;
var_declaration();
for_decl=0;
}else{
with_decl=0;
if(ctok->type!=SEMIC) tree1=expression();
if(tree1){
if(tree1->flags==POSTINC) tree1->flags=PREINC;
if(tree1->flags==POSTDEC) tree1->flags=PREDEC;
if(type_expression(tree1,0)){
if(tree1->sidefx){
gen_IC(tree1,0,0);
if(tree1&&(tree1->o.flags&(SCRATCH|REG))==(SCRATCH|REG)) free_reg(tree1->o.reg);
}else{
#ifdef HAVE_MISRA
/* removed */
#endif
error(153);
}
}
free_expression(tree1);
}
killsp();
if(ctok->type==SEMIC) {next_token();killsp();} else error(54);
}
if(ctok->type!=SEMIC) {tree2=expression();killsp();} else {cexpr=2;}
if(ctok->type==SEMIC) {next_token();killsp();} else error(54);
if(ctok->type!=RPAR) tree3=expression();
killsp();
if(ctok->type==RPAR) {next_token();killsp();} else error(59);
#ifdef HAVE_MISRA
/* removed */
#endif
if(tree3){
if(!type_expression(tree3,0)){
free_expression(tree3);
tree3=0;
}
}
if(tree2){
simple_alg_opt(tree2);
if(tvalid=type_expression(tree2,andcomp(tree2,0))){
#ifdef HAVE_MISRA
/* removed */
#endif
tree2=makepointer(tree2);
if(!ISARITH(tree2->ntyp->flags)&&!ISPOINTER(tree2->ntyp->flags)){
error(142);
cexpr=-1;
}else{
if(tree2->flags==ASSIGN&&tree2->right->flags!=CALL) error(164);
if(tree2->flags==CEXPR){
eval_const(&tree2->val,tree2->ntyp->flags);
if(zldeqto(vldouble,d2zld(0.0))&&zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))) cexpr=1; else cexpr=2;
if(cexpr==1) error(152);
}
}
}else cexpr=-1;
}
lloop=++label;lin=++label;lout=++label;cm=nocode;
contm=cont_label;breakm=break_label;
cont_label=++label;break_label=lout;
if(!cexpr||(tree2&&tree2->sidefx)){
if(c_flags_val[0].l&2){ /* bei Optimierung */
if(tvalid){
gen_IC(tree2,lloop,lout);
if(tree2->o.flags){
gen_test(&tree2->o,tree2->ntyp->flags,BEQ,lout);
#if 0
new=new_IC();
new->code=TEST;
new->typf=tree2->ntyp->flags;
new->q1=tree2->o;
new->q2.flags=new->z.flags=0;
add_IC(new);
new=new_IC();
new->code=BEQ;
new->typf=lout;
add_IC(new);
#endif
}
repair_tree(tree2);
}
}else{
new=new_IC();
new->code=BRA;
new->typf=lin;
new->flags|=LOOP_COND_TRUE;
add_IC(new);
}
}
if(cexpr==1){
new=new_IC();
new->code=BRA;
new->typf=lout;
add_IC(new);
}else{
gen_label(lloop);
last_ic->flags|=LOOP_COND_TRUE;
}
line=last_ic->line;file=last_ic->file;
cm=nocode;
if(cexpr==1) nocode=1;
currentpri*=looppri;
{
int merk_sb=switchbreak;
#ifdef HAVE_MISRA
/* removed */
#endif
switchbreak=0;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
#endif
statement();
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
switchbreak=merk_sb;
}
mic=last_ic;
nocode=cm;
gen_label(cont_label);
cont_label=contm;break_label=breakm;
if(tree3){
if(tree3->flags==POSTINC) tree3->flags=PREINC;
if(tree3->flags==POSTDEC) tree3->flags=PREDEC;
if(tree3->sidefx){
gen_IC(tree3,0,0);
if(tree3&&(tree3->o.flags&(SCRATCH|REG))==(SCRATCH|REG)) free_reg(tree3->o.reg);
}else{
#ifdef HAVE_MISRA
/* removed */
#endif
error(153);}
free_expression(tree3);
}
if(!cexpr||(tree2&&tree2->sidefx)) gen_label(lin);
if(tree2&&cexpr>=0){
if(cexpr!=1||tree2->sidefx){
gen_IC(tree2,lloop,lout);
if((tree2->o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&cexpr) free_reg(tree2->o.reg);
}
if(tree2->o.flags&&!cexpr){
gen_test(&tree2->o,tree2->ntyp->flags,BNE,lloop);
#if 0
new=new_IC();
new->code=TEST;
new->typf=tree2->ntyp->flags;
new->q1=tree2->o;
new->q2.flags=new->z.flags=0;
add_IC(new);
new=new_IC();
new->code=BNE;
new->typf=lloop;
add_IC(new);
#endif
}
if(cexpr==2){
new=new_IC();
new->code=BRA;
new->typf=lloop;
add_IC(new);
}
}
if(!tree2&&cexpr==2){
new=new_IC();
new->code=BRA;
new->typf=lloop;
add_IC(new);
}
if(tree2) free_expression(tree2);
for(mic=mic->next;mic;mic=mic->next){
mic->line=line;mic->file=file;
}
gen_label(lout);
currentpri/=looppri;
cr();
if(with_decl)
leave_block();
}
void do_statement(void)
/* bearbeitet do_statement */
{
np tree;int lloop,lout,contm,breakm;
IC *new;
lloop=++label;lout=++label;currentpri*=looppri;
gen_label(lloop);
breakm=break_label;contm=cont_label;cont_label=++label;break_label=lout;
{
int merk_sb=switchbreak;
#ifdef HAVE_MISRA
/* removed */
#endif
switchbreak=0;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
#endif
statement();
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
switchbreak=merk_sb;
}
killsp();
gen_label(cont_label);cont_label=contm;break_label=breakm;
if(ctok->type!=NAME||strcmp("while",ctok->name)) error(154);
next_token();killsp();
if(ctok->type==LPAR) {next_token();killsp();} else error(151);
tree=expression();
if(tree){
simple_alg_opt(tree);
if(type_expression(tree,andcomp(tree,0))){
#ifdef HAVE_MISRA
/* removed */
#endif
tree=makepointer(tree);
if(ISARITH(tree->ntyp->flags)||ISPOINTER(tree->ntyp->flags)){
if(tree->flags==ASSIGN&&tree->right->flags!=CALL) error(164);
if(tree->flags==CEXPR){
eval_const(&tree->val,tree->ntyp->flags);
if(tree->sidefx) gen_IC(tree,0,0);
if(!zldeqto(vldouble,d2zld(0.0))){
new=new_IC();
new->code=BRA;
new->typf=lloop;
add_IC(new);
}
}else{
gen_IC(tree,lloop,lout);
if(tree->o.flags){
gen_test(&tree->o,tree->ntyp->flags,BNE,lloop);
#if 0
new=new_IC();
new->code=TEST;
new->typf=tree->ntyp->flags;
new->q1=tree->o;
new->q2.flags=new->z.flags=0;
add_IC(new);
new=new_IC();
new->code=BNE;
new->typf=lloop;
add_IC(new);
#endif
}
}
}else error(143);
}
free_expression(tree);
}
killsp();
if(ctok->type==RPAR) {next_token();killsp();} else error(59);
if(ctok->type==SEMIC) {next_token();killsp();} else error(54);
gen_label(lout);
currentpri/=looppri;
cr();
}
void goto_statement(void)
/* bearbeitet goto_statement */
{
llist *lp;
IC *new;
#ifdef HAVE_MISRA
/* removed */
#endif
killsp();
if(ctok->type!=NAME){
error(144);
}else{
if(is_keyword(ctok->name)) error(216,ctok->name);
lp=find_label(ctok->name);
if(!lp){
lp=add_label(ctok->name);
lp->switch_count=0;
}
lp->flags|=LABELUSED;
new=new_IC();
new->typf=lp->label;
new->code=BRA;
new->typf=lp->label;
add_IC(new);
next_token();
killsp();
if(ctok->type==SEMIC){next_token();killsp();} else error(54);
cr();
goto_used=1;
}
}
void continue_statement(void)
/* bearbeitet continue_statement */
{
IC *new;
#ifdef HAVE_MISRA
/* removed */
#endif
if(cont_label==0){error(145);return;}
//if(block_vla[nesting]) freevl();
new=new_IC();
new->code=BRA;
new->typf=cont_label;
add_IC(new);
killsp();
if(ctok->type==SEMIC) {next_token();killsp();} else error(54);
cr();
}
void break_statement(void)
/* bearbeitet break_statement */
{
IC *new;
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
if(break_label==0){error(146);return;}
//if(block_vla[nesting]) freevl();
new=new_IC();
new->code=BRA;
new->typf=break_label;
add_IC(new);
killsp();
if(ctok->type==SEMIC) {next_token();killsp();} else error(54);
cr();
}
static void check_auto_return(np tree)
/* Testet, ob Knoten Adresse einer automatischen Variable ist. */
{
if((tree->flags==ADDRESS||tree->flags==ADDRESSS||tree->flags==ADDRESSA)&&tree->left->flags==IDENTIFIER){
Var *v;
if(v=find_var(tree->left->identifier,0)){
if(v->storage_class==AUTO) error(224);
}
}
}
extern int has_return;
#ifdef HAVE_MISRA
/* removed */
#endif
void return_statement(void)
/* bearbeitet return_statement */
/* SETRETURN hat Groesse in q2.reg und z.reg==ffreturn(rtyp) */
{
np tree;
IC *new;
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
has_return=1;
killsp();
if(ctok->type!=SEMIC){
if(tree=expression()){
if(!return_typ){
if(type_expression(tree,0)){
tree=makepointer(tree);
if((tree->ntyp->flags&NQ)!=VOID)
error(155);
else{
error(225);
#ifdef HAVE_MISRA
/* removed */
#endif
}
gen_IC(tree,0,0);
if((tree->o.flags&(SCRATCH|REG))==(SCRATCH|REG)) free_reg(tree->o.reg);
}
}else{
if(type_expression(tree,return_typ)){
tree=makepointer(tree);
if(tree->flags==ADD||(tree->flags==SUB&&ISPOINTER(tree->ntyp->flags))){
check_auto_return(tree->left);
check_auto_return(tree->right);
}else{
check_auto_return(tree);
}
if(!test_assignment(return_typ,tree)){free_expression(tree);return;}
gen_IC(tree,0,0);
convert(tree,return_typ->flags);
#ifdef OLDPARMS /* alte CALL/RETURN-Methode */
new=new_IC();
new->code=ASSIGN;
new->typf=return_typ->flags&NU;
new->q1=tree->o;
new->q2.flags=0;
new->q2.val.vmax=szof(return_typ);
if(ffreturn(return_typ)){
new->z.flags=SCRATCH|REG;
new->z.reg=ffreturn(return_typ);
if(!regs[new->z.reg]){
IC *alloc=new_IC();
alloc->code=ALLOCREG;
alloc->q1.flags=REG;
alloc->q2.flags=alloc->z.flags=0;
alloc->q1.reg=new->z.reg;
regs[new->z.reg]=1;
add_IC(alloc);
}
}else{
new->z.reg=0;
new->z.v=return_var;
new->z.flags=SCRATCH|VAR;
new->z.val.vmax=l2zm(0L);
}
add_IC(new);
/* das hier ist nicht sehr schoen, aber wie sonst? */
if((new->z.flags&(SCRATCH|REG))==(SCRATCH|REG)&&regs[new->z.reg]) free_reg(new->z.reg);
#else
new=new_IC();
if(return_var){ /* Returnwert ueber Zeiger */
new->code=ASSIGN;
new->z.flags=VAR|DREFOBJ;
new->z.dtyp=POINTER_TYPE(return_typ);
new->z.val.vmax=l2zm(0L);
new->z.v=return_var;
new->z.reg=0;
}else{
new->code=SETRETURN;
new->z.reg=ffreturn(return_typ);
new->z.flags=0;
}
new->typf=return_typ->flags;
/*new->typf=tree->ntyp->flags;*/
new->q1=tree->o;
new->q2.flags=0;
new->q2.val.vmax=szof(return_typ);
add_IC(new);
#endif
}
}
free_expression(tree);
killsp();
if(ctok->type==SEMIC) {next_token();killsp();} else error(54);
}else{
if(return_typ) error(156);
}
}else{
next_token();
if(return_typ) error(156);
}
new=new_IC();
new->code=BRA;
new->typf=return_label;
add_IC(new);
cr();
#ifdef HAVE_MISRA
/* removed */
#endif
}
void expression_statement(void)
/* bearbeitet expression_statement */
{
np tree;
killsp();
if(ctok->type==SEMIC){
int oline=ctok->line;
next_token();
#ifdef HAVE_MISRA
/* removed */
#endif
return;
}
if(tree=expression()){
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
if(tree->flags==POSTINC) tree->flags=PREINC;
if(tree->flags==POSTDEC) tree->flags=PREDEC;
if(type_expression(tree,0)){
if(DEBUG&2){
pre(stdout,tree);
printf("\n");
}
if(tree->sidefx){
gen_IC(tree,0,0);
if((tree->o.flags&(SCRATCH|REG))==REG) ierror(0);
if(tree&&(tree->o.flags&(SCRATCH|REG))==(SCRATCH|REG)) free_reg(tree->o.reg);
}else{
#ifdef HAVE_MISRA
/* removed */
#endif
error(153);
if(DEBUG&2) prd(stdout,tree->ntyp);
}
}
free_expression(tree);
}
killsp();
if(ctok->type==SEMIC) next_token(); else error(54);
cr();
}
void compound_statement(void)
/* bearbeitet compound_statement (block) */
{
killsp();
if(ctok->type==LBRA) next_token(); else error(157);
if(c99||ecpp){
killsp();
while(ctok->type!=RBRA){
if(declaration(0))
var_declaration();
else
statement();
killsp();
}
}else{
killsp();
while(declaration(0)){
var_declaration();
killsp();
}
while(ctok->type!=RBRA){
statement();
killsp();
}
}
next_token();/*killsp();*/
}
llist *add_label(char *identifier)
/* Fuegt label in Liste */
{
llist *new;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
#endif
new=mymalloc(LSIZE);
new->next=0;new->label=++label;new->flags=0;
new->identifier=add_identifier(identifier,strlen(identifier));
if(first_llist==0){
first_llist=last_llist=new;
}else{
last_llist->next=new;
last_llist=new;
}
return last_llist; /* return(new) sollte aequiv. sein */
}
llist *find_label(char *identifier)
/* Sucht Label, gibt Zeiger auf llist oder 0 bei Fehler zurueck */
{
llist *p;
p=first_llist;
while(p){
if(!strcmp(p->identifier,identifier)) return p;
p=p->next;
}
return 0;
}
void free_llist(llist *p)
/* Gibt llist frei */
{
llist *merk;
while(p){
merk=p->next;
if(!(p->flags&LABELDEFINED)) error(147,p->identifier);
if(!(p->flags&LABELUSED)&&!p->switch_count) error(148,p->identifier);
free(p);
p=merk;
}
}