Import VBCC source snapshot (29/04/2022)
diff --git a/type_expr.c b/type_expr.c
new file mode 100644
index 0000000..4c68805
--- /dev/null
+++ b/type_expr.c
@@ -0,0 +1,3090 @@
+/* $VER: vbcc (type_expr.c) $Revision: 1.64 $ */
+
+#include "vbc.h"
+
+static char FILE_[]=__FILE__;
+
+#define CONSTADDR 256
+
+
+/* if MASK is set, a specialized version will be generated */
+#define USEHALF (1L<<1)
+#define USELONG (1L<<2)
+#define USELLONG (1L<<3)
+#define USEFLOAT (1L<<4)
+#define USEHEXL (1L<<5)
+#define USEHEXU (1L<<6)
+#define USEDEC (1L<<7)
+#define USEOCT (1L<<8)
+#define USEINT (1L<<9)
+#define USEUNS (1L<<10)
+#define USESTR (1L<<11)
+#define USECHAR (1L<<12)
+#define USEPERC (1L<<13)
+#define USECNT (1L<<14)
+#define USEALT (1L<<15)
+#define USEZPAD (1L<<16)
+#define USELALGN (1L<<17)
+#define USEBLANK (1L<<18)
+#define USESIGN (1L<<19)
+#define USEWIDTH (1L<<20)
+#define USEAST (1L<<21)
+#define USEPREC (1L<<22)
+#define USESPEC (1L<<23)
+#define USEREXP (1L<<24)
+
+int alg_opt(np,type *);
+void simple_alg_opt(np);
+int test_assignment(type *,np);
+int type_expression2(np,type *);
+void make_cexpr(np);
+
+int dontopt;
+int no_cast_free;
+
+type uct={UNSIGNED|CHAR};
+type ust={UNSIGNED|SHORT};
+type uit={UNSIGNED|INT};
+type ult={UNSIGNED|LONG};
+
+#ifdef HAVE_ECPP
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif
+
+#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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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
+
+
+
+
+
+void insert_constn(np p)
+/* Spezialfall fuer np */
+{
+ if(!p||!p->ntyp) ierror(0);
+ insert_const(&p->val,p->ntyp->flags);
+}
+int const_typ(type *p)
+/* Testet, ob Typ konstant ist oder konstante Elemente enthaelt */
+{
+ int i;struct_declaration *sd;
+ if(p->flags&CONST) return(1);
+ if(ISSTRUCT(p->flags)||ISUNION(p->flags))
+ for(i=0;i<p->exact->count;i++)
+ if(const_typ((*p->exact->sl)[i].styp)) return(1);
+ return 0;
+}
+int arith_flag(int ta,int tb)
+{
+ /* TODO: volatile? */
+ ta&=NU;tb&=NU;
+ if(ta==LDOUBLE||tb==LDOUBLE) return LDOUBLE;
+ if(ta==DOUBLE||tb==DOUBLE) return DOUBLE;
+ if(ta==FLOAT||tb==FLOAT) return FLOAT;
+ ta=int_erw(ta);tb=int_erw(tb);
+ if(ta==(UNSIGNED|LLONG)||tb==(UNSIGNED|LLONG)) return UNSIGNED|LLONG;
+ if(ta==LLONG||tb==LLONG) return LLONG;
+ if(ta==(UNSIGNED|LONG)||tb==(UNSIGNED|LONG)) return UNSIGNED|LONG;
+ if((ta==LONG&&tb==(UNSIGNED|INT))||(ta==(UNSIGNED|INT)&&tb==LONG)){
+ if(zumleq(t_max(UNSIGNED|INT),t_max(LONG)))
+ return LONG;
+ else
+ return UNSIGNED|LONG;
+ }
+ if(ta==LONG||tb==LONG) return LONG;
+ if(ta==(UNSIGNED|INT)||tb==(UNSIGNED|INT)) return UNSIGNED|INT;
+ return INT;
+}
+
+type *arith_typ(type *a,type *b)
+/* Erzeugt Typ fuer arithmetische Umwandlung von zwei Operanden */
+{
+ int ta,tb,va,vol;type *new;
+ new=new_typ();
+ ta=a->flags&NU;tb=b->flags&NU;
+ vol=(a->flags&VOLATILE)|(b->flags&VOLATILE);
+ if(ta==LDOUBLE||tb==LDOUBLE){new->flags=LDOUBLE|vol;return new;}
+ if(ta==DOUBLE||tb==DOUBLE){new->flags=DOUBLE|vol;return new;}
+ if(ta==FLOAT||tb==FLOAT){new->flags=FLOAT|vol;return new;}
+ ta=int_erw(ta);tb=int_erw(tb);
+ if(ta==(UNSIGNED|LLONG)||tb==(UNSIGNED|LLONG)){new->flags=UNSIGNED|LLONG|vol;return new;}
+ if(ta==LLONG||tb==LLONG){new->flags=LLONG|vol;return new;}
+ if(ta==(UNSIGNED|LONG)||tb==(UNSIGNED|LONG)){new->flags=UNSIGNED|LONG|vol;return new;}
+ if((ta==LONG&&tb==(UNSIGNED|INT))||(ta==(UNSIGNED|INT)&&tb==LONG)){
+ if(zumleq(t_max(UNSIGNED|INT),t_max(LONG))) new->flags=LONG|vol; else new->flags=UNSIGNED|LONG|vol;
+ return new;
+ }
+ if(ta==LONG||tb==LONG){new->flags=LONG|vol;return new;}
+ if(ta==(UNSIGNED|INT)||tb==(UNSIGNED|INT)){new->flags=UNSIGNED|INT|vol;return new;}
+ new->flags=INT|vol;
+ return new;
+}
+int int_erw(int t)
+/* Fuehrt Integer_Erweiterung eines Typen durch */
+{
+ if((t&NQ)>=INT) return t;
+ if(t&UNSIGNED){
+ if((t&NQ)<=CHAR&&zumleq(t_max(UNSIGNED|CHAR),t_max(INT))) return INT;
+ if((t&NQ)<=SHORT&&zumleq(t_max(UNSIGNED|SHORT),t_max(INT))) return INT;
+ return UNSIGNED|INT;
+ }
+ return INT;
+}
+#if HAVE_AOS4
+static int aos4err;
+int aos4_attr(type *p,char *s)
+{
+ if(p->attr&&strstr(p->attr,s))
+ return 1;
+ if(p->next)
+ return aos4_attr(p->next,s);
+ else
+ return 0;
+}
+static np aos4_clone_tree(np p)
+{
+ np new;
+ if(!p) return 0;
+ new=new_node();
+ *new=*p;
+ new->ntyp=clone_typ(p->ntyp);
+ new->left=aos4_clone_tree(p->left);
+ new->right=aos4_clone_tree(p->right);
+ new->alist=0;new->cl=0;new->dsize=0;
+ if(p->flags==CALL/*||p->cl||p->dsize*/) aos4err=1;
+ return new;
+}
+#endif
+#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 */
+#endif
+int type_expression(np p,type *ttyp)
+/* Art Frontend fuer type_expression2(). Setzt dontopt auf 0 */
+{
+ int ret_val;
+ dontopt=0;
+ simple_alg_opt(p);
+#ifdef HAVE_MISRA
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif
+ ret_val = type_expression2(p,ttyp);
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ return ret_val;
+
+}
+
+static void fix_addr_ptype(np op)
+{
+ np p=op;
+ while(p->flags==FIRSTELEMENT) p=p->left;
+ if(p->left->flags==CONTENT){
+ int pt=p->left->left->ntyp->flags;
+ if(!ISPOINTER(pt)) ierror(0);
+ if(!ISPOINTER(op->ntyp->flags)) ierror(0);
+ op->ntyp->flags=pt;
+ }
+}
+
+static int ptype(np op)
+{
+#ifdef POINTER_VARADR
+ Var *v=0;
+ np p=op;
+
+ while(p->flags==FIRSTELEMENT/*||p->flags==CONTENT*/) p=p->left;
+
+ if(p->flags==IDENTIFIER)
+ v=find_var(p->identifier,0);
+ if(v)
+ return POINTER_VARADR(v);
+ else
+ return POINTER_TYPE(op->ntyp);
+#else
+ return POINTER_TYPE(op->ntyp);
+#endif
+}
+
+static int decide_shortcut(np p,type *ttyp)
+{
+ int ttf=ttyp->flags,f=p->flags;
+ if(f==PMULT) f=MULT;
+ if(!shortcut(f,ttyp->flags&NU)||
+ ISFLOAT(ttf)||ISFLOAT(p->left->ntyp->flags)||ISFLOAT(p->right->ntyp->flags)
+ )
+ return 0;
+ ttf&=NQ;
+ if(ttf<INT) return 1;
+ if(zm2l(sizetab[ttf])<zm2l(sizetab[(p->left->ntyp->flags&NQ)])) return 1;
+ if(zm2l(sizetab[ttf])<zm2l(sizetab[(p->right->ntyp->flags&NQ)])) return 1;
+ return 0;
+}
+
+
+
+static type *best_addi2pt(zmax sz)
+{
+ if(!zmeqto(sizetab[CHAR],sizetab[INT])&&!zmeqto(sz,Z0)&&MINADDI2P<=CHAR&&zumleq(zm2zum(sz),zumadd(tu_max[CHAR],ZU1))){
+ return &uct;
+ }else if(!zmeqto(sizetab[SHORT],sizetab[INT])&&!zmeqto(sz,Z0)&&MINADDI2P<=SHORT&&zumleq(zm2zum(sz),zumadd(tu_max[SHORT],ZU1))){
+ return &ust;
+ }
+ return 0;
+}
+
+type *andcomp(np and,np cmp)
+{
+ int i=0;zmax sval;zumax uval;
+ if(cmp){
+ if((cmp->flags==CEXPR||cmp->flags==PCEXPR)){i=1;eval_constn(cmp);sval=vmax;uval=vumax;}
+ }else{
+ sval=Z0;uval=ZU0;
+ i=1;
+ }
+ if(and->flags==AND&&(and->left->flags==CEXPR||and->left->flags==PCEXPR)){i|=2;eval_constn(and->left);}
+ if(and->flags==AND&&(and->right->flags==CEXPR||and->right->flags==PCEXPR)){i|=2;eval_constn(and->right);}
+ if(i&2){
+ /*printf("CHECK: x&%ld ==/!= %ld\n",zm2l(vmax),(i&1)?zm2l(sval):-1L);*/
+ if(shortcut(COMPARE,UNSIGNED|CHAR)&&shortcut(AND,UNSIGNED|CHAR)&&!zmeqto(sizetab[CHAR],sizetab[SHORT])){
+ if(zmleq(vmax,t_max[CHAR]))
+ return &uct;
+ else if((i&1)&&zumleq(vumax,tu_max[CHAR])&&zumleq(uval,tu_max[CHAR]))
+ return &uct;
+ }
+ if(shortcut(COMPARE,UNSIGNED|SHORT)&&shortcut(AND,UNSIGNED|SHORT)&&!zmeqto(sizetab[SHORT],sizetab[INT])){
+ if(zmleq(vmax,t_max[SHORT]))
+ return &ust;
+ else if((i&1)&&zumleq(vumax,tu_max[SHORT])&&zumleq(uval,tu_max[SHORT]))
+ return &ust;
+ }
+ if(!zmeqto(sizetab[INT],sizetab[LONG])){
+ if(zmleq(vmax,t_max[INT]))
+ return &uit;
+ else if((i&1)&&zumleq(vumax,tu_max[INT])&&zumleq(uval,tu_max[INT]))
+ return &uit;
+ }
+ if(!zmeqto(sizetab[LONG],sizetab[LLONG])){
+ if(zmleq(vmax,t_max[LONG]))
+ return &ult;
+ else if((i&1)&&zumleq(vumax,tu_max[LONG])&&zumleq(uval,tu_max[LONG]))
+ return &ult;
+ }
+ }
+ return 0;
+}
+
+static int nullpointer(np p)
+{
+ if(p->flags!=CEXPR) return 0;
+ eval_constn(p); /* TODO: do we need to use other measure to verify null pointer? */
+ if(zmeqto(Z0,vmax)) return 1;
+ return 0;
+}
+
+int type_expression2(np p,type *ttyp)
+/* Erzeugt Typ-Strukturen fuer jeden Knoten des Baumes und */
+/* liefert eins zurueck, wenn der Baum ok ist, sonst 0 */
+/* Die Berechnung von Konstanten und andere Vereinfachungen */
+/* sollten vielleicht in eigene Funktion kommen */
+{
+ int ok,f=p->flags,mopt=dontopt,ttf;
+ type *shorttyp;
+ static int assignop;
+ int aoflag;
+#if HAVE_AOS4
+ np thisp=0;
+#endif
+#ifdef HAVE_ECPP
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif
+ if(!p){ierror(0);return(1);}
+ if(ttyp) ttf=ttyp->flags&NQ;
+ /* if(p->ntyp) printf("Warnung: ntyp!=0\n");*/
+ p->lvalue=0;
+ p->sidefx=0;
+ ok=1;
+ if(!ecpp&&f==CALL&&p->left->flags==IDENTIFIER&&!find_var(p->left->identifier,0)){
+ /* implizite Deklaration bei Aufruf einer Funktion */
+ struct_declaration *sd;type *t;Var *v;
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ error(161,p->left->identifier);
+ if(v=find_ext_var(p->left->identifier)){
+ if(!ISFUNC(v->vtyp->flags)||v->vtyp->next->flags!=INT){
+ error(68,p->left->identifier);
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ }
+ v->flags&=~NOTINTU;
+ }else{
+ sd=mymalloc(sizeof(*sd));
+ sd->count=0;
+ t=new_typ();
+ t->flags=FUNKT;
+ t->exact=add_sd(sd,FUNKT);
+ t->next=new_typ();
+ t->next->flags=INT;
+ add_var(p->left->identifier,t,EXTERN,0);
+ }
+ }
+#if HAVE_AOS4
+ if(f==CALL&&p->left->flags==DSTRUCT){
+ thisp=new_node();
+ thisp->flags=ADDRESS;
+ aos4err=0;
+ thisp->left=aos4_clone_tree(p->left->left);
+ thisp->right=0;
+ thisp->alist=0;thisp->cl=0;thisp->dsize=0;thisp->ntyp=0;
+ }
+#endif
+#if HAVE_ECPP
+ if(ecpp&&f==CALL){
+ argument_list *al=p->alist;
+ if(al/*&&!al->arg->ntyp*/){
+ while(al){
+ if(!al->arg) ierror(0);
+ if(!type_expression2(al->arg,0)) return 0;
+ al->arg=makepointer(al->arg);
+ if(type_uncomplete(al->arg->ntyp)) error(39);
+ al=al->next;
+ }
+ }
+ }
+ if(ecpp&&f==CALL){
+ ecpp_merk_al=ecpp_al;
+ ecpp_al=p->alist;
+ }
+#endif
+ dontopt=0;
+ if(f==ADDRESS&&p->left->flags==IDENTIFIER) {p->left->flags|=CONSTADDR;/*puts("&const");*/}
+ if(ttyp&&(f==OR||f==AND||f==XOR||f==ADD||f==SUB||f==MULT||f==PMULT||f==DIV||f==MOD||f==KOMPLEMENT||f==MINUS)&&!ISPOINTER(ttyp->flags)&&shortcut(f==PMULT?MULT:f,ttyp->flags&NU))
+ shorttyp=ttyp;
+ else
+ shorttyp=0;
+ if(assignop){
+ aoflag=1;
+ assignop=0;
+ }else
+ aoflag=0;
+
+ if(!shorttyp){
+ if(f==EQUAL||f==INEQUAL){
+ if(p->left->flags==AND) shorttyp=andcomp(p->left,p->right);
+ if(p->right->flags==AND) shorttyp=andcomp(p->right,p->left);
+ }
+ }
+ if(!shorttyp&&(f==LAND||f==LOR)&&p->left->flags==AND) shorttyp=andcomp(p->left,0);
+ if(p->left&&p->flags!=ASSIGNOP){
+ struct_declaration *sd;
+ /* bei ASSIGNOP wird der linke Zweig durch den Link bewertet */
+ if(!p->left) ierror(0);
+ if(p->flags==CAST)
+ ok&=type_expression2(p->left,p->ntyp);
+ else
+ ok&=type_expression2(p->left,shorttyp);
+ if(p->left) p->sidefx|=p->left->sidefx;
+ if(!ok) return 0;
+ }
+ if(aoflag){
+ if(!p->left||!p->right) ierror(0);
+ shorttyp=p->left->ntyp;
+ ttyp=shorttyp;
+ ttf=ttyp->flags&NQ;
+ }
+
+ if(f==LAND||f==LOR){
+ shorttyp=0;
+ if(p->right->flags==AND) shorttyp=andcomp(p->right,0);
+ }
+
+ if(f==ADD){
+ if(p->left->flags==ADDRESSS||p->left->flags==ADDRESSA||p->left->flags==ADDRESSS){
+ zmax sz=szof(p->left->left->ntyp);
+ shorttyp=best_addi2pt(sz);
+ }
+ if((p->left->ntyp->flags&NQ)==ARRAY){
+ zmax sz=szof(p->left->ntyp);
+ shorttyp=best_addi2pt(sz);
+ if(shorttyp){
+ np new=new_node();
+ new->flags=CAST;
+ new->ntyp=clone_typ(shorttyp);
+ new->left=p->right;
+ p->right=new;
+ }
+ }
+ }
+ if(p->right&&p->right->flags!=MEMBER){
+ struct_declaration *sd;
+ if(p->flags==ASSIGNOP){
+ dontopt=1;
+ assignop=1;
+ }else
+ dontopt=0;
+ if(p->flags==ASSIGN)
+ ok&=type_expression2(p->right,p->left->ntyp);
+ else
+ ok&=type_expression2(p->right,shorttyp);
+ p->sidefx|=p->right->sidefx;
+ if(!ok) return 0;
+ }
+#if HAVE_AOS4
+ if(thisp){
+ if(aos4_attr(p->left->ntyp,"libcall")){
+ argument_list *n=mymalloc(sizeof(*n));
+ n->arg=thisp;
+ n->next=p->alist;
+ n->pushic=0;
+ p->alist=n;
+ if(aos4err) {pre(stdout,thisp);ierror(0);}
+ }else{
+ free_expression(thisp);
+ }
+ }
+#endif
+#if HAVE_ECPP
+ if(ecpp&&f==CALL){
+ ecpp_al=ecpp_merk_al;
+ }
+#endif
+/* printf("bearbeite %s\n",ename[p->flags]);*/
+/* Erzeugung von Zeigern aus Arrays */
+/* Hier muss noch einiges genauer werden (wie gehoert das?) */
+ if(p->left&&f!=PCEXPR&&(ISARRAY(p->left->ntyp->flags)||ISFUNC(p->left->ntyp->flags))){
+ if(f!=ADDRESS&&f!=ADDRESSA&&f!=ADDRESSS&&f!=FIRSTELEMENT&&f!=DSTRUCT&&(f<PREINC||f>POSTDEC)&&(f<ASSIGN||f>ASSIGNOP)){
+ np new=new_node();
+ zmax sz=szof(p->left->ntyp);
+ if((p->left->ntyp->flags&NQ)==ARRAY) new->flags=ADDRESSA;
+ else new->flags=ADDRESS;
+ new->ntyp=0;
+ new->left=p->left;
+ new->right=0;new->lvalue=0;new->sidefx=0; /* sind sidefx immer 0? */
+ p->left=new;
+ ok&=type_expression2(p->left,0);
+ }
+ }
+ if(p->right&&f!=PCEXPR&&f!=FIRSTELEMENT&&f!=DSTRUCT&&f!=ADDRESSS&&p->right->ntyp&&(ISARRAY(p->right->ntyp->flags)||ISFUNC(p->right->ntyp->flags))){
+ np new=new_node();
+ if(ISARRAY(p->right->ntyp->flags)) new->flags=ADDRESSA;
+ else new->flags=ADDRESS;
+ new->ntyp=0;
+ new->left=p->right;
+ new->right=0;new->lvalue=0;new->sidefx=0; /* sind sidefx immer 0? */
+ p->right=new;
+ ok&=type_expression2(p->right,0);
+ }
+
+ if(f==IDENTIFIER||f==(IDENTIFIER|CONSTADDR)){
+ int ff;Var *v;
+#ifdef HAVE_ECPP
+/* 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 */
+/* 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 */
+/* removed */
+/* removed */
+/* removed */
+#endif
+ if(!ecpp){
+ if(p->identifier==empty)
+ /* variable sizeof-expression */
+ v=p->dsize;
+ else{
+ char buf[20];
+ v=find_var(p->identifier,0);
+ if(v&&v->storage_class==EXTERN){
+ if(!strcmp(p->identifier,"strtod")){sprintf(buf,"vfscanf.%ld",1|USEFLOAT);needs(buf);}
+ if(!strcmp(p->identifier,"strtof")){sprintf(buf,"vscanf.%ld",1|USEFLOAT);needs(buf);}
+ if(!strcmp(p->identifier,"atof")){sprintf(buf,"vscanf.%ld",1|USEFLOAT);needs(buf);}
+ if(!strcmp(p->identifier,"tmpnam")){sprintf(buf,"vfprintf.%ld",1|USEDEC);needs(buf);}
+ if(!strcmp(p->identifier,"fopen")){
+ needs("__read.2");
+ needs("__write.2");
+ needs("stdin.2");
+ needs("stdout.2");
+ needs("stderr.2");
+ }
+ }
+ }
+ }
+ if(v==0){error(82,p->identifier);return(0);}
+ if(disallow_statics&&v->storage_class==STATIC&&v->nesting==0&&*v->identifier){
+ error(302,v->identifier);
+ return 0;
+ }
+ ff=v->vtyp->flags&NQ;
+ if(ISARITH(ff)||ISPOINTER(ff)||ISSTRUCT(ff)||ISUNION(ff)||ISVECTOR(ff)) p->lvalue=1;
+ p->ntyp=clone_typ(v->vtyp);
+ /* arithmetischen const Typ als Konstante behandeln, das muss noch
+ deutlich anders werden, bevor man es wirklich so machen kann
+ if((p->ntyp->flags&CONST)&&ISARITH(p->ntyp->flags)&&v->clist&&!(f&CONSTADDR)){
+ p->flags=CEXPR;
+ p->val=v->clist->val;
+ v->flags|=USEDASSOURCE;
+ }*/
+ p->flags&=~CONSTADDR;
+ if((p->ntyp->flags&NQ)==ENUM){
+ /* enumerations auch als Konstante (int) behandeln */
+ p->flags=CEXPR;
+ if(!v->clist) ierror(0);
+ p->val=v->clist->val;
+ p->ntyp->flags=CONST|INT;
+ }
+ p->o.v=v;
+ if (p->ntyp->flags&VOLATILE) p->sidefx=1; /* Touching a volatile may have side effects */
+ return 1;
+ }
+
+ if(f==CEXPR||f==PCEXPR||f==STRING) return 1;
+
+ if(f==REINTERPRET){
+ /* todo: add checks */
+ return 1;
+ }
+
+ if(f==BITFIELD) return 1;
+
+ if(f==LITERAL){
+ p->lvalue=1;
+ return 1;
+ }
+
+ if(f==KOMMA){
+ if(const_expr){error(46);return 0;}
+ p->ntyp=clone_typ(p->right->ntyp);
+ if(f==CEXPR) p->val=p->right->val;
+ return ok;
+ }
+ if(f==ASSIGN||f==ASSIGNOP){
+ if(!p) ierror(0);
+ if(!p->left) ierror(0);
+ if(p->left->lvalue==0) {error(86);/*prd(p->left->ntyp);*/return 0;}
+ if(const_typ(p->left->ntyp)) {error(87);return 0;}
+ if(type_uncomplete(p->left->ntyp)) {error(88);return 0;}
+ if(type_uncomplete(p->right->ntyp)) {error(88);return 0;}
+ p->ntyp=clone_typ(p->left->ntyp);
+ p->sidefx=1;
+ return(test_assignment(p->left->ntyp,p->right));
+ }
+ if(f==LOR||f==LAND){
+ int a1=-1,a2=-1,m;
+ if(ISVECTOR(p->left->ntyp->flags)){
+ if(ISVECTOR(p->right->ntyp->flags)){
+ if((p->left->ntyp->flags&NU)!=(p->right->ntyp->flags&NU)){error(89);return 0;}
+ }else{
+ if(!ISINT(p->right->ntyp->flags)){error(89);return 0;}
+ }
+ p->ntyp=new_typ();
+ p->ntyp->flags=p->left->ntyp->flags&NQ;
+ return ok;
+ }
+ if(ISVECTOR(p->right->ntyp->flags)){
+ if(!ISINT(p->left->ntyp->flags)){error(89);return 0;}
+ p->ntyp->flags=p->right->ntyp->flags&NQ;
+ return ok;
+ }
+ if(f==LAND) m=1; else m=0;
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ p->ntyp=new_typ();
+ p->ntyp->flags=INT;
+ if(!ISARITH(p->left->ntyp->flags)&&!ISPOINTER(p->left->ntyp->flags))
+ {error(89);ok=0;}
+ if(!ISARITH(p->right->ntyp->flags)&&!ISPOINTER(p->right->ntyp->flags))
+ {error(89);ok=0;}
+ if(p->left->flags==CEXPR){
+ eval_constn(p->left);
+ if(!zldeqto(vldouble,d2zld(0.0))||!zumeqto(vumax,ul2zum(0UL))||!zmeqto(vmax,l2zm(0L))) a1=1; else a1=0;
+ }
+ if(p->right->flags==CEXPR){
+ eval_constn(p->right);
+ if(!zldeqto(vldouble,d2zld(0.0))||!zumeqto(vumax,ul2zum(0UL))||!zmeqto(vmax,l2zm(0L))) a2=1; else a2=0;
+ }
+ if(a1==1-m||a2==1-m||(a1==m&&a2==m)){
+ p->flags=CEXPR;p->sidefx=0;
+ if(!p->left->sidefx) {free_expression(p->left);p->left=0;} else p->sidefx=1;
+ if(!p->right->sidefx||a1==1-m) {free_expression(p->right);p->right=0;} else p->sidefx=0;
+ if(a1==1-m||a2==1-m) {p->val.vint=zm2zi(l2zm((long)(1-m)));}
+ else {p->val.vint=zm2zi(l2zm((long)m));}
+ }
+ return ok;
+ }
+ if(f==OR||f==AND||f==XOR){
+ if(ISVECTOR(p->left->ntyp->flags)){
+ if(!ISINT(VECTYPE(p->left->ntyp->flags))){error(90);return 0;}
+ if(ISVECTOR(p->right->ntyp->flags)){
+ if((p->left->ntyp->flags&NU)!=(p->right->ntyp->flags&NU)){error(98);return 0;}
+ }else{
+ if(!ISINT(p->right->ntyp->flags)){error(90);return 0;}
+ }
+ p->ntyp=clone_typ(p->left->ntyp);
+ return ok;
+ }
+ if(ISVECTOR(p->right->ntyp->flags)){
+ if(!ISINT(VECTYPE(p->right->ntyp->flags))){error(90);return 0;}
+ if(!ISINT(p->left->ntyp->flags)){error(90);return 0;}
+ p->ntyp=clone_typ(p->right->ntyp);
+ return ok;
+ }
+ if(!ISINT(p->left->ntyp->flags)){error(90);return 0;}
+ if(!ISINT(p->right->ntyp->flags)){error(90);return 0;}
+#ifdef HAVE_MISRA
+/* removed */
+/* removed */
+#endif
+ if(ttyp&&decide_shortcut(p,ttyp))
+ p->ntyp=clone_typ(ttyp);
+ else
+ p->ntyp=arith_typ(p->left->ntyp,p->right->ntyp);
+ if(!mopt){
+ if(!alg_opt(p,ttyp)) ierror(0);
+ }
+ return ok;
+ }
+ if(f==LESS||f==LESSEQ||f==GREATER||f==GREATEREQ||f==EQUAL||f==INEQUAL){
+ /* hier noch einige Abfragen fuer sichere Entscheidungen einbauen */
+ /* z.B. unigned/signed-Vergleiche etc. */
+ /* die val.vint=0/1-Zuweisungen muessen noch an zint angepasst */
+ /* werden */
+ zmax s1,s2;zumax u1,u2;zldouble d1,d2;int c=0;
+ type *t;
+ if(ISVECTOR(p->left->ntyp->flags)){
+ if(ISVECTOR(p->right->ntyp->flags)){
+ if((p->left->ntyp->flags&NU)!=(p->right->ntyp->flags&NU)){error(89);return 0;}
+ }
+ p->ntyp=new_typ();
+ if(ISFLOAT(VECTYPE(p->left->ntyp->flags)))
+ p->ntyp->flags=mkvec(INT,VECDIM(p->left->ntyp->flags));
+ else
+ p->ntyp->flags=p->left->ntyp->flags&NQ;
+ return ok;
+ }
+ if(ISVECTOR(p->right->ntyp->flags)){
+ p->ntyp=new_typ();
+ if(ISFLOAT(VECTYPE(p->right->ntyp->flags)))
+ p->ntyp->flags=mkvec(INT,VECDIM(p->left->ntyp->flags));
+ else
+ p->ntyp->flags=p->right->ntyp->flags&NQ;
+ return ok;
+ }
+#ifdef HAVE_MISRA
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif
+ if(!ISARITH(p->left->ntyp->flags)||!ISARITH(p->right->ntyp->flags)){
+ if(!ISPOINTER(p->left->ntyp->flags)||!ISPOINTER(p->right->ntyp->flags)){
+ if(f!=EQUAL&&f!=INEQUAL){
+ error(92);return 0;
+ }else{
+ if((!ISPOINTER(p->left->ntyp->flags)||p->right->flags!=CEXPR)&&
+ (!ISPOINTER(p->right->ntyp->flags)||p->left->flags!=CEXPR)){
+ error(93);return 0;
+ }else{
+ if(p->left->flags==CEXPR) eval_constn(p->left);
+ else eval_constn(p->right);
+ if(!zldeqto(vldouble,d2zld(0.0))||!zmeqto(vmax,l2zm(0L))||!zumeqto(vumax,ul2zum(0UL)))
+ {error(40);return 0;}
+ }
+ }
+ }else{
+ if(compatible_types(p->left->ntyp->next,p->right->ntyp->next,NQ)){
+ }else{
+ if(f!=EQUAL&&f!=INEQUAL) error(41);
+ if((p->left->ntyp->next->flags&NQ)!=VOID&&(p->right->ntyp->next->flags&NQ)!=VOID)
+ {error(41);}
+ }
+ }
+ }
+ if(p->left->flags==CEXPR){
+ eval_constn(p->left);
+ d1=vldouble;u1=vumax;s1=vmax;c|=1;
+ if((p->right->ntyp->flags&UNSIGNED)&&!(p->left->ntyp->flags&UNSIGNED)){
+ if(zldleq(d1,d2zld(0.0))&&zmleq(s1,l2zm(0L))){
+ if(!zldeqto(d1,d2zld(0.0))||!zmeqto(s1,l2zm(0L))){
+ if(zumleq(tu_max[p->right->ntyp->flags&NQ],t_max[p->left->ntyp->flags&NQ]))
+ error(165);
+ }else{
+ if(f==GREATER||f==LESSEQ) error(165);
+ }
+ }
+ }
+ }
+ if(p->right->flags==CEXPR){
+ eval_constn(p->right);
+ d2=vldouble;u2=vumax;s2=vmax;c|=2;
+ if((p->left->ntyp->flags&UNSIGNED)&&!(p->right->ntyp->flags&UNSIGNED)){
+ if(zldleq(d2,d2zld(0.0))&&zmleq(s2,l2zm(0L))){
+ if(!zldeqto(d2,d2zld(0.0))||!zmeqto(s2,l2zm(0L))){
+ if(zumleq(tu_max[p->left->ntyp->flags&NQ],t_max[p->right->ntyp->flags&NQ]))
+ error(165);
+ }else{
+ if(f==LESS||f==GREATEREQ) error(165);
+ }
+ }
+ }
+ }
+ p->ntyp=new_typ();
+ p->ntyp->flags=INT;
+ if(c==3){
+ p->flags=CEXPR;
+ t=arith_typ(p->left->ntyp,p->right->ntyp);
+ if(!p->left->sidefx) {free_expression(p->left);p->left=0;}
+ if(!p->right->sidefx) {free_expression(p->right);p->right=0;}
+ if(ISFLOAT(t->flags)){
+ if(f==EQUAL) p->val.vint=zm2zi(l2zm((long)zldeqto(d1,d2)));
+ if(f==INEQUAL) p->val.vint=zm2zi(l2zm((long)!zldeqto(d1,d2)));
+ if(f==LESSEQ) p->val.vint=zm2zi(l2zm((long)zldleq(d1,d2)));
+ if(f==GREATER) p->val.vint=zm2zi(l2zm((long)!zldleq(d1,d2)));
+ if(f==LESS){
+ if(zldleq(d1,d2)&&!zldeqto(d1,d2))
+ p->val.vint=zm2zi(l2zm(1L));
+ else
+ p->val.vint=zm2zi(l2zm(0L));
+ }
+ if(f==GREATEREQ){
+ if(!zldleq(d1,d2)||zldeqto(d1,d2))
+ p->val.vint=zm2zi(l2zm(1L));
+ else
+ p->val.vint=zm2zi(l2zm(0L));
+ }
+ }else{
+ if(t->flags&UNSIGNED){
+ if(f==EQUAL) p->val.vint=zm2zi(l2zm((long)zumeqto(u1,u2)));
+ if(f==INEQUAL) p->val.vint=zm2zi(l2zm((long)!zumeqto(u1,u2)));
+ if(f==LESSEQ) p->val.vint=zm2zi(l2zm((long)zumleq(u1,u2)));
+ if(f==GREATER) p->val.vint=zm2zi(l2zm((long)!zumleq(u1,u2)));
+ if(f==LESS){
+ if(zumleq(u1,u2)&&!zumeqto(u1,u2))
+ p->val.vint=zm2zi(l2zm(1L));
+ else
+ p->val.vint=zm2zi(l2zm(0L));
+ }
+ if(f==GREATEREQ){
+ if(!zumleq(u1,u2)||zumeqto(u1,u2))
+ p->val.vint=zm2zi(l2zm(1L));
+ else
+ p->val.vint=zm2zi(l2zm(0L));
+ }
+ }else{
+ if(f==EQUAL) p->val.vint=zm2zi(l2zm((long)zmeqto(s1,s2)));
+ if(f==INEQUAL) p->val.vint=zm2zi(l2zm((long)!zmeqto(s1,s2)));
+ if(f==LESSEQ) p->val.vint=zm2zi(l2zm((long)zmleq(s1,s2)));
+ if(f==GREATER) p->val.vint=zm2zi(l2zm((long)!zmleq(s1,s2)));
+ if(f==LESS){
+ if(zmleq(s1,s2)&&!zmeqto(s1,s2))
+ p->val.vint=zm2zi(l2zm(1L));
+ else
+ p->val.vint=zm2zi(l2zm(0L));
+ }
+ if(f==GREATEREQ){
+ if(!zmleq(s1,s2)||zmeqto(s1,s2))
+ p->val.vint=zm2zi(l2zm(1L));
+ else
+ p->val.vint=zm2zi(l2zm(0L));
+ }
+ }
+ }
+ freetyp(t);
+ }
+ return ok;
+ }
+ if(f==ADD||f==SUB||f==MULT||f==DIV||f==MOD||f==LSHIFT||f==RSHIFT||f==PMULT){
+ if(ISVECTOR(p->left->ntyp->flags)){
+ if((f==MOD||f==LSHIFT||f==RSHIFT)&&ISFLOAT(VECTYPE(p->left->ntyp->flags))){
+ error(98);
+ return 0;
+ }
+ if(ISARITH(p->right->ntyp->flags)){
+ p->ntyp=clone_typ(p->left->ntyp);
+ return ok;
+ }
+ if((p->left->ntyp->flags&NU)==(p->right->ntyp->flags&NU)){
+ p->ntyp=clone_typ(p->left->ntyp);
+ return ok;
+ }
+ error(98);
+ return 0;
+ }
+ if(ISVECTOR(p->right->ntyp->flags)){
+ if((f==MOD||f==LSHIFT||f==RSHIFT)&&ISFLOAT(VECTYPE(p->right->ntyp->flags))){
+ error(98);
+ return 0;
+ }
+ if(ISARITH(p->left->ntyp->flags)){
+ p->ntyp=clone_typ(p->right->ntyp);
+ return ok;
+ }
+ error(98);
+ return 0;
+ }
+ if(!ISARITH(p->left->ntyp->flags)||!ISARITH(p->right->ntyp->flags)){
+ np new;zmax sz; int typf=0;
+#ifdef MAXADDI2P
+ static type pmt={MAXADDI2P};
+#endif
+ if(f!=ADD&&f!=SUB){error(94);return 0;}
+#ifdef HAVE_MISRA
+/* removed */
+/* removed */
+#endif
+ if(ISPOINTER(p->left->ntyp->flags)){
+ if((p->left->ntyp->next->flags&NQ)==VOID)
+ {error(95);return 0;}
+ if(ISPOINTER(p->right->ntyp->flags)){
+ if((p->right->ntyp->next->flags&NQ)==VOID)
+ {error(95);return 0;}
+ if(!compatible_types(p->left->ntyp->next,p->right->ntyp->next,NQ))
+ {error(41);}
+ if(f!=SUB){
+ error(96);
+ return 0;
+ }else{
+ typf=3;
+ }
+ }else{
+ if(!ISINT(p->right->ntyp->flags))
+ {error(97,ename[f]);return 0;}
+ if(p->right->flags!=PMULT&&p->right->flags!=PCEXPR){
+ new=new_node();
+ new->flags=PMULT;
+ new->ntyp=0;
+ new->left=p->right;
+ new->right=new_node();
+ if(is_vlength(p->left->ntyp->next)){
+ new->right->flags=IDENTIFIER;
+ new->right->identifier=empty;
+ new->right->dsize=vlength_szof(p->left->ntyp->next);
+ new->right->val.vmax=l2zm(0L);
+ new->right->sidefx=0;
+ }else{
+ new->right->flags=PCEXPR;
+ sz=szof(p->left->ntyp->next);
+ if(zmeqto(l2zm(0L),sz)) error(78);
+#if HAVE_INT_SIZET
+ new->right->val.vint=zm2zi(sz);
+#else
+ new->right->val.vlong=zm2zl(sz);
+#endif
+ }
+ new->right->left=new->right->right=0;
+ new->right->ntyp=new_typ();
+#if HAVE_INT_SIZET
+ new->right->ntyp->flags=INT;
+#else
+ new->right->ntyp->flags=LONG;
+#endif
+ p->right=new;
+#ifdef MAXADDI2P
+ ok&=type_expression2(new,(shorttyp&&(shorttyp->flags&NQ)<MAXADDI2P)?shorttyp:&pmt);
+#else
+ ok&=type_expression2(new,shorttyp);
+#endif
+ }
+ typf=1;
+ }
+ }else{
+ np merk;
+ if(!ISPOINTER(p->right->ntyp->flags))
+ {error(98);return 0;}
+ if((p->right->ntyp->next->flags&NQ)==VOID)
+ {error(95);return 0;}
+ if(!ISINT(p->left->ntyp->flags))
+ {error(98);return 0;}
+ if(p->flags==SUB){error(99);return 0;}
+ if(p->left->flags!=PMULT&&p->left->flags!=PCEXPR){
+ new=new_node();
+ new->flags=PMULT;
+ new->ntyp=0;
+ new->left=p->left;
+ new->right=new_node();
+ if(is_vlength(p->right->ntyp->next)){
+ new->right->flags=IDENTIFIER;
+ new->right->identifier=empty;
+ new->right->dsize=vlength_szof(p->right->ntyp->next);
+ new->right->val.vmax=l2zm(0L);
+ new->right->sidefx=0;
+ }else{
+ new->right->flags=PCEXPR;
+ sz=szof(p->right->ntyp->next);
+ if(zmeqto(l2zm(0L),sz)) error(78);
+#if HAVE_INT_SIZET
+ new->right->val.vint=zm2zi(sz);
+#else
+ new->right->val.vlong=zm2zl(sz);
+#endif
+ }
+ new->right->left=new->right->right=0;
+ new->right->ntyp=new_typ();
+#if HAVE_INT_SIZET
+ new->right->ntyp->flags=INT;
+#else
+ new->right->ntyp->flags=LONG;
+#endif
+ p->left=new;
+#ifdef MAXADDI2P
+ ok&=type_expression2(new,&pmt);
+#else
+ ok&=type_expression2(new,0);
+#endif
+ }
+ typf=2;
+ merk=p->left;p->left=p->right;p->right=merk;
+ }
+ if(typf==0){ierror(0);return(0);}
+ else{
+ if(typf==3){
+ p->ntyp=new_typ();
+ p->ntyp->flags=PTRDIFF_T(p->left->ntyp->flags);
+ }else{
+ /*if(typf==1)*/ p->ntyp=clone_typ(p->left->ntyp);
+ /* else p->ntyp=clone_typ(p->right->ntyp);*/
+ /* Abfrage wegen Vertauschen der Knoten unnoetig */
+ }
+ }
+ }else{
+ if(f==LSHIFT||f==RSHIFT){
+ if(ttyp&&f==LSHIFT&&(ttf<=INT||ttf<(p->left->ntyp->flags&NQ))&&shortcut(f,ttyp->flags&NU)){
+ p->ntyp=clone_typ(ttyp);
+ }else if(ttyp&&f==RSHIFT&&ttf<=INT&&ttf<=(p->left->ntyp->flags&NQ)&&shortcut(f,p->left->ntyp->flags&NU)){
+ p->ntyp=clone_typ(p->left->ntyp);
+ }else{
+ p->ntyp=arith_typ(p->left->ntyp,p->left->ntyp);
+ p->ntyp->flags&=~NQ;
+ p->ntyp->flags|=int_erw(p->left->ntyp->flags);
+ }
+ if(p->right->flags==CEXPR){
+ eval_constn(p->right);
+ if(!zmleq(l2zm(0L),vmax)) error(366);
+ if(zmleq(zmmult(sizetab[p->ntyp->flags&NQ],char_bit),vmax)&&zmleq(zmmult(sizetab[p->left->ntyp->flags&NQ],char_bit),vmax)) error(367);
+ }
+#ifdef HAVE_MISRA
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif
+ }else{
+ /* ggfs. in kleinerem Zieltyp auswerten - bei float keinen shortcut (wäre evtl. double=>float unkritisch?) */
+ if(ttyp&&decide_shortcut(p,ttyp))
+ p->ntyp=clone_typ(ttyp);
+ else
+ p->ntyp=arith_typ(p->left->ntyp,p->right->ntyp);
+ if(!ISINT(p->ntyp->flags)&&(f==MOD||f==LSHIFT||f==RSHIFT))
+ {error(101);ok=0;}
+ }
+ }
+ /* fuegt &a+x zusammen, noch sub und left<->right machen */
+ /* Bei CEXPR statt PCEXPR auch machen? */
+ if((p->flags==ADD||p->flags==SUB)){
+ np m,c=0,a=0;
+ if(p->left->flags==PCEXPR&&p->flags==ADD) c=p->left;
+ if(p->right->flags==PCEXPR) c=p->right;
+ if(p->left->flags==ADDRESS||p->left->flags==ADDRESSA||p->left->flags==ADDRESSS) a=p->left;
+ if(p->right->flags==ADDRESS||p->right->flags==ADDRESSA||p->right->flags==ADDRESSS) a=p->right;
+ if(c&&a){
+ m=a->left;
+ /* kann man das hier so machen oder muss man da mehr testen ? */
+ while(m->flags==FIRSTELEMENT||m->flags==ADDRESS||m->flags==ADDRESSA||m->flags==ADDRESSS) m=m->left;
+ if((m->flags==IDENTIFIER||m->flags==STRING)&&!is_vlength(m->ntyp)){
+ if(DEBUG&1) printf("&a+x with %s combined\n",ename[p->left->flags]);
+ eval_const(&c->val,c->ntyp->flags);
+ if(p->flags==ADD)
+ m->val.vmax=zumadd(m->val.vmax,vmax);
+ else
+ m->val.vmax=zmsub(m->val.vmax,vmax);
+ vmax=szof(m->ntyp);
+ if(!zmeqto(vmax,l2zm(0L))&&zumleq(vmax,m->val.vmax)){
+ if(zumeqto(vmax,m->val.vmax))
+ error(79);
+ else
+ error(80);
+ }
+ vmax=l2zm(0L);
+ if(!zmeqto(m->val.vmax,l2zm(0L))&&zumleq(m->val.vmax,vmax)) error(80);
+ free_expression(c);
+ if(p->ntyp) freetyp(p->ntyp);
+ *p=*a;
+ free(a);
+ return type_expression2(p,0);
+ }
+ }
+ }
+ if(!mopt){
+ if(!alg_opt(p,ttyp)) ierror(0);
+ }
+ return ok;
+ }
+ if(f==CAST){
+ int from=(p->left->ntyp->flags),to=(p->ntyp->flags);
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ from&=NQ;to&=NQ;
+ if(to==VOID) return ok;
+ if(from==VOID)
+ {error(102);return 0;}
+ if((!ISARITH(to)||!ISARITH(from))&&
+ (!ISPOINTER(to)||!ISPOINTER(from))){
+ if(ISPOINTER(to)){
+ if(ISINT(from)){
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ if(!zmleq(sizetab[from],sizetab[to])){
+ error(103);
+ }
+ }else{
+ error(104);return 0;
+ }
+ }else{
+ if(!ISPOINTER(from))
+ {error(105);return 0;}
+ if(ISINT(to)){
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ if(!zmleq(sizetab[from],sizetab[to])){
+ error(106);
+ }
+ }else{
+ error(104);return 0;
+ }
+ }
+ }
+ if(ISINT(from)&&ISINT(to)&&!zmleq(sizetab[from],sizetab[to])&&p->left->flags!=CEXPR) error(166);
+ if(ISPOINTER(to)&&ISPOINTER(from)&&!zmleq(falign(p->ntyp->next),falign(p->left->ntyp->next)))
+ error(167);
+ if(p->left->flags==CEXPR){
+ eval_constn(p->left);
+ if(ISPOINTER(p->ntyp->flags))
+ if(!zumeqto(vumax,ul2zum(0UL))||!zmeqto(vmax,l2zm(0L))||!zldeqto(vldouble,d2zld(0.0)))
+ error(81);
+ insert_constn(p);
+ p->flags=CEXPR;
+ if(!p->left->sidefx){
+ if(!no_cast_free)
+ free_expression(p->left);
+ p->left=0;
+ }
+ }
+#ifdef HAVE_ECPP
+/* 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
+ return ok;
+ }
+ if(f==MINUS||f==KOMPLEMENT||f==NEGATION){
+ if(ISVECTOR(p->left->ntyp->flags)){
+ if(f==NEGATION){
+ if(ISFLOAT(VECTYPE(p->left->ntyp->flags))){error(98);return 0;}
+ p->ntyp=new_typ();
+ p->ntyp->flags=p->left->ntyp->flags&NQ;
+ return ok;
+ }
+ if(f==KOMPLEMENT&&ISFLOAT(VECTYPE(p->left->ntyp->flags))){error(109);return 0;}
+ p->ntyp=clone_typ(p->left->ntyp);
+ return ok;
+ }
+ if(!ISARITH(p->left->ntyp->flags)){
+ if(f!=NEGATION){
+ error(107);return 0;
+ }else{
+ if(!ISPOINTER(p->left->ntyp->flags))
+ {error(108);return 0;}
+ }
+ }
+#ifdef HAVE_MISRA
+/* removed */
+/* removed */
+#endif
+ if(f==KOMPLEMENT&&!ISINT(p->left->ntyp->flags))
+ {error(109);return 0;}
+ if(f==NEGATION){
+ p->ntyp=new_typ();
+ p->ntyp->flags=INT;
+ }else{
+ if(!p->left->ntyp) ierror(0);
+ p->ntyp=clone_typ(p->left->ntyp);
+ if(ISINT(p->ntyp->flags)){
+ if(!ttyp||!shortcut(f,ttyp->flags&NU)){
+ p->ntyp->flags=int_erw(p->ntyp->flags);
+ }else{
+ if((f==MINUS&&!zmleq(sizetab[ttyp->flags&NQ],sizetab[p->ntyp->flags&NQ]))||
+ (f==KOMPLEMENT&&!zmleq(sizetab[ttyp->flags&NQ],sizetab[p->ntyp->flags&NQ])&&(p->ntyp->flags&UNSIGNED)))
+ p->ntyp->flags=int_erw(p->ntyp->flags);
+ }
+ }
+ }
+ if(p->left->flags==CEXPR){
+ eval_constn(p->left);
+ if(f==KOMPLEMENT){
+ if(p->ntyp->flags&UNSIGNED){
+ gval.vumax=zumkompl(vumax);
+ eval_const(&gval,(UNSIGNED|MAXINT));
+ }else{
+ gval.vmax=zmkompl(vmax);
+ eval_const(&gval,MAXINT);
+ }
+ }
+ if(f==MINUS){
+ if(ISFLOAT(p->ntyp->flags)){
+ gval.vldouble=zldsub(d2zld(0.0),vldouble);
+ eval_const(&gval,LDOUBLE);
+ }else{
+ if(p->ntyp->flags&UNSIGNED){
+ gval.vumax=zumsub(ul2zum(0UL),vumax);
+ eval_const(&gval,(UNSIGNED|MAXINT));
+ }else{
+ gval.vmax=zmsub(l2zm(0L),vmax);
+ eval_const(&gval,MAXINT);
+ }
+ }
+ }
+ if(f==NEGATION){
+ if(zldeqto(vldouble,d2zld(0.0))&&zumeqto(vumax,ul2zum(0UL))&&zmeqto(vmax,l2zm(0L)))
+ gval.vmax=l2zm(1L);
+ else
+ gval.vmax=l2zm(0L);
+ eval_const(&gval,MAXINT);
+ }
+ insert_constn(p);
+ p->flags=CEXPR;
+ if(!p->left->sidefx&&p->left) {free_expression(p->left);p->left=0;}
+ }
+ return ok;
+ }
+ if(f==CONTENT){
+ if(!ISPOINTER(p->left->ntyp->flags))
+ {error(111);return 0;}
+ if(!ISARRAY(p->left->ntyp->next->flags)&&type_uncomplete(p->left->ntyp->next))
+ {error(112);return 0;}
+ p->ntyp=clone_typ(p->left->ntyp->next);
+ if(!ISARRAY(p->ntyp->flags)) p->lvalue=1;
+ if(p->left->flags==ADDRESS&&zumeqto(p->left->val.vumax,ul2zum(0UL))){
+ /* *&x durch x ersetzen */
+ np merk;
+ merk=p->left;
+ if(p->ntyp) freetyp(p->ntyp);
+ if(p->left->ntyp) freetyp(p->left->ntyp);
+ *p=*p->left->left;
+ free(merk->left);
+ free(merk);
+ return ok;
+ }
+ /* *&ax durch firstelement-of(x) ersetzen */
+ if(p->left->flags==ADDRESSA||p->left->flags==ADDRESSS){
+ if(!is_vlength(p->left->left->ntyp)){
+ np merk;
+ if(DEBUG&1) printf("substitutet * and %s with FIRSTELEMENT\n",ename[p->left->flags]);
+ p->flags=FIRSTELEMENT;
+ p->lvalue=1; /* evtl. hier erst Abfrage ? */
+ merk=p->left;
+ p->left=merk->left;
+ p->right=merk->right;
+ if(merk->ntyp) freetyp(merk->ntyp);
+ free(merk);
+ }
+ }
+ if (p->ntyp->flags&VOLATILE) p->sidefx=1;
+ return ok;
+ }
+ if(f==FIRSTELEMENT){
+ if(ISARRAY(p->left->ntyp->flags)){
+ p->ntyp=clone_typ(p->left->ntyp->next);
+ }else{
+ int i,n=-1;
+ for(i=0;i<p->left->ntyp->exact->count;i++)
+ if(!strcmp((*p->left->ntyp->exact->sl)[i].identifier,p->right->identifier)) n=i;
+ if(n<0) ierror(0);
+ p->ntyp=clone_typ((*p->left->ntyp->exact->sl)[n].styp);
+ }
+ p->lvalue=1; /* hier noch genauer testen ? */
+ return ok;
+ }
+ if(f==ADDRESS){
+ if(!ISFUNC(p->left->ntyp->flags)&&!ISARRAY(p->left->ntyp->flags)){
+ if(!p->left->lvalue){error(115);return 0;}
+ if(p->left->flags==IDENTIFIER){
+ Var *v;
+ v=find_var(p->left->identifier,0);
+ if(!v){error(116,p->left->identifier);return 0;}
+ if(v->storage_class==REGISTER)
+ {error(117);return 0;}
+ }
+ }
+ p->ntyp=new_typ();
+ p->ntyp->flags=ptype(p->left);
+ p->ntyp->next=clone_typ(p->left->ntyp);
+ fix_addr_ptype(p);
+ return ok;
+ }
+ if(f==ADDRESSA){
+ p->ntyp=clone_typ(p->left->ntyp);
+ p->ntyp->flags=ptype(p->left);
+ fix_addr_ptype(p);
+ return ok;
+ }
+ if(f==ADDRESSS){
+ int i,n=-1;
+ struct_list *sl=0;
+ if(!ecpp){
+ for(i=0;i<p->left->ntyp->exact->count;i++)
+ if(!strcmp((*p->left->ntyp->exact->sl)[i].identifier,p->right->identifier)) n=i;
+ if(n<0)
+ return 0;
+ else
+ sl=&(*p->left->ntyp->exact->sl)[n];
+ }
+#ifdef HAVE_ECPP
+/* 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
+ p->ntyp=new_typ();
+ if(!p->left->ntyp) ierror(0);
+ if(!p->left->ntyp->exact) ierror(0);
+ if(!sl->styp) ierror(0);
+ p->ntyp->next=clone_typ(sl->styp);
+ p->ntyp->flags=ptype(p->left);
+ fix_addr_ptype(p);
+ return ok;
+ }
+ if(f==DSTRUCT){
+ struct_declaration *sd=p->left->ntyp->exact;
+ char *identifier=p->right->identifier;
+ int i=0,f,bfs=-1,bfo=-1;type *t;np new;zmax offset=l2zm(0L);
+ if(!ISSTRUCT(p->left->ntyp->flags)&&!ISUNION(p->left->ntyp->flags))
+ {error(8);return 0;}
+ if(type_uncomplete(p->left->ntyp)){error(11);return 0;}
+ if(p->right->flags!=MEMBER) ierror(0);
+ if(i>=p->left->ntyp->exact->count) {error(23,p->right->identifier);return 0;}
+ if(!ecpp){
+ offset=struct_offset(sd,identifier);
+ }
+#ifdef HAVE_ECPP
+/* 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 */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif
+ if(ISUNION(p->left->ntyp->flags)) offset=l2zm(0L);
+ p->flags=CONTENT;
+ if(p->ntyp) {freetyp(p->ntyp);p->ntyp=0;}
+ new=new_node();
+ new->flags=ADD;
+ new->ntyp=0;
+ new->right=new_node();
+ new->right->left=new->right->right=0;
+ new->right->flags=PCEXPR;
+ new->right->ntyp=new_typ();
+ if(/*MINADDI2P<=INT&&*/zumleq(zm2zum(offset),t_max(INT))){
+ new->right->ntyp->flags=INT;
+ new->right->val.vint=zm2zi(offset);
+ }else{
+ new->right->ntyp->flags=LONG;
+ new->right->ntyp->next=0;
+ new->right->val.vlong=zm2zl(offset);
+ }
+ new->left=new_node();
+ new->left->flags=ADDRESSS;
+ new->left->left=p->left;
+ new->left->right=p->right;
+ new->left->ntyp=0;
+ p->left=new;p->right=0;
+
+ /* Check for bitfields */
+ i=0;
+ while(i<sd->count&&strcmp((*sd->sl)[i].identifier,identifier)){
+ i++;
+ }
+ if(i<sd->count){
+ bfo=(*sd->sl)[i].bfoffset;
+ bfs=(*sd->sl)[i].bfsize;
+ }else
+ bfs=-1;
+ if(bfs!=-1){
+ /* create a special node for bitfields */
+ ok|=type_expression2(p,0);
+ new=new_node();
+ *new=*p;
+ p->flags=BITFIELD;
+ p->left=new;
+ p->right=0;
+ p->sidefx=0;
+ p->bfs=bfs;
+ p->bfo=bfo;
+ p->ntyp=clone_typ(new->ntyp);
+ return ok;
+ }
+ return type_expression2(p,0);
+ }
+ if(f==PREINC||f==POSTINC||f==PREDEC||f==POSTDEC){
+ if(!p->left->lvalue){error(86);return 0;}
+ if(p->left->ntyp->flags&CONST){error(87);return 0;}
+ if(!ISARITH(p->left->ntyp->flags)){
+ if(!ISPOINTER(p->left->ntyp->flags)){
+ error(24);
+ return 0;
+ }else{
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ if((p->left->ntyp->next->flags&NQ)==VOID)
+ {error(95);return 0;}
+ }
+ }
+ p->ntyp=clone_typ(p->left->ntyp);
+ p->sidefx=1;
+ return ok;
+ }
+ if(f==CALL){
+ argument_list *al;int i,flags=0;char *s=0;
+ struct_declaration *sd;
+#ifdef HAVE_ECPP
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif
+ al=p->alist;
+ if(!ISPOINTER(p->left->ntyp->flags)||!ISFUNC(p->left->ntyp->next->flags))
+ {error(26);return 0;}
+ if(ok&&p->left->left&&p->left->left->flags==IDENTIFIER&&p->left->left->o.v->storage_class==EXTERN){
+ s=p->left->left->o.v->identifier;
+ flags=p->left->left->o.v->flags;
+ }
+ sd=p->left->ntyp->next->exact;
+ if(!sd) ierror(0);
+ if(sd->count==0){
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ error(162);
+ if(s){
+ if(!strcmp(s,"printf")||!strcmp(s,"fprintf")||!strcmp(s,"sprintf")||
+ !strcmp(s,"scanf")|| !strcmp(s,"fscanf")|| !strcmp(s,"sscanf"))
+ error(213);
+ }
+ }
+ if(!(ecpp&&al&&al->arg->ntyp)){
+ i=0;
+ while(al){
+ if(!al->arg) ierror(0);
+ if(!type_expression2(al->arg,(short_push&&i<sd->count)?(*sd->sl)[i].styp:0)) return 0;
+ al->arg=makepointer(al->arg);
+ if(type_uncomplete(al->arg->ntyp)) error(39);
+ al=al->next;
+ i++;
+ }
+ }
+ p->sidefx=1;
+ p->ntyp=clone_typ(p->left->ntyp->next->next);
+ i=0;al=p->alist;
+ while(al){
+ if(i>=sd->count) return ok;
+ if(!(*sd->sl)[i].styp) return ok; /* nur Bezeichner, aber kein Typ im Prototype */
+ if(!test_assignment((*sd->sl)[i].styp,al->arg)) return 0;
+#ifdef HAVE_MISRA
+/* removed */
+/* removed */
+#endif
+ if(i==sd->count-1&&(flags&(PRINTFLIKE|SCANFLIKE))){
+ if(al->arg->left&&al->arg->left->flags==STRING){
+ /* Argumente anhand des Formatstrings ueberpruefen */
+ const_list *cl=al->arg->left->cl;
+ int fused=0;long mask=1;
+ al=al->next;
+ while(cl&&cl->other){
+ int c,fflags=' ',at,lflag;
+ type *t;
+ enum{LL=1,HH};
+ c=(int)zm2l(zc2zm(cl->other->val.vchar));
+ cl=cl->next;
+ if(c==0){
+ if(cl) error(215);
+ break;
+ }
+ c=CHARBACK(c);
+ if(c!='%') continue;
+ if(!cl){error(214);return ok;}
+ lflag=0;
+ c=(int)zm2l(zc2zm(cl->other->val.vchar));
+ c=CHARBACK(c);
+ cl=cl->next;
+ while(isdigit((unsigned char)c)||
+ c=='-'||c=='+'||c==' '||c=='#'||c=='.'||
+ c=='h'||c=='l'||c=='L'||c=='z'||c=='j'||c=='t'||c=='*'){
+ if(c=='-') mask|=USELALGN;
+ if(c=='+') mask|=USESIGN;
+ if(c=='#') mask|=USEALT;
+ if(c=='.') mask|=USEPREC;
+ if(c==' ') mask|=USEBLANK;
+ if(c=='0'&&!(mask&USEPREC)&&!(mask&USEWIDTH)) mask|=USEZPAD;
+ if(isdigit((unsigned char)c)&&!(mask&USEPREC)) mask|=USEWIDTH;
+ fused|=3;
+ if(c=='*'&&(flags&PRINTFLIKE)){
+ mask|=USEAST;
+ if(!al) {error(214);return ok;}
+ at=al->arg->ntyp->flags&NQ;
+ al=al->next;
+ if(at>INT) {error(214);return ok;}
+ }
+ if((fflags!='*'||(flags&PRINTFLIKE))&&(c=='h'||c=='l'||c=='L'||c=='*'||c=='t'||c=='z'||c=='j')){
+ if(c=='l'&&fflags=='l')
+ fflags=LL;
+ else if(c=='h'&&fflags=='h')
+ fflags=HH;
+ else
+ fflags=c;
+ }
+ c=(int)zm2l(zc2zm(cl->other->val.vchar));
+ c=CHARBACK(c);
+ cl=cl->next;
+ if(!cl){error(214);return ok;}
+ }
+ /*FIXME: assumes intmax_t==long long */
+ if(fflags=='j') {mask|=USESPEC;fflags=LL;}
+#if HAVE_INT_SIZET
+ if(fflags=='z') {mask|=USESPEC;fflags=' ';}
+#else
+ if(fflags=='z') {mask|=USESPEC;fflags='l';}
+#endif
+ if(fflags=='t'){
+ mask|=USESPEC;
+ if(PTRDIFF_T(CHAR)==LLONG)
+ fflags=LL;
+ else if(PTRDIFF_T(CHAR)==LONG)
+ fflags='l';
+ else
+ fflags=' ';
+ }
+ if(fflags==HH) lflag|=USESPEC;
+ if(fflags=='h') lflag|=USEHALF;
+ if(fflags=='l') lflag|=USELONG;
+ if(fflags==LL) lflag|=USELLONG;
+ if(DEBUG&1) printf("format=%c%c\n",fflags,c);
+ if(fflags=='*'&&(flags&SCANFLIKE)) continue;
+ if(c!='%'){
+ if(!al){error(214);return ok;}
+ t=al->arg->ntyp;
+ if(DEBUG&1){ prd(stdout,t);printf("\n");}
+ if((flags&SCANFLIKE)){
+ if(!ISPOINTER(t->flags)){error(214);return ok;}
+ t=t->next;
+ }
+ at=t->flags&NU;
+ }
+ if(flags&PRINTFLIKE){
+ switch(c){
+ case '%':
+ mask|=USEPERC;
+ fused|=1;
+ break;
+ case 'o':
+ case 'x':
+ case 'X':
+ case 'c':
+ at&=NQ; /* fall through */
+ case 'i':
+ case 'd':
+ fused|=1;
+ if(at==LLONG&&fflags!=LL){error(214);return ok;}
+ if(at==LONG&&fflags!='l'){error(214);return ok;}
+ if(fflags=='l'&&at!=LONG){error(214);return ok;}
+ if(at<CHAR||at>LLONG){error(214);return ok;}
+ if(c=='o') mask|=USEOCT;
+ if(c=='x') mask|=USEHEXL;
+ if(c=='X') mask|=USEHEXU;
+ if(c=='i') mask|=USEINT;
+ if(c=='d') mask|=USEDEC;
+ if(c=='c') mask|=USECHAR;
+ mask|=lflag;
+ break;
+ case 'u':
+ mask|=USEUNS;
+ fused|=1;
+ if(al->arg->flags==CEXPR) at|=UNSIGNED;
+ if(at==(UNSIGNED|LLONG)&&fflags!=LL){error(214);return ok;}
+ if(at==(UNSIGNED|LONG)&&fflags!='l'){error(214);return ok;}
+ if(fflags=='l'&&at!=(UNSIGNED|LONG)){error(214);return ok;}
+ if(at<(UNSIGNED|CHAR)||at>(UNSIGNED|LLONG)){error(214);return ok;}
+ mask|=lflag;
+ break;
+ case 's':
+ mask|=USESTR;
+ fused|=1;
+ if(!ISPOINTER(at)||(t->next->flags&NQ)!=CHAR){error(214);return ok;}
+ break;
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ mask|=USEFLOAT;
+ fused|=7;
+ if(fflags=='L'){
+ if(at!=LDOUBLE){error(214); return ok;}
+ }else{
+ if(at!=FLOAT&&at!=DOUBLE){error(214);return ok;}
+ }
+ break;
+ case 'p':
+ mask|=USESPEC;
+ fused|=3;
+ if(!ISPOINTER(at)||(t->next->flags)!=VOID){error(214);return ok;}
+ break;
+ case 'n':
+ mask|=USECNT;
+ fused|=3;
+ if(!ISPOINTER(at)){error(214);return ok;}
+ at=t->next->flags&NU;
+ if(fflags==HH&&at!=CHAR){error(214);return ok;}
+ if(fflags=='h'&&at!=SHORT){error(214);return ok;}
+ if(fflags==' '&&at!=INT){error(214);return ok;}
+ if(fflags=='l'&&at!=LONG){error(214);return ok;}
+ if(fflags==LL&&at!=LLONG){error(214);return ok;}
+ break;
+ default:
+ error(214);return ok;
+ }
+ }else{
+ if(c=='s') mask|=USESTR;
+ if(c=='c') mask|=USECHAR;
+ if(c=='n') mask|=USECNT;
+ if(c=='d') mask|=USEDEC;
+ if(c=='i') mask|=USEINT;
+ if(c=='o') mask|=USEOCT;
+ if(c=='x') mask|=USEHEXL;
+ if(c=='u') mask|=USEUNS;
+
+ switch(c){
+ case '%':
+ mask|=USEPERC;
+ fused|=1;
+ break;
+ case '[':
+ mask|=USEREXP;
+ fused|=3;
+ do{
+ c=(int)zm2l(zc2zm(cl->other->val.vchar));
+ c=CHARBACK(c);
+ cl=cl->next;
+ if(!cl){error(214);return ok;}
+ }while(c!=']'); /* fall through */
+ case 's':
+ case 'c':
+ fused|=1;
+ if((at&NQ)!=CHAR){error(214);return(ok);}
+ break;
+ case 'n':
+ fused|=3; /* fall through */
+ case 'd':
+ case 'i':
+ case 'o':
+ fused|=1;
+ if(fflags==HH&&at!=CHAR){error(214);return ok;}
+ if(fflags=='h'&&at!=SHORT){error(214);return ok;}
+ if(fflags==' '&&at!=INT){error(214);return ok;}
+ if(fflags=='l'&&at!=LONG){error(214);return ok;}
+ if(fflags==LL&&at!=LLONG){error(214);return ok;}
+ break;
+ case 'x':
+ case 'u':
+ fused|=1;
+ if(fflags==HH&&at!=CHAR){error(214);return ok;}
+ if(fflags=='h'&&at!=(UNSIGNED|SHORT)){error(214);return ok;}
+ if(fflags==' '&&at!=(UNSIGNED|INT)){error(214);return ok;}
+ if(fflags=='l'&&at!=(UNSIGNED|LONG)){error(214);return ok;}
+ if(fflags==LL&&at!=(UNSIGNED|LLONG)){error(214);return ok;}
+ break;
+ case 'e':
+ case 'f':
+ case 'g':
+ mask|=USEFLOAT;
+ fused|=7;
+ if(fflags==' '&&at!=FLOAT){error(214);return ok;}
+ if(fflags=='l'&&at!=DOUBLE){error(214);return ok;}
+ if(fflags=='L'&&at!=LDOUBLE){error(214);return ok;}
+ break;
+ case 'p':
+ mask|=USESPEC;
+ fused|=3;
+ if(!ISPOINTER(at)||(t->next->flags&NQ)!=VOID){error(214);return ok;}
+ break;
+ default:
+ error(214);return ok;
+ }
+ }
+ if(c!='%') al=al->next;
+ }
+ if(al){ error(214);return ok;} /* zu viele */
+ if(DEBUG&1) printf("fused=%d\n",fused);
+ if(mask_opt){
+ Var *v;char repl[MAXI+16];
+ if(mask){
+ sprintf(repl,"%s.%lu",s,1L);
+ v=find_var(repl,0);
+ if(!v){
+ type *t;
+ v=find_var(s,0);
+ if(!v) ierror(0);
+ v=add_var(repl,clone_typ(v->vtyp),EXTERN,0);
+ }
+ }
+ if(mask)
+ sprintf(repl,"%s.%lu",(flags&PRINTFLIKE)?"vfprintf":"vfscanf",mask);
+ else
+ sprintf(repl,"%s",(flags&PRINTFLIKE)?"vfprintf":"vfscanf");
+ needs(repl);
+ p->left->left->o.v=v;
+ if(DEBUG&1) printf("repl=%s\n",repl);
+ }else if(fused!=7&&s){
+ /* Wenn kein Format benutzt wird, kann man printf, */
+ /* scanf etc. durch aehnliches ersetzen. */
+ Var *v;char repl[MAXI+6]="__v";
+ if(fused==3) fused=2;
+ repl[3]=fused+'0';repl[4]=0;
+ strcat(repl,s);
+ if(DEBUG&1) printf("repl=%s\n",repl);
+ while(fused<=2){
+ v=find_var(repl,0);
+ if(v&&v->storage_class==EXTERN){
+ p->left->left->o.v=v;
+ break;
+ }
+ fused++;repl[3]++;
+ }
+ }
+ return ok;
+ }
+ }
+ i++;al=al->next;
+ }
+ if(i>=sd->count) return ok;
+ if((*sd->sl)[i].styp&&((*sd->sl)[i].styp->flags&NQ)!=VOID){error(83);/*printf("sd->count=%d\n",sd->count);*/}
+ return ok;
+ }
+ if(f==COND){
+ if(!ISARITH(p->left->ntyp->flags)&&!ISPOINTER(p->left->ntyp->flags)){
+ error(29);
+ return 0;
+ }
+ if(p->left->flags==CEXPR&&!p->left->sidefx){
+ int null;np merk;
+ if(DEBUG&1) printf("constant conditional-expression simplified\n");
+ eval_constn(p->left);
+ if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0)))
+ null=1;
+ else
+ null=0;
+ free_expression(p->left);
+ merk=p->right;
+ if(null){
+ free_expression(p->right->left);
+ *p=*p->right->right;
+ }else{
+ free_expression(p->right->right);
+ *p=*p->right->left;
+ }
+ if(merk->ntyp) freetyp(merk->ntyp);
+ free(merk);
+ return 1;
+ }
+ if(const_expr){error(46);return 0;}
+ p->ntyp=clone_typ(p->right->ntyp);
+ return 1;
+ }
+ if(f==COLON){
+ /* Hier fehlt noch korrekte Behandlung der Typattribute */
+ if(ISARITH(p->left->ntyp->flags)&&ISARITH(p->right->ntyp->flags)){
+ p->ntyp=arith_typ(p->left->ntyp,p->right->ntyp);
+ return 1;
+ }
+ if(compatible_types(p->left->ntyp,p->right->ntyp,NQ)){
+ p->ntyp=clone_typ(p->left->ntyp);
+ return 1;
+ }
+ if(ISPOINTER(p->left->ntyp->flags)&&ISPOINTER(p->right->ntyp->flags)){
+ if((p->left->ntyp->next->flags&NQ)==VOID){
+ if(nullpointer(p->left))
+ p->ntyp=clone_typ(p->right->ntyp);
+ else
+ p->ntyp=clone_typ(p->left->ntyp);
+ return 1;
+ }
+ if((p->right->ntyp->next->flags&NQ)==VOID){
+ if(nullpointer(p->right))
+ p->ntyp=clone_typ(p->left->ntyp);
+ else
+ p->ntyp=clone_typ(p->right->ntyp);
+ return 1;
+ }
+ }
+ if(ISPOINTER(p->left->ntyp->flags)&&p->right->flags==CEXPR){
+ eval_constn(p->right);
+ if(zmeqto(vmax,l2zm(0L))&&zumeqto(ul2zum(0UL),vumax)&&zldeqto(d2zld(0.0),vldouble)){
+ p->ntyp=clone_typ(p->left->ntyp);
+ return 1;
+ }
+ }
+ if(ISPOINTER(p->right->ntyp->flags)&&p->left->flags==CEXPR){
+ eval_constn(p->left);
+ if(zmeqto(l2zm(0L),vmax)&&zumeqto(ul2zum(0UL),vumax)&&zldeqto(d2zld(0.0),vldouble)){
+ p->ntyp=clone_typ(p->right->ntyp);
+ return 1;
+ }
+ }
+ error(31);
+ return 0;
+ }
+ if(f) printf("type_testing fuer diesen Operator (%d) noch nicht implementiert\n",f);
+ return 0;
+}
+
+np makepointer(np p)
+/* Fuehrt automatische Zeigererzeugung fuer Baumwurzel durch */
+/* Durch mehrmaligen Aufruf von type_expression() ineffizient */
+{
+ struct_declaration *sd;
+ if(ISARRAY(p->ntyp->flags)||ISFUNC(p->ntyp->flags)){
+ np new=new_node();
+ if(ISARRAY(p->ntyp->flags)){
+ new->flags=ADDRESSA;
+ new->ntyp=clone_typ(p->ntyp);
+ new->ntyp->flags=POINTER_TYPE(new->ntyp->next);
+ }else{
+ new->flags=ADDRESS;
+ new->ntyp=new_typ();
+ new->ntyp->flags=POINTER_TYPE(p->ntyp);
+ new->ntyp->next=clone_typ(p->ntyp);
+ }
+ new->left=p;
+ new->right=0;
+ new->lvalue=0; /* immer korrekt ? */
+ new->sidefx=p->sidefx;
+/* type_expression(new);*/
+ return new;
+ }else
+ return p;
+}
+
+void simple_alg_opt(np p)
+{
+ int c=0,f,t=0;
+ zldouble d1,d2;
+ zumax u1,u2;zmax s1,s2;
+ Var *v;
+
+ if(!p) return;
+
+ f=p->flags;
+
+ if(f==IDENTIFIER&&(v=find_var(p->identifier,0))&&(v->vtyp->flags&NQ)==ENUM){
+ /* enumerations auch als Konstante (int) behandeln */
+ p->flags=CEXPR;
+ if(!v->clist) ierror(0);
+ p->val=v->clist->val;
+ if(!p->ntyp) p->ntyp=new_typ();
+ p->ntyp->flags=CONST|INT;
+ return;
+ }
+
+
+ if(p->left)
+ simple_alg_opt(p->left);
+ else
+ return;
+ if(p->right)
+ simple_alg_opt(p->right);
+
+ if(p->left->flags==CEXPR||p->left->flags==PCEXPR){
+ eval_constn(p->left);
+ d1=vldouble;u1=vumax;s1=vmax;c|=1;
+ }
+ if(p->right&&(p->right->flags==CEXPR||p->right->flags==PCEXPR)){
+ eval_constn(p->right);
+ d2=vldouble;u2=vumax;s2=vmax;c|=2;
+ }
+
+ if(p->ntyp) t=p->ntyp->flags;
+
+ if(c==3&&((f>=OR&&f<=AND)||(f>=LSHIFT&&f<=MOD))){
+ if(DEBUG&1) printf("did simple_alg constant folding\n");
+ if(!t) t=arith_flag(p->left->ntyp->flags,p->right->ntyp->flags);
+ if(DEBUG&1) printf("did simple constant folding\n");
+
+ if(f==AND&&ISINT(t)){
+ vumax=zumand(u1,u2);
+ vmax=zmand(s1,s2);
+ }
+ if(f==OR&&ISINT(t)){
+ vumax=zumor(u1,u2);
+ vmax=zmor(s1,s2);
+ }
+ if(f==XOR&&ISINT(t)){
+ vumax=zumxor(u1,u2);
+ vmax=zmxor(s1,s2);
+ }
+ if(f==ADD){
+ vumax=zumadd(u1,u2);
+ vmax=zmadd(s1,s2);
+ vldouble=zldadd(d1,d2);
+ }
+ if(f==SUB){
+ vumax=zumsub(u1,u2);
+ vmax=zmsub(s1,s2);
+ vldouble=zldsub(d1,d2);
+ }
+ if(f==MULT||f==PMULT){
+ vumax=zummult(u1,u2);
+ vmax=zmmult(s1,s2);
+ vldouble=zldmult(d1,d2);
+ if(f==PMULT) p->flags=PCEXPR;
+ }
+ if(f==DIV){
+ if(zmeqto(l2zm(0L),s2)&&zumeqto(ul2zum(0UL),u2)&&zldeqto(d2zld(0.0),d2)){
+ error(84);
+ vmax=l2zm(0L);vumax=ul2zum(0UL);vldouble=d2zld(0.0);
+ }else{
+ if(!zumeqto(ul2zum(0UL),u2)) vumax=zumdiv(u1,u2);
+ if(!zmeqto(l2zm(0L),s2)) vmax=zmdiv(s1,s2);
+ if(!zldeqto(d2zld(0.0),d2)) vldouble=zlddiv(d1,d2);
+ }
+ }
+ if(f==MOD&&ISINT(t)){
+ if(zmeqto(l2zm(0L),s2)&&zumeqto(ul2zum(0UL),u2)){
+ error(84);
+ vmax=l2zm(0L);vumax=zm2zum(vmax);
+ }else{
+ if(!zumeqto(ul2zum(0UL),u2)) vumax=zummod(u1,u2);
+ if(!zmeqto(l2zm(0L),s2)) vmax=zmmod(s1,s2);
+ }
+ }
+ if(f==LSHIFT&&ISINT(t)){
+ vumax=zumlshift(u1,u2);
+ vmax=zmlshift(s1,s2);
+ }
+ if(f==RSHIFT&&ISINT(t)){
+ vumax=zumrshift(u1,u2);
+ vmax=zmrshift(s1,s2);
+ }
+ }else if(c==1&&f==MINUS){
+ if(!t) t=arith_flag(p->left->ntyp->flags,p->left->ntyp->flags);
+ vmax=zmsub(Z0,s1);
+ vumax=zumsub(ZU0,u1);
+ vldouble=zldsub(d2zld(0.0),d1);
+ }else if(c==1&&f==KOMPLEMENT){
+ if(!t) t=arith_flag(p->left->ntyp->flags,p->left->ntyp->flags);
+ if(!ISINT(t)) return;
+ vmax=zmkompl(s1);
+ vumax=zumkompl(u1);
+ }else if(c==1&&f==NEGATION){
+ if(!p->left->ntyp) return;
+ t=INT;
+ if(!ISINT(p->left->ntyp->flags)){
+ if(zldeqto(d1,d2zld(0.0))) vmax=Z1; else vmax=Z0;
+ }else if(p->left->ntyp->flags&UNSIGNED){
+ if(zumeqto(u1,ZU0)) vmax=Z1; else vmax=Z0;
+ }else
+ if(zmeqto(s1,Z0)) vmax=Z1; else vmax=Z0;
+ }else
+ return;
+
+ p->flags=CEXPR;
+ if(p->left&&!p->left->sidefx) {free_expression(p->left);p->left=0;}
+ if(p->right&&p->right->sidefx) {free_expression(p->right);p->right=0;}
+
+ if(ISFLOAT(t)){
+ gval.vldouble=vldouble;
+ eval_const(&gval,LDOUBLE);
+ }else{
+ if(t&UNSIGNED){
+ gval.vumax=vumax;
+ eval_const(&gval,(UNSIGNED|MAXINT));
+ }else{
+ gval.vmax=vmax;
+ eval_const(&gval,MAXINT);
+ }
+ }
+ insert_const(&p->val,t);
+ if(!p->ntyp){p->ntyp=new_typ();p->ntyp->flags=t;}
+}
+
+
+int alg_opt(np p,type *ttyp)
+/* fuehrt algebraische Vereinfachungen durch */
+/* hier noch genau testen, was ANSI-gemaess erlaubt ist etc. */
+/* v.a. Floating-Point ist evtl. kritisch */
+{
+ int c=0,f,komm,null1,null2,eins1,eins2;np merk;
+ zldouble d1,d2;zumax u1,u2;zmax s1,s2;
+ f=p->flags;
+
+ /* do not optimze pointer-pointer */
+ if(f==SUB&&ISPOINTER(p->left->ntyp->flags)&&ISPOINTER(p->right->ntyp->flags))
+ return 1;
+
+ /* kommutativ? */
+ if(f==ADD||f==MULT||f==PMULT||(f>=OR&&f<=AND)) komm=1; else komm=0;
+ /* Berechnet Wert, wenn beides Konstanten sind */
+ if(p->left->flags==CEXPR||p->left->flags==PCEXPR){
+ eval_constn(p->left);
+ d1=vldouble;u1=vumax;s1=vmax;c|=1;
+ }
+ if(p->right->flags==CEXPR||p->right->flags==PCEXPR){
+ eval_constn(p->right);
+ d2=vldouble;u2=vumax;s2=vmax;c|=2;
+ }
+ if(c==3){
+ p->flags=CEXPR;
+ if(DEBUG&1) printf("did simple constant folding\n");
+ if(!p->left->sidefx) {free_expression(p->left);p->left=0;}
+ if(!p->right->sidefx) {free_expression(p->right);p->right=0;}
+ if(f==AND){
+ vumax=zumand(u1,u2);
+ vmax=zmand(s1,s2);
+ }
+ if(f==OR){
+ vumax=zumor(u1,u2);
+ vmax=zmor(s1,s2);
+ }
+ if(f==XOR){
+ vumax=zumxor(u1,u2);
+ vmax=zmxor(s1,s2);
+ }
+ if(f==ADD){
+ vumax=zumadd(u1,u2);
+ vmax=zmadd(s1,s2);
+ vldouble=zldadd(d1,d2);
+ }
+ if(f==SUB){
+ vumax=zumsub(u1,u2);
+ vmax=zmsub(s1,s2);
+ vldouble=zldsub(d1,d2);
+ }
+ if(f==MULT||f==PMULT){
+ vumax=zummult(u1,u2);
+ vmax=zmmult(s1,s2);
+ vldouble=zldmult(d1,d2);
+ if(f==PMULT) p->flags=PCEXPR;
+ }
+ if(f==DIV){
+ if(zmeqto(l2zm(0L),s2)&&zumeqto(ul2zum(0UL),u2)&&zldeqto(d2zld(0.0),d2)){
+ error(84);
+ vmax=l2zm(0L);vumax=ul2zum(0UL);vldouble=d2zld(0.0);
+ }else{
+ if(!zumeqto(ul2zum(0UL),u2)) vumax=zumdiv(u1,u2);
+ if(!zmeqto(l2zm(0L),s2)) vmax=zmdiv(s1,s2);
+ if(!zldeqto(d2zld(0.0),d2)) vldouble=zlddiv(d1,d2);
+ }
+ }
+ if(f==MOD){
+ if(zmeqto(l2zm(0L),s2)&&zumeqto(ul2zum(0UL),u2)){
+ error(84);
+ vmax=l2zm(0L);vumax=zm2zum(vmax);
+ }else{
+ if(!zumeqto(ul2zum(0UL),u2)) vumax=zummod(u1,u2);
+ if(!zmeqto(l2zm(0L),s2)) vmax=zmmod(s1,s2);
+ }
+ }
+ if(f==LSHIFT){
+ vumax=zumlshift(u1,u2);
+ vmax=zmlshift(s1,s2);
+ }
+ if(f==RSHIFT){
+ vumax=zumrshift(u1,u2);
+ vmax=zmrshift(s1,s2);
+ }
+ if(ISFLOAT(p->ntyp->flags)){
+ gval.vldouble=vldouble;
+ eval_const(&gval,LDOUBLE);
+ }else{
+ if(p->ntyp->flags&UNSIGNED){
+ gval.vumax=vumax;
+ eval_const(&gval,(UNSIGNED|MAXINT));
+ }else{
+ gval.vmax=vmax;
+ eval_const(&gval,MAXINT);
+ }
+ }
+ insert_constn(p);
+ return 1;
+ }
+ /* Konstanten nach rechts, wenn moeglich */
+ if(c==1&&komm){
+ if(DEBUG&1) printf("exchanged commutative constant operand\n");
+ merk=p->left;p->left=p->right;p->right=merk;
+ c=2;
+ d2=d1;u2=u1;s2=s1;
+ }
+ /* Vertauscht die Knoten, um Konstanten */
+ /* besser zusammenzufassen (bei allen Type erlaubt?) */
+ /* Hier muss noch einiges kontrolliert werden */
+ if(komm&&c==2&&p->flags==p->left->flags&&(ISINT(p->ntyp->flags)||c_flags[21]&USEDFLAG)){
+ if(p->left->right->flags==CEXPR||p->left->right->flags==PCEXPR){
+ np merk;
+ merk=p->right;p->right=p->left->left;p->left->left=merk;
+ if(DEBUG&1) printf("Vertausche Add-Nodes\n");
+ dontopt=0;
+ return type_expression2(p,ttyp);
+ }
+ }
+ null1=null2=eins1=eins2=0;
+ if(c&1){
+ if(zldeqto(d1,d2zld(0.0))&&zumeqto(u1,ul2zum(0UL))&&zmeqto(s1,l2zm(0L))) null1=1;
+ if(zldeqto(d1,d2zld(1.0))&&zumeqto(u1,ul2zum(1UL))&&zmeqto(s1,l2zm(1L))) eins1=1;
+ if(!(p->ntyp->flags&UNSIGNED)&&zldeqto(d1,d2zld(-1.0))&&zmeqto(s1,l2zm(-1L))) eins1=-1;
+ }
+ if(c&2){
+ if(zldeqto(d2,d2zld(0.0))&&zumeqto(u2,ul2zum(0UL))&&zmeqto(s2,l2zm(0L))) null2=1;
+ if(zldeqto(d2,d2zld(1.0))&&zumeqto(u2,ul2zum(1UL))&&zmeqto(s2,l2zm(1L))) eins2=1;
+ if(!(p->ntyp->flags&UNSIGNED)&&zldeqto(d2,d2zld(-1.0))&&zmeqto(s2,l2zm(-1L))) eins2=-1;
+ }
+ if(c==2){
+ /* a+0=a-0=a^0=a>>0=a<<0=a*1=a/1=a */
+ if(((eins2==1&&(f==MULT||f==PMULT||f==DIV))||(null2&&(f==ADD||f==SUB||f==OR||f==XOR||f==LSHIFT||f==RSHIFT)))&&!p->right->sidefx){
+ if(DEBUG&1){if(f==MULT||f==PMULT||f==DIV) printf("a*/1->a\n"); else printf("a+-^0->a\n");}
+ free_expression(p->right);
+ merk=p->left;
+ *p=*p->left;
+/* freetyp(merk->ntyp); das war Fehler */
+ free(merk);
+ dontopt=0;
+ return type_expression2(p,ttyp);
+ }
+ /* a*0=0 */
+ if(null2&&(f==MULT||f==PMULT||f==AND||f==DIV||f==MOD)){
+ if(DEBUG&1) printf("a*&/%%0->0\n");
+ if(null2&&(f==DIV||f==MOD)) error(84);
+ if(p->flags==PMULT) p->flags=PCEXPR; else p->flags=CEXPR;
+ gval.vint=zm2zi(l2zm(0L));
+ eval_const(&gval,INT);
+ /* hier nur int,long,float,double moeglich, hoffe ich */
+ insert_constn(p);
+ if(!p->left->sidefx){free_expression(p->left);p->left=0;} else make_cexpr(p->left);
+ if(!p->right->sidefx){free_expression(p->right);p->right=0;} else make_cexpr(p->right);
+
+/* return(type_expression2(p,ttyp)); */
+ return 1;
+ }
+ if(eins2==-1&&(f==MULT||f==PMULT||f==DIV)&&!p->right->sidefx){
+ if(DEBUG&1) printf("a*/(-1)->-a\n");
+ free_expression(p->right);
+ p->right=0;
+ p->flags=MINUS;
+ dontopt=0;
+ return type_expression2(p,ttyp);
+ }
+ /* check volatile */
+ if(0) /* TODO: make this efficient */
+ {
+ type st={0};
+ if(!zmeqto(sizetab[CHAR],sizetab[SHORT])){
+ //if(f==AND&&(!ttyp||(ttyp->flags&NQ)>CHAR)&&shortcut(AND,CHAR)&&zumleq(u2,t_max[CHAR]))
+ //st.flags=CHAR;
+ if(f==AND&&(!ttyp||(ttyp->flags&NQ)>CHAR)/*&&(p->ntyp->flags&UNSIGNED)*/&&shortcut(AND,UNSIGNED|CHAR)&&zumleq(u2,tu_max[CHAR]))
+ st.flags=UNSIGNED|CHAR;
+ }
+ if(!zmeqto(sizetab[SHORT],sizetab[INT])){
+ //if(f==AND&&(!ttyp||(ttyp->flags&NQ)>SHORT)&&shortcut(AND,SHORT)&&zumleq(s2,t_max[SHORT]))
+ //st.flags=SHORT;
+ if(f==AND&&(!ttyp||(ttyp->flags&NQ)>SHORT)/*&&(p->ntyp->flags&UNSIGNED)*/&&shortcut(AND,UNSIGNED|SHORT)&&zumleq(u2,tu_max[SHORT]))
+ st.flags=UNSIGNED|SHORT;
+ }
+ //if(!ttyp&&(p->left->ntyp->flags&NQ)>INT) st.flags=0;
+ if(st.flags){
+ int ret;type *otyp;np n;
+ if(!p->ntyp) ierror(0);
+ otyp=clone_typ(p->ntyp);
+ n=new_node();
+ n->left=p->left;
+ n->right=0;
+ n->flags=CAST;
+ n->ntyp=clone_typ(&st);
+ eval_const(&p->right->val,p->right->ntyp->flags);
+ p->right->ntyp->flags=st.flags;
+ insert_const(&p->right->val,st.flags);
+ p->left=n;
+ n=new_node();
+ *n=*p;
+ p->left=n;
+ p->right=0;
+ p->flags=CAST;
+ p->ntyp=otyp;
+ ret=type_expression2(p->left,&st);
+
+ return ret;
+ }
+ }
+
+ }
+ if(c==1){
+ /* 0-a=-a */
+ if(f==SUB&&null1&&!p->left->sidefx){
+ if(DEBUG&1) printf("0-a->-a\n");
+ free_expression(p->left);
+ p->flags=MINUS;
+ p->left=p->right;
+ p->right=0;
+ dontopt=0;
+ return type_expression2(p,ttyp);
+ }
+ /* 0/a=0 */
+ if(null1&&(f==DIV||f==MOD||f==LSHIFT||f==RSHIFT)){
+ if(DEBUG&1) printf("0/%%<<>>a->0\n");
+ p->flags=CEXPR;
+ gval.vint=zm2zi(l2zm(0L));
+ eval_const(&gval,INT);
+ insert_constn(p);
+ if(!p->left->sidefx){free_expression(p->left);p->left=0;}else make_cexpr(p->left);
+ if(!p->right->sidefx){free_expression(p->right);p->right=0;} else make_cexpr(p->right);
+ dontopt=0;
+ return type_expression2(p,ttyp);
+ }
+ }
+ return 1;
+}
+void make_cexpr(np p)
+/* Macht aus einem Knoten, der durch constant-folding ueberfluessig */
+/* wurde, eine PCEXPR, sofern er keine Nebenwirkungen von sich aus */
+/* erzeugt. Hier noch ueberpruefen, ob CEXPR besser waere. */
+/* Fuehrt rekursiven Abstieg durch. Ist das so korrekt? */
+{
+ int f=p->flags;
+ if(f!=ASSIGN&&f!=ASSIGNOP&&f!=CALL&&f!=POSTINC&&f!=POSTDEC&&f!=PREINC&&f!=PREDEC&&f!=LAND&&f!=LOR){
+ p->flags=PCEXPR;
+ if(p->left) make_cexpr(p->left);
+ if(p->right) make_cexpr(p->right);
+ }
+}
+int test_assignment(type *zt,np q)
+/* testet, ob q an Typ z zugewiesen werden darf */
+{
+ type *qt=q->ntyp;
+ if(ISARITH(zt->flags)&&ISARITH(qt->flags)){
+ if(ISINT(zt->flags)&&ISINT(qt->flags)&&
+ !zmleq(sizetab[qt->flags&NQ],sizetab[zt->flags&NQ])&&q->flags!=CEXPR){
+#ifdef HAVE_MISRA
+/* removed */
+#endif
+ error(166);
+ }
+ if(q->flags==CEXPR){
+ zmax ms,ns;zumax mu,nu;
+ eval_constn(q);
+ ms=vmax;mu=vumax;
+ insert_const(&gval,zt->flags&~UNSIGNED);
+ eval_const(&gval,zt->flags&~UNSIGNED);
+ ns=vmax;
+ eval_constn(q);
+ insert_const(&gval,zt->flags|UNSIGNED);
+ eval_const(&gval,zt->flags|UNSIGNED);
+ nu=vumax;
+ if(!zumeqto(nu,mu)&&!zmeqto(ns,ms))
+ error(363);
+ else{
+ if(zt->flags&UNSIGNED){
+ if(!zumeqto(nu,mu))
+ error(362);
+ }else{
+ if(!zmeqto(ns,ms))
+ error(362);
+ }
+ }
+ }
+ return 1;
+ }
+ if((ISSTRUCT(zt->flags)&&ISSTRUCT(qt->flags))||
+ (ISUNION(zt->flags)&&ISUNION(qt->flags))){
+ if(!compatible_types(zt,qt,NU)){
+ error(38);
+ return 0;
+ }else
+ return 1;
+ }
+ if(ISVECTOR(zt->flags)&&(zt->flags&NU)==(qt->flags&NU)){
+ return 1;
+ }
+ if(ISPOINTER(zt->flags)&&ISPOINTER(qt->flags)){
+ if((zt->next->flags&NQ)==VOID&&!ISFUNC(qt->next->flags)) return 1;
+ if((qt->next->flags&NQ)==VOID&&!ISFUNC(qt->next->flags)) return 1;
+ if(!compatible_types(zt->next,qt->next,(c_flags[7]&USEDFLAG)?NU:NQ)){
+ if(!ecpp){
+ error(85);
+ }
+#ifdef HAVE_ECPP
+/* 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
+ }else{
+ if((qt->next->flags&CONST)&&!(zt->next->flags&CONST))
+ error(91);
+ if((qt->next->flags&VOLATILE)&&!(zt->next->flags&VOLATILE))
+ error(100);
+ if((qt->next->flags&RESTRICT)&&!(zt->next->flags&RESTRICT))
+ error(298);
+ if(qt->next->next&&zt->next->next&&!compatible_types(zt->next->next,qt->next->next,NU))
+ error(110);
+ }
+ return 1;
+ }
+ if(ISPOINTER(zt->flags)&&q->flags==CEXPR){
+ eval_constn(q);
+ if(!(zldeqto(d2zld(0.0),vldouble)&&zmeqto(l2zm(0L),vmax)&&zumeqto(ul2zum(0UL),vumax)))
+ error(113);
+ return 1;
+ }
+ error(39);
+ return 0;
+}
+#ifdef HAVE_ECPP
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* 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 */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif