/*  $VER: vbcc (declaration.c) $Revision: 1.90 $    */

#include <string.h>
#include <stdio.h>

#include "vbcc_cpp.h"
#include "vbc.h"

static char FILE_[]=__FILE__;

#define PLAIN_STORAGE_CLASS 7
#define PARAMETER 8
#define OLDSTYLE 16

void dynamic_init(Var *v,type *t,const_list *cl,zmax of,int noconst);
int test_assignment(type *,np);
int return_sc,return_reg,has_return,return_inline;
char *return_vattr;
static int did_return_label;
#ifdef HAVE_TARGET_ATTRIBUTES
unsigned long return_tattr;
#endif
zumax return_mask;
zmax init_dyn_sz,init_const_sz;
int init_dyn_cnt,init_const_cnt;

void init_sl(struct_list *sl);

#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 */
#endif

extern np gen_libcall(char *,np,type *,np,type *);
extern int float_used;
extern void optimize(long,Var *);

extern type uct;

void needs(char *s)
{
  Var *v;
  if(!(v=find_ext_var(s))||!strcmp(v->identifier,s)){
    Var *needs=add_var(s,clone_typ(&uct),EXTERN,0);
    needs->flags|=(USEDASSOURCE|REFERENCED|NEEDS);
  }		
}

static void clear_main_ret(void)
{
  if(c99&&!strcmp(cur_func,"main")&&return_typ&&ISSCALAR(return_typ->flags)){
    /* in c99, main returns 0 if it falls from back */
    IC *new=new_IC();
    new->code=SETRETURN;
    new->q1.val.vmax=l2zm(0L);
    eval_const(&new->q1.val,MAXINT);
    insert_const(&new->q1.val,return_typ->flags&NU);
    new->q1.flags=KONST;
    new->typf=return_typ->flags;
    new->q2.val.vmax=szof(return_typ);
    new->q2.flags=new->z.flags=0;
    new->z.reg=freturn(return_typ);
    add_IC(new);
  }
}

static char *get_string(void)
/* Liest Stringkonstante und liefert Wert als String (malloced) */
{
  np tree;int l;char *p;
  const_list *cl;
  killsp();
  if(ctok->type!=T_STRING) {error(74);return 0;}
  tree=string_expression();
  if(!tree||tree->flags!=STRING){
    error(229);
    return 0;
  }
  cl=tree->cl;l=0;
  while(cl){
    l++;
    cl=cl->next;
  }
  p=mymalloc(l);
  cl=tree->cl;l=0;
  while(cl){
    p[l]=CHARBACK(zm2l(zc2zm(cl->other->val.vchar)));
    l++;
    cl=cl->next;
  }
  if(tree) free_expression(tree);
  killsp();
  return p;
}

/* checks whether string is a valid vector type */
/* returns the dimension */
static int check_vect(char *s,char *base)
{
  int i=strlen(base),dim;
  if(strncmp(s,base,i)) return 0;
  dim=s[i];
  if(dim=='2'||dim=='3'||dim=='4'||dim=='8'){
    if(s[i+1]==0)
      return dim-'0';
    else
      return 0;
  }
  if(s[i]=='1'&&s[i+1]=='6'&&s[i+2]==0)
    return 16;
  return 0;
}

int settyp(int typnew, int typold)
/* Unterroutine fuer declaration_specifiers().              */
{
  if(DEBUG&2) printf("settyp: new=%d old=%d\n",typnew,typold);
  if(typold==LONG&&typnew==FLOAT){ error(203); return DOUBLE;}
  if(typold==LONG&&typnew==DOUBLE) return LDOUBLE;
  if(c99&&typold==LONG&&typnew==LONG) return LLONG;
  if(typold==INT&&(typnew==SHORT||typnew==LONG)) return typnew;
  if(typold!=0&&typnew!=INT){error(47);return(typnew);}
  if(typold==0&&typnew==INT) return(INT);
  if(typold==0) return(typnew);
  if(typold==SHORT||typold==LONG||typold==LLONG) return(typold);
  error(48);
  return(typnew);
}

#define dsc if(storage_class) error(49); if(typ||type_qualifiers) error(50)
#define XSIGNED 16384

#ifdef HAVE_MISRA
/* removed */
#endif

type *declaration_specifiers(void)
/* Erzeugt neuen Typ und gibt Zeiger darauf zurueck,      */
/* parst z.B. unsigned int, bla etc.               */
{
  int typ=0,type_qualifiers=0,notdone,storage_class,hard_reg,have_inline;
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
#endif
  char *imerk,sident[MAXI],sbuff[MAXI],*attr=0,*vattr=0;
  zumax mask=ul2zum(0UL);
  type *new=new_typ(),*t,*ts;
  struct_declaration *ssd;
  struct_list (*sl)[];
  size_t slsz;
  Var *v;
  int dim;
#ifdef HAVE_TARGET_ATTRIBUTES
  unsigned long tattr=0;
#endif
  storage_class=hard_reg=have_inline=0;
  do{
    killsp();notdone=0;
    if(ctok->type==NAME){
      if(!strcmp("struct",ctok->name)||!strcmp("union",ctok->name)||(ecpp&&!strcmp("class",ctok->name))){
        if(!strcmp("struct",ctok->name)) notdone=STRUCT;
        if(!strcmp("union",ctok->name)) {
          notdone=UNION;
#ifdef HAVE_MISRA
/* removed */
#endif
        }
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
        next_token();
        killsp();
        if(ctok->type!=LBRA){
          cpbez(sident,1);
          next_token();
          killsp();
          ssd=find_struct(sident,0);
#ifdef HAVE_MISRA
/* removed */
#endif
          if(ssd&&ctok->type==LBRA&&find_struct(sident,nesting)&&ssd->count>0) error(13,sident);
          if(!ssd||((ctok->type==LBRA||ctok->type==SEMIC)&&!find_struct(sident,nesting))){
            typ=settyp(notdone,typ);
            ssd=mymalloc(sizeof(*ssd));
            ssd->count=0;
            new->exact=ssd=add_sd(ssd,notdone);
            if(!ecpp)add_struct_identifier(sident,ssd);
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
#endif
          }else{
            new->exact=ssd;
            typ=settyp(new->flags=notdone,typ);
          }
        }else{
          *sident=0;
          typ=settyp(notdone,typ);
          ssd=mymalloc(sizeof(*ssd));
          ssd->count=0;
          new->exact=ssd=add_sd(ssd,notdone);
        }
        if(ssd->typ!=notdone) error(230,sident);
#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 */
#endif        
        if(ctok->type==LBRA){
          int bfoffset,bfsize,flex_array=0,cbfo=0;
	  int scount;
          zmax off=l2zm(0L);
          next_token();
          killsp();
          slsz=SLSIZE;
          imerk=ident;
            sl=mymalloc(slsz*sizeof(struct_list));
            ssd->count=0;
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
	  scount=ssd->count;
          ts=declaration_specifiers();
          while(ctok->type!=RBRA&&ts){
            if(flex_array) error(231);
            ident=sbuff;
            t=declarator(clone_typ(ts));
            killsp();
            bfsize=bfoffset=-1;
            if(ctok->type==T_COLON){
              np tree;
              if((ts->flags&NQ)!=INT) {
                error(51);
#ifdef HAVE_MISRA
/* removed */
#endif
              }
              next_token();killsp();tree=assignment_expression();

              if(type_expression(tree,0)){
                int tsize;
                if(tree->flags!=CEXPR) error(52);
                if(!ISINT(tree->ntyp->flags)) error(52);
                eval_const(&tree->val,tree->ntyp->flags);
                bfsize=(int)zm2l(vmax);
                tsize=(int)zm2l(zmmult(sizetab[t->flags&NQ],char_bit));
                if(bfsize<0||bfsize>tsize||(bfsize==0&&*ident)){
                  error(332);bfsize=1;
                }
                if(bfsize+cbfo>tsize){
                  bfoffset=cbfo=0;
                }else{
                  bfoffset=cbfo;
                }
                if(bfsize!=0)
                  cbfo+=bfsize;
                else
                  cbfo=0;
              }
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
#endif
              if(tree) free_expression(tree);
            }else{
              if(!ecpp&&*ident==0) error(53);
              cbfo=0;
            }
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
            if(type_uncomplete(t)){
              if(!c99||notdone!=STRUCT||flex_array||(t->flags&NQ)!=ARRAY||type_uncomplete(t->next)){
                error(14,sbuff);
                freetyp(t);
                break;
              }else{
                flex_array=1;
              }
            }
	    if(ISARRAY(t->flags)&&t->dsize){
	      error(352,sbuff);
	    }
            if(ISFUNC(t->flags)){
              if(!ecpp){
                error(15,sbuff);
              }
            }
            if(*ident!=0){
              int i=scount;
              while(--i>=0)
                if(!strcmp((*sl)[i].identifier,ident))
                  error(16,ident);
            }
#ifdef HAVE_MISRA
/* removed */
#endif
#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 */
#endif
	    (*sl)[scount].bfoffset=bfoffset;
            (*sl)[scount].bfsize=bfsize;
            (*sl)[scount].styp=t;
            if(!ecpp) (*sl)[scount].identifier=add_identifier(ident,strlen(ident));
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
#endif
            if(pack_align>0&&pack_align<falign(t))
              (*sl)[scount].align=pack_align;
            else
              (*sl)[scount].align=falign(t);
            {
              zmax m,al=(*sl)[scount].align;
              zmax sz=szof(t);
              m=off;
              if((zmeqto(al,l2zm(0L))||zmeqto(sz,l2zm(0L)))&&!flex_array){
                if (!ecpp){
                  error(316,ident);
                }
              }else{
                off=zmmult(zmdiv(zmadd(off,zmsub(al,l2zm(1L))),al),al);
                if(!zmeqto(m,off)) error(306,ident);
                if(!flex_array){
                  m=zmmult(zmdiv(zmadd(off,zmsub(sz,l2zm(1L))),sz),sz);
                  if(!zmeqto(m,off)) error(307,ident);
                  off=zmadd(off,sz);
                }
              }
            }
            scount++;
            if(scount>=slsz-1){
              slsz+=SLSIZE;
              sl=myrealloc(sl,slsz*sizeof(struct_list));
            }
            killsp();
            if(ctok->type==COMMA) {next_token();killsp();continue;}
            if(ctok->type!=SEMIC) error(54); else next_token();
            killsp();
#ifdef HAVE_ECPP
/* removed */
#endif
            if(ctok->type!=RBRA){
              if(ts) freetyp(ts);
              ts=declaration_specifiers();killsp();
            }
          }
          if(ts) freetyp(ts);
	  ssd->count=scount;
          if(ssd->count==0) error(55);
#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 */
#endif
          ident=imerk;
					add_sl(ssd,sl);
					free(sl);
          if(ctok->type!=RBRA) error(56); else next_token();
          new->flags=notdone|type_qualifiers;
        }
#ifdef HAVE_ECPP
/* removed */
#endif
        notdone=1;
      }else if(!strcmp("enum",ctok->name)){
        /*  enumerations; die Namen werden leider noch ignoriert    */
        next_token();killsp();notdone=1;
        if(ctok->type!=LBRA){cpbez(buff,1);next_token();killsp();}
        if(ctok->type==LBRA){
          /* mode: 0=start 1=first was not init 2=first was init 3=more init */
          zmax val; Var *v; type *t;int mode=0;
          val=l2zm(0L);
          next_token();killsp();
          while(ctok->type!=RBRA){
            cpbez(sident,1);next_token();killsp();
            if(*sident==0) {error(56);break;}
            t=new_typ();
            t->flags=CONST|INT;
            if(find_var(sident,nesting)) error(17,sident);
            v=add_var(sident,t,AUTO,0); /*  AUTO hier klug? */
            if(ctok->type==ASGN){
              if(mode==2) mode=3;
              if(mode==0) mode=2;
#ifdef HAVE_MISRA                                /* MISRA Rule 9.3 checking */
/* removed */
#endif
              next_token();killsp();
              v->clist=initialization(v->vtyp,0,0,0,0,0);
              val=zi2zm(v->clist->val.vint);killsp();
            }else{
              if(mode==0) mode=1;
#ifdef HAVE_MISRA                                /* MISRA Rule 9.3 checking */
/* removed */
#endif
              v->clist=mymalloc(CLS);
              v->clist->val.vint=zm2zi(val);
              v->clist->next=v->clist->other=0;
              v->clist->tree=0;
	      v->clist->idx=l2zm(0L);
            }
            vmax=l2zm(1L);val=zmadd(val,vmax);
            v->vtyp->flags=CONST|ENUM;
            if(ctok->type!=RBRA&&ctok->type!=COMMA) {error(56);break;}
            if(ctok->type==COMMA) next_token();
            killsp();
            if(ctok->type==RBRA) {next_token(); break;}
          }
        }
        killsp();
        typ=settyp(INT,typ);
      }else if(!strcmp("__readsmem",ctok->name)||!strcmp("__writesmem",ctok->name)){
        enum {READS,WRITES} op;
        char *imerk,tbuf[MAXI];
        type *tmp;
        if(!strcmp("__readsmem",ctok->name))
          op=READS;
        else
          op=WRITES;
        next_token();killsp();
        if(ctok->type==LPAR) next_token(); else error(151);
        imerk=ident;ident=tbuf;
        tmp=declarator(declaration_specifiers());
        ident=imerk;
        if(tmp){
          if(vattr)
            vattr=myrealloc(vattr,strlen(vattr)+25);
          else{
            vattr=mymalloc(25);
            vattr[0]=0;
          }
          sprintf(vattr+strlen(vattr),";%s(%d)",op==READS?"readmem":"writemem",tmp->flags);
        }
        killsp();
        if(ctok->type==RPAR) next_token(); else error(59);
        killsp();
        notdone=1;
      }else if(!strcmp("void",ctok->name)){
        next_token();
        typ=settyp(VOID,typ);notdone=1;
      }else if(!strcmp("char",ctok->name)){
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
        next_token();
        typ=settyp(CHAR,typ);
	notdone=1;
	if(default_unsigned&&!(type_qualifiers&XSIGNED))
	  type_qualifiers|=UNSIGNED;
      }else if(!strcmp("short",ctok->name)){
#ifdef HAVE_MISRA
/* removed */
#endif
        next_token();
        typ=settyp(SHORT,typ);notdone=1;
      }else if(!strcmp("int",ctok->name)){
#ifdef HAVE_MISRA
/* removed */
#endif
        next_token();
        typ=settyp(INT,typ);notdone=1;
      }else if(!strcmp("long",ctok->name)){
#ifdef HAVE_MISRA
/* removed */
#endif
        next_token();
        typ=settyp(LONG,typ);notdone=1;
      }else if(!strcmp("float",ctok->name)){
#ifdef HAVE_MISRA
/* removed */
#endif
        next_token();
        typ=settyp(FLOAT,typ);notdone=1;
      }else if(!strcmp("double",ctok->name)){
#ifdef HAVE_MISRA
/* removed */
#endif
        next_token();
        typ=settyp(DOUBLE,typ);notdone=1;
      }else if(!strcmp("const",ctok->name)){
        next_token();
        if(type_qualifiers&CONST) error(58);
        type_qualifiers|=CONST;notdone=1;
      }else if(!strcmp("volatile",ctok->name)){
        next_token();
        if(type_qualifiers&VOLATILE) error(58);
        type_qualifiers|=VOLATILE;notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"bool"))){
	next_token();
	typ=settyp(VECBOOL+dim-1,typ);
	notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"char"))){
	next_token();
	typ=settyp(VECCHAR+dim-1,typ);
	notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"uchar"))){
	next_token();
	typ=settyp((VECCHAR+dim-1)|UNSIGNED,typ);
	notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"short"))){
	next_token();
	typ=settyp(VECSHORT+dim-1,typ);
	notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"ushort"))){
	next_token();
	typ=settyp((VECSHORT+dim-1)|UNSIGNED,typ);
	notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"int"))){
	next_token();
	typ=settyp(VECINT+dim-1,typ);
	notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"uint"))){
	next_token();
	typ=settyp((VECINT+dim-1)|UNSIGNED,typ);
	notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"long"))){
	next_token();
	typ=settyp(VECLONG+dim-1,typ);
	notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"ulong"))){
	next_token();
	typ=settyp((VECLONG+dim-1)|UNSIGNED,typ);
	notdone=1;
      }else if(opencl&&(dim=check_vect(ctok->name,"float"))){
	next_token();
	typ=settyp(VECFLOAT+dim-1,typ);
	notdone=1;
#if 0
      }else if(c99&&!strcmp("restrict",ctok->name)){
        next_token();
        if(type_qualifiers&RESTRICT) error(58);
        type_qualifiers|=RESTRICT;notdone=1;
#endif
      }else if(!strcmp("unsigned",ctok->name)){
        next_token();
        if(type_qualifiers&(XSIGNED|UNSIGNED)) error(58);
        notdone=1;type_qualifiers|=UNSIGNED;
      }else if(!strcmp("signed",ctok->name)){
        next_token();
        if(type_qualifiers&(XSIGNED|UNSIGNED)) error(58);
        notdone=1;type_qualifiers|=XSIGNED;
      }else if(!strcmp("auto",ctok->name)){
        next_token();
        dsc;storage_class=AUTO;notdone=1;
      }else if(!strcmp("register",ctok->name)){
#ifdef HAVE_MISRA
/* removed */
#endif
        next_token();
        dsc;storage_class=REGISTER;notdone=1;
      }else if(!strcmp("static",ctok->name)){
        next_token();
        dsc;storage_class=STATIC;notdone=1;
#ifdef HAVE_ECPP
/* removed */
#endif
      }else if(!strcmp("extern",ctok->name)){
        next_token();
        dsc;storage_class=EXTERN;notdone=1;
      }else if(!strcmp("typedef",ctok->name)){
        next_token();
        dsc;storage_class=TYPEDEF;notdone=1;
      }else if(c99&&!strcmp("inline",ctok->name)){
        next_token();
        have_inline=1;notdone=1;
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
			}else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__reg",ctok->name)){
        char *d;
        next_token();killsp(); 
        if(ctok->type==LPAR) next_token(); else error(151);
        killsp();
        if(d=get_string()){
          for(hard_reg=1;hard_reg<=MAXR;hard_reg++){
            if(!strcmp(d,regnames[hard_reg])) break;
          }
          if(hard_reg>MAXR){ hard_reg=0;error(220,d);}
          notdone=1;
          free(d);
        }
        killsp();
        if(ctok->type==RPAR) next_token(); else error(59);
        killsp();
      }else if(!strcmp("__mask",ctok->name)){
	np tree;
	next_token();killsp();
        if(ctok->type==LPAR) next_token(); else error(151);
	tree=expression();
	if(tree&&type_expression(tree,0)){
	  if(tree->flags==CEXPR&&ISINT(tree->ntyp->flags)){
	    eval_const(&tree->val,tree->ntyp->flags);
	    mask=vumax;
	  }else
	    error(18);
	  free_expression(tree);
	}else
	  error(18);
        killsp();
        if(ctok->type==RPAR) next_token(); else error(59);
        killsp();
	notdone=1;
      }else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__attr",ctok->name)){
        char *d;
        next_token();killsp(); 
        if(ctok->type==LPAR) next_token(); else error(151);
        killsp();
        if(d=get_string()){
          if(!attr){
            attr=d;
          }else{
            attr=myrealloc(attr,strlen(attr)+strlen(d)+2);
            strcat(attr,";");
            strcat(attr,d);
            free(d);
          }
          notdone=1;
        }
        killsp();
        if(ctok->type==RPAR) next_token(); else error(59);
        killsp();
      }else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__vattr",ctok->name)){
        char *d;
        next_token();killsp();
        if(ctok->type==LPAR) next_token(); else error(151);
        killsp();
        if(d=get_string()){
          if(!vattr){
            vattr=d;
          }else{
            vattr=myrealloc(vattr,strlen(vattr)+strlen(d)+2);
            strcat(vattr,";");
            strcat(vattr,d);
            free(d);
          }
          notdone=1;
        }
        killsp();
        if(ctok->type==RPAR) next_token(); else error(59);
        killsp();
      }else{
#ifdef HAVE_TARGET_ATTRIBUTES
        int i;
        for(i=0;g_attr_name[i];i++){
          if(!strcmp(g_attr_name[i],ctok->name)){
            if(tattr&(1L<<i)) error(227,ctok->name);
            tattr|=(1L<<i);
            next_token();
            notdone=1;break;
          }
        }
#endif
        if(!notdone&&typ==0&&!(type_qualifiers&(XSIGNED|UNSIGNED))){
          v=find_var(ctok->name,0);
          if(v&&v->storage_class==TYPEDEF){
            free(new);
            new=clone_typ(v->vtyp);
            typ=settyp(new->flags,typ);
            notdone=1;
            next_token();
          }
#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 */
#endif
        }
      }
    }
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
    if(DEBUG&2) printf("typ:%d\n",typ);
  }while(notdone);
  killsp();
  return_sc=storage_class;
  return_reg=hard_reg;
  return_vattr=vattr;
  return_mask=mask;
  return_inline=have_inline;
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
#endif
#ifdef HAVE_TARGET_ATTRIBUTES
  return_tattr=tattr;
#endif
  if(typ==0){
    if(storage_class==0&&type_qualifiers==0&&!hard_reg){
      free(new);
      return 0;
    }
#ifdef HAVE_MISRA
/* removed */
#endif
    typ=INT;
  }
  if(type_qualifiers&(XSIGNED|UNSIGNED))
    if(!ISINT(typ))
      error(58);
  new->flags=typ|type_qualifiers;
  new->attr=attr;
  return new;
}

type *declarator(type *a)
/* Erzeugt einen neuen Typ, auf Basis des Typs a.           */
/* a wird hiermit verkettet.                                */
{
  type *t;
  killsp();*ident=0;
  t=direct_declarator(pointer(a));
  if(!a)
    {if(t) freetyp(t);return 0;}
#ifdef HAVE_ECPP
/* removed */
#endif
#ifdef HAVE_EXT_TYPES
  conv_typ(t);
#endif  
  return t;
}
type *pointer(type *a)
/* Unterroutine fuer declarator(), behandelt Zeiger auf Typ.   */
{
  type *t;char *attr;int notdone;
  if(!a) return(0);
  killsp();
  while(ctok->type==STAR){
    next_token();
    t=new_typ();
    t->flags=POINTER_TYPE(a);
    t->next=a;
    attr=0;
    a=t;
    do{
      killsp();
      notdone=0;
      if(ctok->type==NAME&&!strcmp("const",ctok->name)){
	a->flags|=CONST;
	notdone=1;
	next_token();
      }else if(ctok->type==NAME&&!strcmp("volatile",ctok->name)){
	a->flags|=VOLATILE;
	notdone=1;
	next_token();
      }else if(c99&&ctok->type==NAME&&!strcmp("restrict",ctok->name)){
	a->flags|=RESTRICT;
	notdone=1;
	next_token();
      }else if(ctok->type==NAME&&!strcmp("__attr",ctok->name)){
	char *d;
	next_token();
	killsp();
	if(ctok->type==LPAR) next_token(); else error(151);
	killsp();
	if(d=get_string()){
	  if(!attr){
	    attr=d;
	  }else{
	    attr=myrealloc(attr,strlen(attr)+strlen(d)+2);
	    strcat(attr,";");
	    strcat(attr,d);
	    free(d);
	  }
	  notdone=1;
	}
	killsp();
	if(ctok->type==RPAR) next_token(); else error(59);
	killsp();
      }
    }while(notdone);
    a->attr=attr;
  }
  return a;
}
type *direct_declarator(type *a)
/*  Unterroutine zu declarator()                    */
/*  behandelt [],(funkt),(dekl).                     */
{
  type *rek=0,*merk,*p,*t=0,*first,*last=0;
  struct_declaration *fsd;
  struct_list (*sl)[];
  size_t slsz;char *imerk;
  char fbuff[MAXI];
  killsp();
  if(ctok->type!=NAME&&ctok->type!=LPAR&&ctok->type!=LBRK)
    return a;
  if(ctok->type==NAME){
    cpbez(ident,1);
    next_token();
    if(!a) return(0);
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
  }
  else if(ctok->type==LPAR&&a){
    /* Rekursion */
    token mtok;
    copy_token(&mtok,ctok);
    next_token(); killsp();
    if(ctok->type!=RPAR&&*ident==0&&!declaration(0)){
      merk=a;
      rek=declarator(a);
      if(ctok->type!=RPAR) error(59); else next_token();
    }else

      push_token(&mtok);
    free(mtok.name);
  }
  if(!a)return(0);
  killsp();
  while(ctok->type==LBRK||ctok->type==LPAR){
    if(ctok->type==LBRK){
      next_token();
      killsp();
      p=new_typ();
      p->flags=ARRAY;
      p->next=0;
      if(ctok->type==RBRK){
        p->size=l2zm(0L);
      }else{
        np tree;
        tree=expression();
        if(!type_expression(tree,0)){
          /*                    error("incorrect constant expression");*/
        }else{
          if(tree->sidefx&&!c99) error(60);
          if(tree->flags!=CEXPR||!ISINT(tree->ntyp->flags)){
	    if(!c99||!ALLOCVLA_INLINEASM)
	      error(19);
	    else{
	      type *st;IC *new;
	      st=new_typ();
	      st->flags=HAVE_INT_SIZET?(UNSIGNED|INT):(UNSIGNED|LONG);
	      p->dsize=add_tmp_var(st);
	      gen_IC(tree,0,0);
	      convert(tree,st->flags);
	      new=new_IC();
	      new->code=ASSIGN;
	      new->typf=st->flags;
	      new->q1=tree->o;
	      new->z.flags=VAR;
	      new->z.v=p->dsize;
	      new->z.val.vmax=l2zm(0L);
	      new->q2.val.vmax=szof(st);
	      add_IC(new);
	    }
          }else{
            eval_constn(tree);
            p->size=vmax;
            if(zmleq(p->size,l2zm(0L))) {error(61);p->size=l2zm(1L);}
          }
        }
        free_expression(tree);
      }
      if(ctok->type!=RBRK) error(62); else next_token();
      if(last){
        last->next=p;
        last=p;
      }else{
        first=last=p;
      }
    }
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
#endif
    if(ctok->type==LPAR){
      int komma,firstparm,oldstyle=0;
#if 0 /*#ifdef HAVE_REGPARMS*/
      treg_handle reg_handle=empty_reg_handle;
      type rpointer={0};
      if(!ffreturn(a)&&(a->flags&NQ)!=VOID){
	rpointer.flags=POINTER_TYPE(a);
        rpointer.next=a;
        reg_parm(&reg_handle,&rpointer,0,a); /*TODO: a might be incomplete */
      }
#endif
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
      next_token();
      killsp();
#ifdef HAVE_MISRA
/* removed */
#endif
      fsd=mymalloc(sizeof(*fsd));
      slsz=SLSIZE;
      sl=mymalloc(sizeof(struct_list)*slsz);
      fsd->count=0;
      imerk=ident;komma=0;
      enter_block();
      firstparm=1;
      while(ctok->type!=RPAR&&ctok->type!=MDOTS){
        int hard_reg;
#ifdef HAVE_ECPP
/* removed */
#endif
	if(!firstparm&&!komma) error(57);
	komma=firstparm=0;
        ident=fbuff;*fbuff=0;
        t=declaration_specifiers();
        hard_reg=return_reg;
        t=declarator(t);
        if(!t){
          oldstyle=1;
          if(*ident==0) {error(20);freetyp(t);continue;}
        }
        if(fsd->count){
          if((t&&!(*sl)[fsd->count-1].styp)||
             (!t&&(*sl)[fsd->count-1].styp))
            error(63);
        }
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
        if(!return_sc) return_sc=AUTO;
        if(return_sc!=AUTO&&return_sc!=REGISTER)
          {error(21);return_sc=AUTO;}
        (*sl)[fsd->count].styp=t;
        (*sl)[fsd->count].storage_class=return_sc;
	{
	  int m=nesting;
	  nesting=0;
	  (*sl)[fsd->count].identifier=add_identifier(ident,strlen(ident));
	  nesting=m;
	}
        if(t){
          if(((*sl)[fsd->count].styp->flags&NQ)==VOID&&fsd->count!=0)
            error(22);
          /*  Arrays in Zeiger umwandeln  */
          if(ISARRAY((*sl)[fsd->count].styp->flags))
            (*sl)[fsd->count].styp->flags=POINTER_TYPE((*sl)[fsd->count].styp->next);
	  /*  Funktionen in Zeiger auf Funktionen umwandeln   */
	  if(ISFUNC((*sl)[fsd->count].styp->flags)){
	    type *new;
	    new=new_typ();
	    new->next=(*sl)[fsd->count].styp;
	    new->flags=POINTER_TYPE(new->next);
	    (*sl)[fsd->count].styp=new;
	  }
	}
        if(hard_reg&&regok(hard_reg,t->flags,-1)<=0) error(217,regnames[hard_reg]);
#if 0 /*#ifdef HAVE_REGPARMS*/
        if(t) (*sl)[fsd->count].reg=reg_parm(&reg_handle,t,0,a); /*TODO: a might be incomplete */
        if(hard_reg) (*sl)[fsd->count].reg=hard_reg;
#else
        (*sl)[fsd->count].reg=hard_reg;
#endif
        fsd->count++;
        if(fsd->count>=slsz-2){     /*  eins Reserve fuer VOID  */
          slsz+=SLSIZE;
          sl=myrealloc(sl,slsz*sizeof(struct_list));
        }
        killsp(); /* Hier Syntaxpruefung strenger machen */
        if(ctok->type==COMMA) {next_token();komma=1; killsp();}
      }
      ident=imerk;
#ifdef HAVE_MISRA
/* removed */
#endif
      if(ctok->type!=MDOTS||!komma){
        int ecpp_addvoid=0;
#ifdef HAVE_ECPP
/* removed */
#endif
        if(ecpp_addvoid||(!ecpp&&fsd->count>0&&(!(*sl)[fsd->count-1].styp||((*sl)[fsd->count-1].styp->flags&NQ)!=VOID))){
          (*sl)[fsd->count].styp=new_typ();
          (*sl)[fsd->count].styp->flags=VOID;
          (*sl)[fsd->count].styp->next=0;
          (*sl)[fsd->count].reg=0;
          (*sl)[fsd->count].identifier=empty;
#ifdef HAVE_ECPP
/* removed */
#endif
          fsd->count++;
        }
        if(ecpp&&ctok->type==MDOTS){next_token();killsp();}
      }else if(komma){
        next_token();komma=0;
        if(oldstyle) error(221);
      }
      p=new_typ();
      p->flags=FUNKT;
      {
        int m=nesting;
        nesting=0;
        p->exact=add_sd(fsd,FUNKT);
        add_sl(fsd,sl);
        free(sl);
        nesting=m;
      }
#ifdef HAVE_REGPARMS
      {
	treg_handle reg_handle=empty_reg_handle;
	int i,r;

	p->next=a;

	if(!ffreturn(a)&&(a->flags&NQ)!=VOID){
	  type rpointer={0};

	  rpointer.flags=POINTER_TYPE(a);
	  rpointer.next=a;
	  reg_parm(&reg_handle,&rpointer,0,p);
	}

	for(i=0;i<p->exact->count;i++){
	  if((*p->exact->sl)[i].styp)
	    r=reg_parm(&reg_handle,(*p->exact->sl)[i].styp,0,p);
	  else
	    r=0;
	  if((*p->exact->sl)[i].reg==0) (*p->exact->sl)[i].reg=r;
	}
      }
#endif
      killsp();
      if(komma) error(59);
      if(ctok->type!=RPAR) error(59); else next_token();
      killsp();
      if(ctok->type==COMMA||ctok->type==SEMIC||ctok->type==RPAR||ctok->type==ASGN)
	leave_block();
      if(last){
        last->next=p;
        last=p;
      }else{
        first=last=p;
      }
    }
    killsp();
  }
  if(last){last->next=a;last=a;a=first;}
  if(rek!=0&&rek!=merk){
    /* Zweite Liste anhaengen */
    p=rek;
    while(p->next!=merk) p=p->next;
    if(p) p->next=a; else ierror(0);
    return rek;
  }
  return a;
}
int declaration(int offset)
/*  Testet, ob eine Typangabe kommt. Wenn offset!=0 ist,    */
/*  muss s auf '(' zeigen und es wird getestet, ob nach der */
/*  Klammer eine Typangabe kommt.                           */
/*  In jedem Fall zeigt s danach wieder auf dieselbe Stelle */
/*  im Source.                                              */
{
  Var *v;token mtok;
  int fl=0;
  if(offset){
    copy_token(&mtok,ctok);
    next_token();
    killsp();
  }
  if(ctok->type==NAME){
    if(!strcmp("auto",ctok->name)) fl=1;
    else if(!strcmp("char",ctok->name)) fl=1;
    else if(!strcmp("const",ctok->name)) fl=1;
    else if(!strcmp("double",ctok->name)) fl=1;
    else if(!strcmp("enum",ctok->name)) fl=1;
    else if(!strcmp("extern",ctok->name)) fl=1;
    else if(!strcmp("float",ctok->name)) fl=1;
    else if(!strcmp("int",ctok->name)) fl=1;
    else if(!strcmp("long",ctok->name)) fl=1;
    else if(!strcmp("register",ctok->name)) fl=1;
    else if(c99&&!strcmp("restrict",ctok->name)) fl=1;
    else if(!strcmp("short",ctok->name)) fl=1;
    else if(!strcmp("signed",ctok->name)) fl=1;
    else if(!strcmp("static",ctok->name)) fl=1;
    else if(!strcmp("struct",ctok->name)) fl=1;
    else if(!strcmp("typedef",ctok->name)) fl=1;
    else if(!strcmp("union",ctok->name)) fl=1;
    else if(!strcmp("unsigned",ctok->name)) fl=1;
    else if(!strcmp("void",ctok->name)) fl=1;
    else if(!strcmp("volatile",ctok->name)) fl=1;
    else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__reg",ctok->name)) fl=1;
    else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__attr",ctok->name)) fl=1;
    else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__vattr",ctok->name)) fl=1;
    else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__mask",ctok->name)) fl=1;
    else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__readsmem",ctok->name)) fl=1;
    else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__writesmem",ctok->name)) fl=1;
    else{
      v=find_var(ctok->name,0);
      if(v&&v->storage_class==TYPEDEF) fl=1;
    }
  }
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
  if(offset){
    push_token(&mtok);
    free(mtok.name);
  }
  return fl;
}
void init_sl(struct_list *sl){
  if(!sl){ierror(0);return;}
  sl->identifier=0;
  sl->styp=0;
  sl->align=0;
  sl->bfoffset=-1;
  sl->bfsize=-1;
  sl->reg=0;
  sl->storage_class=0;
#ifdef HAVE_ECPP
/* removed */
#endif
}
void add_sl(struct_declaration *sd,struct_list (*sl)[])
/*  Fuegt ein struct_list-Array in eine struct_declaration ein.     */
/*  Das Array muss mind. sd->count Elements haben und wird kopiert. */
{
  size_t sz=sizeof(struct_list)*sd->count;
  sd->sl=mymalloc(sz);
  memcpy(sd->sl,sl,sz);
}
struct_declaration *add_sd(struct_declaration *new,int typ)
/*  Fuegt eine Declaration in Liste ein.     */
{
  new->next=0;
  new->label=0;
  new->typ=typ;
  new->identifier=0;
  new->tunit=last_tunit;
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
  if(first_sd[nesting]==0){
    first_sd[nesting]=last_sd[nesting]=new;
  }else{
    last_sd[nesting]->next=new;
    last_sd[nesting]=new;
  }
  return new;
}
void free_sd(struct_declaration *p)
/*  Gibt eine struct_declaration-List inkl. struct_lists und    */
/*  allen Typen jeder struct_list frei, nicht aber identifier.  */
{
  int i;struct_declaration *merk;
  while(p){
    merk=p->next;
    if(p->sl){
      for(i=0;i<p->count;i++){
	if((*p->sl)[i].styp) freetyp((*p->sl)[i].styp);
      }
      if(p->count>0) free(p->sl);
    }
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
#endif
    free(p);
    p=merk;
  }
}
char *add_identifier(char *identifier,int length)
/*  Kopiert identifier an sicheren Ort, der spaeter zentral     */
/*  freigegeben werden kann.                                    */
/*  Sollte noch einbauen, dass ueberprueft wird, ob schon       */
/*  vorhanden und dann nicht zweimal speichern.                 */
{
  identifier_list *new;
  if((*identifier==0&&length==0)||identifier==empty) return(empty);
  new=mymalloc(sizeof(identifier_list));
  new->identifier=mymalloc(length+1);
  memcpy(new->identifier,identifier,length+1);
  new->next=0;new->length=length;
  if(last_ilist[nesting]){
    last_ilist[nesting]->next=new;
    last_ilist[nesting]=new;
  }else{
    last_ilist[nesting]=first_ilist[nesting]=new;
  }
  return(new->identifier);
}
void free_ilist(identifier_list *p)
/*  Gibt eine verkettete identifier_liste und saemtliche darin  */
/*  gespeicherten Identifier frei.                              */
{
  identifier_list *merk;
  while(p){
    merk=p->next;
    if(p->identifier) free(p->identifier);
    free(p);
    p=merk;
  }
}
int type_uncomplete(type *p)
/*  Testet, ob Typ unvollstaendig ist. Momentan gelten nur      */
/*  unvollstaendige Strukturen und Arrays von solchen als       */
/*  unvollstaendig, aber keine Zeiger oder Funktionen darauf.   */
{
  struct_declaration *sd;
  if(!p){ierror(0);return(0);}
  if(ISSTRUCT(p->flags)||ISUNION(p->flags))
    if(p->exact->count<=0) return 1;
  if(ISARRAY(p->flags)){
    if(!p->dsize&&zmleq(p->size,l2zm(0L))) return 1;
if(!p->next) ierror(0);
    if(type_uncomplete(p->next)) return 1;
  }
  return 0;
}
void add_struct_identifier(char *identifier,struct_declaration *sd)
/*  Erzeugt neuen struct_identifier, fuegt ihn in Liste an und  */
/*  vervollstaendigt unvollstaendige Typen dieser Struktur.     */
{
  struct_identifier *new;
/*    type *t;*/
  if(DEBUG&1) printf("add_si %s (nesting=%d)->%p\n",identifier,nesting,(void *)sd);
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
  new=mymalloc(sizeof(struct_identifier));
  new->identifier=add_identifier(identifier,strlen(identifier));
  new->sd=sd;
  new->next=0; 
  if(first_si[nesting]==0){
    first_si[nesting]=new;last_si[nesting]=new;
  }else{
    last_si[nesting]->next=new;last_si[nesting]=new;
  }
  sd->identifier=new->identifier;
}
void free_si(struct_identifier *p)
/*  Gibt eine struct_identifier-Liste frei, aber nicht die      */
/*  identifiers und struct_declarations.                        */
{
  struct_identifier *merk;
  while(p){
    merk=p->next;
    p->sd->identifier="<prototype-only>";
    free(p);
    p=merk;
  }
}
struct_declaration *find_struct(char *identifier,int endnesting)

/*  Sucht angegebene Strukturdefinition und liefert             */
/*  entsprechende struct_declaration.                           */
{
  struct_identifier *si; int i,l;
  if(misracheck) l=strlen(identifier);
  for(i=nesting;i>=endnesting;i--){
    si=first_si[i];
    while(si){
      if(!strcmp(si->identifier,identifier)){
        if(DEBUG&1) printf("found tag <%s> at nesting %d->%p\n",identifier,i,(void *)si->sd);
        return(si->sd);
      }
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
#endif
	si=si->next;
	}
  }
  if(DEBUG&1) printf("didn't find tag <%s>\n",identifier);
  return(0);
}

/* generate code to create a variable-lenght-array */
static void create_allocvl(Var *v)
{
  np tree,ds;
  IC *new;Var *fv;

  /* check if we got a frame-pointer */
  if(FPVLA_REG&&!regsa[FPVLA_REG]){
    if(regused[FPVLA_REG])
      ierror(0);
    else
      regsa[FPVLA_REG]=regscratch[FPVLA_REG]=regused[FPVLA_REG]=1;
  }

  /* if this is the first vla in this block, save old sp */
  if(!block_vla[nesting]){
    /* declare function - may be done by the backend, if necessary */
    if(!(fv=find_ext_var("__oldvlasp"))){
      type *t;
      static type voidt={VOID};
      struct_declaration *sd=mymalloc(sizeof(*sd));
      t=new_typ();
      t->flags=FUNKT;

      t->next=new_typ();
      t->next->flags=POINTER_TYPE(&voidt);
      t->next->next=clone_typ(&voidt);
      sd->count=0;
      t->exact=add_sd(sd,FUNKT);
      fv=add_var("__oldvlasp",t,EXTERN,0);
      fv->fi=new_fi();
      fv->fi->flags|=(ALL_USES|ALL_MODS);
      fv->fi->inline_asm=mystrdup(OLDSPVLA_INLINEASM);
    } 
    block_vla[nesting]=add_tmp_var(clone_typ(fv->vtyp->next));
    tree=gen_libcall("__oldvlasp",0,0,0,0);
    new=new_IC();
    new->code=ASSIGN;
    new->z.flags=VAR;
    new->z.v=block_vla[nesting];
    new->z.val.vmax=l2zm(0L);
    new->q1=tree->o;
    new->q2.flags=0;
    new->typf=block_vla[nesting]->vtyp->flags;
    new->q2.val.vmax=sizetab[new->typf];
    add_IC(new);
    free_expression(tree);
  }

  /* make room on the stack */
  ds=new_node();
  ds->flags=IDENTIFIER;
  ds->identifier=empty;
  ds->dsize=vlength_szof(v->vtyp);
  ds->val.vmax=l2zm(0L);
  ds->ntyp=clone_typ(ds->dsize->vtyp);
  ds->o.flags=VAR;
  ds->o.v=ds->dsize;
  ds->o.val.vmax=l2zm(0L);
  ds->left=ds->right=0;

  if(!find_ext_var("__allocvla")){
    /* declare function */
    struct_declaration *sd=mymalloc(sizeof(*sd));
    type *t=new_typ();
    sd->count=1;
    sd->sl=mymalloc(sizeof(struct_list));
    (*sd->sl)[0].storage_class=AUTO;
    (*sd->sl)[0].styp=clone_typ(ds->dsize->vtyp);
    (*sd->sl)[0].reg=ALLOCVLA_REG;
    t->flags=FUNKT;
    t->exact=add_sd(sd,FUNKT);
    t->next=new_typ();
    t->next->flags=POINTER_TYPE(v->vtyp);
    t->next->next=new_typ();
    t->next->next->flags=v->vtyp->flags;
    fv=add_var("__allocvla",t,EXTERN,0);
    fv->fi=new_fi();
    fv->fi->flags|=(ALL_USES|ALL_MODS);
    fv->fi->inline_asm=mystrdup(ALLOCVLA_INLINEASM);
  }

  if(!type_expression(ds,0)) ierror(0);
  tree=gen_libcall("__allocvla",ds,0,0,0);
  new=new_IC();
  new->code=ASSIGN;
  new->z.flags=VAR;
  new->z.v=v;
  new->z.val.vmax=l2zm(0L);
  new->q1=tree->o;
  new->q2.flags=0;
  new->typf=POINTER_TYPE(v->vtyp);
  new->q2.val.vmax=sizetab[new->typf];
  add_IC(new);
  free_expression(tree);
  vlas=1;
}

/* reset sp to remove variable-length-arrays */
void freevl(void)
{
  np tree,ds;
  Var *fv;
  dontdelete=1; /* never remove them, otherwise, fix_vla_jump get confused */
  if(!find_ext_var("__resetvlasp")){
    struct_declaration *sd=mymalloc(sizeof(*sd));
    type *t=new_typ();
    sd->count=1;
    sd->sl=mymalloc(sizeof(struct_list));
    (*sd->sl)[0].storage_class=AUTO;
    (*sd->sl)[0].styp=clone_typ(block_vla[nesting]->vtyp);
    (*sd->sl)[0].reg=FREEVLA_REG;
    t->flags=FUNKT;
    t->exact=add_sd(sd,FUNKT);
    t->next=new_typ();
    t->next->flags=VOID;
    fv=add_var("__resetvlasp",t,EXTERN,0);
    fv->fi=new_fi();
    fv->fi->flags|=(ALL_USES|ALL_MODS);
    fv->fi->inline_asm=mystrdup(FREEVLA_INLINEASM);
  }
  if(nesting==1){
    clear_main_ret();
    gen_label(return_label);
    did_return_label=1;
  }
  ds=new_node();
  ds->flags=IDENTIFIER;
  ds->identifier=empty;
  ds->dsize=block_vla[nesting];
  ds->val.vmax=l2zm(0L);
  ds->ntyp=clone_typ(ds->dsize->vtyp);
  ds->left=ds->right=0;
  ds->o.flags=VAR;
  ds->o.v=ds->dsize;
  ds->o.val.vmax=l2zm(0L);
  if(!type_expression(ds,0)) ierror(0);
  tree=gen_libcall("__resetvlasp",ds,0,0,0);
  free_expression(tree);
  dontdelete=0;
}  

void clearvl(void)
{
  llist *p,*n;
  vlaadjust_list *vl,*vn;
  /* look for stack-adjusts that have to be removed */
  vl=vlaadjusts[nesting];
  while(vl){
    int ln;
    IC *ic=vl->branch;
    if(ic){
      ln=ic->typf;
      if(ic->code!=BRA) ierror(0);
      p=vladeflabels[nesting];
      while(p){
	if(p->label==ln) break;
	p=p->next;
      }
      if(!p){
	ic=ic->prev;
	while(ic!=vl->first->prev){
	  if(!ic) ierror(0);
	  ic->code=NOP;
	  ic->q1.flags=ic->q2.flags=ic->z.flags=0;
	  ic=ic->prev;
	}
      }
    }
    vn=vl->next;
    free(vl);
    vl=vn;
  }
  freevl();
  block_vla[nesting]=0;
  p=vladeflabels[nesting];
  while(p){
    n=p->next;
    free(p);
    p=n;
  }
  p=vlajmplabels[nesting];
  while(p){
    n=p->next;
    free(p);
    p=n;
  }
  vladeflabels[nesting]=vlajmplabels[nesting]=0;
  vlaadjusts[nesting]=0;
}

/* Handle a stack of stored sp variables when traversing an IC list; */
void vla_nesting(IC *p,Var **vn,int *nest)
{
  if(p->code==CALL&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p->q1.v->identifier,"__oldvlasp")){
    IC *p2=p->next;
    while(p2&&(p2->code==ALLOCREG||p2->code==FREEREG)) p2=p2->next;
    if(!p2||p2->code!=GETRETURN||(p2->z.flags&(VAR|DREFOBJ))!=VAR) ierror(0);
    /*printf("found save sp to %p\n",p2->z.v);*/
    vn[*nest]=p2->z.v;
    (*nest)++;
    vn[*nest]=0;
    if(*nest>=MAXN) ierror(0);
    return;
  }
  if(p->code==CALL&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p->q1.v->identifier,"__resetvlasp")){ 
    /*printf("found reset\n");*/
    if(*nest<=0) ierror(0);
    (*nest)--;
    return;
  }
}

static int return_vla_nest;
static Var *return_last_vlasp;

/* Find the stack pointer that is needed when jumping to label lab */
Var *vla_find_sp(int lab)
{
  IC *p;int nest=0;
  static Var *vn[MAXN];
  for(p=first_ic;p;p=p->next){
    if(p->code==LABEL&&p->typf==lab){
      return_vla_nest=nest;
      return_last_vlasp=vn[nest];
      if(nest<=0)
	return 0;
      else
	return vn[nest-1];
    }
    vla_nesting(p,vn,&nest);
  }
  ierror(0);
}

void vla_jump_fix(void)
{
  IC *p;int nest=0;
  static Var *vn[MAXN],*savedsp;
  if(DEBUG&1) printf("searching for vla-jump-fixes\n");
  for(p=first_ic;p;p=p->next){
    /*pric2(stdout,p);*/
    if(p->code>=BEQ&&p->code<=BRA){
      /*printf("jump found\n");*/
      p->savedsp=0;
      if(1/*nest>0*/){
	/*printf("is in vla context!\n");*/
	savedsp=vla_find_sp(p->typf);
	if(return_vla_nest>nest||(nest>0&&return_vla_nest==nest&&savedsp!=vn[nest-1])){
	  err_ic=p;
	  error(351);
	}else if(nest==0||savedsp==vn[nest-1]){
	  /*printf("jump within the same context\n");*/
	}else{
	  if(vn[nest]){
	    if(DEBUG&1) printf("have to set sp to %p\n",return_last_vlasp);
	    p->savedsp=return_last_vlasp;
	  }else{
	    int ndiff=nest-return_vla_nest-1;
	    IC *p2;
	    /*printf("have to search oldsp ndiff=%d\n",ndiff);*/
	    for(p2=p->prev;p2;p2=p2->prev){
	      if(p2->code==CALL&&(p2->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p2->q1.v->identifier,"__oldvlasp")){
		if(ndiff==0){
		  /*printf("found savesp\n");*/
		  p2=p2->next;
		  while(p2&&(p2->code==ALLOCREG||p2->code==FREEREG)) p2=p2->next;
		  if(!p2||p2->code!=GETRETURN) ierror(0);
		  if((p2->z.flags&(VAR|DREFOBJ))!=VAR) ierror(0);
		  /*printf("found oldsp %p\n",p2->z.v);*/
		  p->savedsp=p2->z.v;
		  break;
		}
		ndiff--;
	      }
	      if(p2->code==CALL&&(p2->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p2->q1.v->identifier,"__resetvlasp")){
		ndiff++;
	      }
	    }
	    if(!p2) ierror(0);
	  }
	}
      }else{
	/*printf("not in vla context\n");*/
      }
    }
    vla_nesting(p,vn,&nest);
  }
  for(p=first_ic;p;p=p->next){
    if(p->code>=BEQ&&p->code<=BRA){  
      if(p->savedsp){
	IC *merkfic,*merklic,*newcode,*m,*new,*setr=0;
	np ds,tree;
	if(DEBUG&1) printf("generating sp-adjust\n");
        merkfic=first_ic;merklic=last_ic;
	first_ic=0;last_ic=0;
	ds=new_node();
	ds->flags=IDENTIFIER;
	ds->identifier=empty;
	ds->dsize=p->savedsp;
	ds->val.vmax=l2zm(0L);
	ds->ntyp=clone_typ(ds->dsize->vtyp);
	ds->left=ds->right=0;
	ds->o.flags=VAR;
	ds->o.v=ds->dsize;
	ds->o.val.vmax=l2zm(0L);
	if(!type_expression(ds,0)) ierror(0);
	tree=gen_libcall("__resetvlasp",ds,0,0,0);
	free_expression(tree);
	newcode=first_ic;
	first_ic=merkfic;last_ic=merklic;
	if(p->code==BRA){
	  /* check if the branch was preceded by a SETRETURN */
	  IC *p2=p->prev;
	  while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG))
	    p2=p2->prev;
	  if(p2->code==SETRETURN&&p2->z.reg)
	    setr=p2;
	}else{
	  new=new_IC();
	  new->typf=++label;
	  if(p->code==BEQ) new->code=BRA;
	  else if(p->code==BNE) new->code=BEQ;
	  else if(p->code==BLT) new->code=BGE;
	  else if(p->code==BGT) new->code=BLE;
	  else if(p->code==BLE) new->code=BGT;
	  else if(p->code==BGE) new->code=BLT;
	  insert_IC(p->prev,new);
	}
	while(newcode){
	  m=newcode->next;
	  insert_IC(p->prev,newcode);
	  newcode=m;
	}
	if(p->code!=BRA){
	  p->code=BRA;
	  new=new_IC();
	  new->code=LABEL;
	  new->typf=label;
	  insert_IC(p,new);
	}
	if(setr){
	  /* save the return value to save it from being overwritten */
	  /* could be optimized further */
	  Var *v;
	  if(ISSCALAR(setr->typf)){
	    static type t={0};
	    t.flags=setr->typf;
	    v=add_tmp_var(clone_typ(&t));
	  }else ierror(0);
	  new=new_IC();
	  *new=*setr;
	  new->q1.flags=VAR;
	  new->q1.v=v;
	  new->q1.val.vmax=l2zm(0L);
	  setr->z=new->q1;
	  setr->code=ASSIGN;
	  insert_IC(p->prev,new);
	}
      }
    }
  }
}  
  

Var *add_tmp_var(type *t)
{
  t->flags&=NU;
  return add_var(empty,t,AUTO,0);
}
Var *add_var(char *identifier, type *t, int storage_class,const_list *clist)
/*  Fuegt eine Variable mit Typ in die var_list ein.            */
/*  In der storage_class werden die Flags PARAMETER und evtl.   */
/*  OLDSTYLE und REGPARM erkannt.                               */
{
  Var *new;int f;
  struct_declaration *sd;
  static zmax paroffset;
  zmax al;
  /*if(*identifier==0) return;*/ /* sollte woanders bemaekelt werden */
  if(DEBUG&2) printf("add_var(): %s\n",identifier);
#ifdef HAVE_TARGET_VARHOOK_PRE
  add_var_hook_pre(identifier,t,storage_class,clist);
#endif
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
  if(ISFUNC(t->flags&NQ)&&(ISARRAY(t->next->flags)||ISFUNC(t->next->flags)))
    error(25);
  new=mymalloc(sizeof(Var));
  if(!*identifier&&identifier!=empty) ierror(0);
  new->clist=clist;
  new->vtyp=t;
  new->storage_class=storage_class&PLAIN_STORAGE_CLASS;
  new->reg=0;
  new->vattr=0;
  new->next=0;
  new->flags=0;
  new->inr=0;
  new->fi=0;
  new->nesting=nesting;
  new->filename=filename;
  new->line=line;
  new->dfilename=0;
  new->dline=0;
  new->description=0;
  new->tunit=last_tunit;
  new->inline_copy=0;
  new->index=-1;
#ifdef HAVE_TARGET_ATTRIBUTES
  new->tattr=0;
#endif
  /*    if((storage_class&PLAIN_STORAGE_CLASS)==STATIC||(storage_class&PLAIN_STORAGE_CLASS)==EXTERN) new->flags=USEDASSOURCE|USEDASDEST;*/
  if(DEBUG&2) printf("storage_class=%d\n",storage_class);
  if(storage_class&PARAMETER) new->flags|=USEDASDEST;
  if(storage_class&REGPARM){
    new->flags|=REGPARM;
    if(!(storage_class&DBLPUSH)){
      if((storage_class&OLDSTYLE)&&(t->flags&NQ)==FLOAT)
	new->flags|=CONVPARAMETER;
      storage_class&=~PARAMETER;
    }
  }
  if(DEBUG&2) printf("storage_class=%d\n",storage_class);
  if(DEBUG&2) printf("max_offset=%ld\n",zm2l(max_offset));
  if(is_vlength(t)&&storage_class!=AUTO&&storage_class!=REGISTER)
    error(315);
  if((storage_class&PLAIN_STORAGE_CLASS)==REGISTER) new->priority=registerpri; else new->priority=0;
  if(/*nesting==0&&*/new->storage_class==EXTERN){
    int m=nesting;
    nesting=0;
    new->identifier=add_identifier(identifier,strlen(identifier));
    nesting=m;
    if(last_ext){
      last_ext->next=new;
      last_ext=new;
    }else{
      first_ext=last_ext=new;
      vl0=first_ext;
    }
    if(hash_ext) add_hashentry(hash_ext,new->identifier,new);
  }else{
    new->identifier=add_identifier(identifier,strlen(identifier));
    if(last_var[nesting]){
      new->offset=zmadd(last_var[nesting]->offset,szof(last_var[nesting]->vtyp));
      last_var[nesting]->next=new;
      last_var[nesting]=new;
    }else{
      new->offset=l2zm(0L);
      paroffset=l2zm(0L);;
      first_var[nesting]=last_var[nesting]=new;
      if(nesting==0) vl1=new;
      if(nesting==1) vl2=new;
    }
  }
  f=t->flags&NQ;
  if((storage_class&PLAIN_STORAGE_CLASS)==AUTO||(storage_class&PLAIN_STORAGE_CLASS)==REGISTER){
    if(DEBUG&2) printf("auto\n");
    al=falign(t);
    if((c_flags_val[0].l&2)&&nesting==1&&!(storage_class&PARAMETER)){
      new->offset=max_offset;
    }else{
      if(storage_class&PARAMETER){
        new->offset=paroffset;
	if(align_arguments)
	  new->offset=zmmult(zmdiv(zmadd(new->offset,zmsub(al,l2zm(1L))),al),al);
      }else{
        new->offset=local_offset[nesting];
	new->offset=zmmult(zmdiv(zmadd(new->offset,zmsub(al,l2zm(1L))),al),al);
      }
    }
    if(storage_class&PARAMETER){
      new->offset=zmmult(zmdiv(zmadd(new->offset,zmsub(stackalign,l2zm(1L))),stackalign),stackalign);
      if(ISINT(f)&&f<INT&&!short_push){
        /*  Integer-Erweiterungen fuer alle Funktionsparameter  */
        paroffset=zmadd(new->offset,sizetab[INT]);
      }else{
        if(f==FLOAT&&(storage_class&OLDSTYLE)){
          /*  Bei alten Funktionen werden FLOAT als DOUBLE uebergeben */
          new->offset=zmmult(zmdiv(zmadd(new->offset,zmsub(align[DOUBLE],l2zm(1L))),align[DOUBLE]),align[DOUBLE]);
          paroffset=zmadd(new->offset,sizetab[DOUBLE]);
        }else{
          paroffset=zmadd(new->offset,szof(new->vtyp));
        }
      }
    }else{
      local_offset[nesting]=zmadd(new->offset,szof(new->vtyp));
    }
    if(!(storage_class&PARAMETER))
      if(zmleq(max_offset,local_offset[nesting])) max_offset=local_offset[nesting];
    if(DEBUG&2) printf("max_offset=%ld\n",zm2l(max_offset));
  }
  if((storage_class&PLAIN_STORAGE_CLASS)==STATIC) new->offset=l2zm((long)++label);
  if(storage_class&PARAMETER){

    if(DEBUG&2) printf("parameter\n");

    if(ISINT(f)&&f<INT&&!zmleq(sizetab[INT],sizetab[f])){
      if(BIGENDIAN){
        new->offset=zmadd(new->offset,zmsub(sizetab[INT],sizetab[f]));
      }else{
        if(!LITTLEENDIAN)
          ierror(0);
      }
    }
    if((storage_class&OLDSTYLE)&&f==FLOAT){
      /*  Bei alten Funktionen werden DOUBLE nach FLOAT konvertiert   */
      if(!(storage_class&REGPARM)){
#if HAVE_LIBCALLS
	static type dt={DOUBLE},ft={FLOAT};
	static node n,nn;
	IC *conv=new_IC();
	n.flags=REINTERPRET;
	n.left=&nn;
	n.ntyp=&dt;
	nn.flags=IDENTIFIER;
	nn.identifier=identifier;
	nn.ntyp=&ft;
	nn.o.flags=VAR|DONTREGISTERIZE;
	nn.o.v=new;
	nn.o.val.vmax=l2zm(0L);
	n.o=nn.o;
	convert(&n,FLOAT);
	

	conv->code=ASSIGN;
	conv->typf=FLOAT;
	conv->q1=n.o;
	conv->z.v=new;
	conv->z.flags=VAR;
	conv->z.val.vmax=l2zm(0L);
	conv->q2.val.vmax=sizetab[FLOAT];
	conv->z.v=new;
	add_IC(conv);	
#else
	IC *conv=new_IC();
	conv->code=CONVERT;
	conv->typf=FLOAT;
	conv->typf2=DOUBLE;
	conv->q1.flags=VAR|DONTREGISTERIZE;
	conv->z.flags=VAR;
	conv->q2.flags=0;
	conv->q1.v=conv->z.v=new;
	conv->q1.val.vmax=conv->z.val.vmax=l2zm(0);
	add_IC(conv);
#endif
      }
      new->flags|=CONVPARAMETER;
    }
    new->offset=zmsub(l2zm(0L),zmadd(maxalign,new->offset));
  }
  if((storage_class&PLAIN_STORAGE_CLASS)==EXTERN){
    if(!strcmp("fprintf",identifier)) new->flags|=PRINTFLIKE;
    if(!strcmp("printf",identifier))  new->flags|=PRINTFLIKE;
    if(!strcmp("sprintf",identifier)) new->flags|=PRINTFLIKE;
    if(!strcmp("fscanf",identifier))  new->flags|=SCANFLIKE;
    if(!strcmp("scanf",identifier))   new->flags|=SCANFLIKE;
    if(!strcmp("sscanf",identifier))  new->flags|=SCANFLIKE;
  }
  if(is_vlength(new->vtyp))
    create_allocvl(new);
#ifdef HAVE_TARGET_VARHOOK_POST
  add_var_hook_post(new);
#endif
  return(new);
}
void free_var(Var *p)
/*  Gibt Variablenliste inkl. Typ, aber ohne Identifier frei.   */
{
  Var *merk;
  while(p){
    if(!*p->identifier&&p->identifier!=empty) ierror(0);
    free(p->description);
    free(p->vattr);
    merk=p->next;
    if(!(p->flags&USEDASADR)&&(p->storage_class==AUTO||p->storage_class==REGISTER)){
      if(*p->identifier&&!(p->flags&USEDASDEST)&&ISSCALAR(p->vtyp->flags)) error(64,p->identifier);
      if(*p->identifier&&!(p->flags&USEDASSOURCE)&&ISSCALAR(p->vtyp->flags)) error(65,p->identifier);
    }
    if(DEBUG&2) printf("free_var %s, pri=%d\n",p->identifier,p->priority);
    if(p->vtyp) freetyp(p->vtyp);
    if(p->clist) free_clist(p->clist);
    if(p->fi){
      if(DEBUG&2) printf("free_fi of function %s\n",p->identifier);
      free_fi(p->fi);
      if(DEBUG&2) printf("end free_fi of function %s\n",p->identifier);
    }
    free(p);
    p=merk;
  }
}
Var *find_ext_var(char *identifier)
{
  Var *v;int l;
  if(misracheck) l=strlen(identifier);
  if(hash_ext) return find_name(hash_ext,identifier);
  for(v=first_ext;v;v=v->next){
    if(!strcmp(v->identifier,identifier)) return v;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
#endif

  }
  return 0;
}
Var *find_var(char *identifier,int endnesting)
/*  Sucht Variable mit Bezeichner und liefert Zeiger zurueck    */
/*  es werden nur Variablen der Bloecke endnesting-nesting      */
/*  durchsucht.                                                 */
{
  int i,l;Var *v;
  if(identifier==0||*identifier==0) return 0;
  if(misracheck) l=strlen(identifier);
  for(i=nesting;i>=endnesting;i--){
    for(v=first_var[i];v;v=v->next){
      if(!strcmp(v->identifier,identifier))
	return v;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
#endif
    }
  }
  if(endnesting==0){
    v=find_ext_var(identifier);
    if(v&&!(v->flags&NOTINTU))
      return v;
    else
      return 0;
  }else
    return 0;
}


#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif



int check_zero_initialisation(const_list* cl, int typ) 
{
  
  if (cl->next) return 0;
  if (cl->tree) return 0;
  if (cl->other)  {
    return check_zero_initialisation(cl->other,typ);
  } else {
    eval_const(&cl->val,typ);
    if ( (zmeqto(vmax,l2zm(0L))) && (zumeqto(vumax,ul2zum(0UL))) && (zldeqto(vldouble,d2zld(0.0))) ) {
      return 1;
    }
  }
  return 0;
}

/* decide whether a initialization shall be performed only be generated code
   or if a table copy should be used first */
int use_only_dyn_init(zmax sz,zmax dyn_sz,zmax const_sz,int dyn_cnt,int const_cnt)
{
  if(zmleq(sz,l2zm(clist_copy_stack)))
    return 1;
  if(zmeqto(dyn_sz,l2zm(0L)))
    return 0;
  if(!zmleq(zmdiv(sz,dyn_sz),l2zm(2L)))
    return 0;
  else
    return 1;
}

void init_local_compound(Var *v)
{
  if(v->storage_class==AUTO||v->storage_class==REGISTER){
    IC *new;
    /*  Initialisierung von auto-Variablen  */
    new=new_IC();
    new->code=ASSIGN;
    new->typf=v->vtyp->flags;
    new->q2.flags=0;
    new->q2.val.vmax=szof(v->vtyp);
    new->z.flags=VAR;
    new->z.v=v;
    new->z.val.vmax=l2zm(0L);
    if(v->clist->tree){
      /*  einzelner Ausdruck  */
      gen_IC(v->clist->tree,0,0);
      convert(v->clist->tree,v->vtyp->flags&NU);
      new->q1=v->clist->tree->o;
      add_IC(new);
      /*                        v->clist=0;*/
    }else{
      /*  Array etc.  */
      Var *nv;
      if(!ISSCALAR(v->vtyp->flags)&&!use_only_dyn_init(szof(v->vtyp),init_dyn_sz,init_const_sz,init_dyn_cnt,init_const_cnt)){
	nv=add_var(empty,clone_typ(v->vtyp),STATIC,v->clist);
	nv->flags|=DEFINED;
	nv->dfilename=filename;
	nv->dline=line;
	nv->vtyp->flags|=CONST;
	/*                        v->clist=0;*/
	new->q1.flags=VAR;
	new->q1.v=nv;
	new->q1.val.vmax=l2zm(0L);

	add_IC(new);
	
	dynamic_init(v,v->vtyp,v->clist,0,1);
      }else{
	dynamic_init(v,v->vtyp,v->clist,0,0);
      }
    }   
  }
}

#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
#endif

void var_declaration(void)
/*  Bearbeitet eine Variablendeklaration und erzeugt alle       */
/*  noetigen Strukturen.                                        */
{
  type *ts,*t,*old=0,*om=0;char *imerk,vident[MAXI];
  int mdef=0,makeint=0,notdone,storage_class,msc,extern_flag,isfunc,
    had_decl,hard_reg,mhr,diffunit=0,inline_flag;
  Var *v;
  char *vattr;
  zumax mask;
  int base_type;
#ifdef HAVE_TARGET_ATTRIBUTES
  unsigned long tattr;
#endif
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
#endif
  ts=declaration_specifiers();notdone=1;

  storage_class=return_sc;hard_reg=return_reg;vattr=return_vattr;mask=return_mask;
  inline_flag=return_inline;
#ifdef HAVE_ECPP
/* removed */
#endif
  if(for_decl&&storage_class!=0&&storage_class!=AUTO&&storage_class!=REGISTER){
    error(299);
    storage_class=AUTO;
  }

#ifdef HAVE_TARGET_ATTRIBUTES
  tattr=return_tattr;
#endif
  if(storage_class==EXTERN) extern_flag=1; else extern_flag=0;
  killsp();
  if(ctok->type==SEMIC){
    if(!ts) error(0);
    if(storage_class||(!ISSTRUCT(ts->flags)&&!ISUNION(ts->flags)&&(ts->flags&NQ)!=INT))
      error(36);
    freetyp(ts);
    next_token();killsp();
    return;
  }
  if(nesting==0&&(storage_class==AUTO||storage_class==REGISTER))
    {error(66);storage_class=EXTERN;}
  if(!ts){
    if(nesting<=1){
      ts=new_typ();
      ts->flags=INT;ts->next=0;
      makeint=1;
      if(!storage_class) storage_class=EXTERN;
#ifdef HAVE_MISRA
/* removed */
#endif
      error(67);
    }else{
      error(365);
    }
  }
  if(storage_class==0){
    if(nesting==0) 
      storage_class=EXTERN;
    else
      storage_class=AUTO;
  }
  msc=storage_class;mhr=hard_reg;
  while(notdone){
    int oldnesting=nesting;
    imerk=ident;ident=vident;*vident=0;  /* merken von ident hier vermutlich */
    storage_class=msc;hard_reg=mhr;
    if(old) {freetyp(old);old=0;}
    t=declarator(clone_typ(ts));
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
#ifdef HAVE_EXT_TYPES
    conv_typ(t);
#endif
    if(!ISFUNC(t->flags)){
        isfunc=0;
        if(inline_flag) error(301);
    }else{
        isfunc=1;
#ifdef HAVE_MISRA
/* removed */
#endif
        if(storage_class!=STATIC&&storage_class!=TYPEDEF) storage_class=EXTERN;
    }
    ident=imerk;                    /* nicht unbedingt noetig ?         */
    if(!*vident){
      free(ts);free(t);
      error(36);return;
    }
    v=find_var(vident,oldnesting);
    if(!v&&/*oldnesting==0&&*/storage_class==EXTERN&&cross_module&&(v=find_ext_var(vident))){
      v->flags&=~NOTINTU;
      diffunit=1;
      /*FIXME: check auf doppelte Def. */
    }
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
    if(v){
      had_decl=1;
      if(storage_class==TYPEDEF){
        error(226,v->identifier);
      }else{
        if(nesting>0&&(v->flags&DEFINED)&&!extern_flag&&!isfunc){
          error(27,vident);
        }else{
          if(t&&v->vtyp&&!compatible_types(v->vtyp,t,NU|CONST|VOLATILE)){
	    if(ISFUNC(t->flags)&&!ISFUNC(v->vtyp->flags))
	      error(361,vident);
	    else
	      error(68,vident);
#ifdef HAVE_MISRA
/* removed */
#endif
          }
          if((storage_class!=v->storage_class&&!extern_flag)||hard_reg!=v->reg)
            error(28,v->identifier);
          if(!isfunc&&!extern_flag) v->flags|=TENTATIVE;
        }
#ifdef HAVE_TARGET_ATTRIBUTES
        {
          int i;
          for(i=0;g_attr_name[i];i++){
            if((v->tattr&(1L<<i))!=(tattr&(1L<<i))) error(228,vident,g_attr_name[i]);
          }
          v->tattr=tattr;
        }
#endif
        if(vattr){
	  if(!v->vattr||!strstr(v->vattr,vattr)){
	    error(370,v->identifier,vattr,v->vattr?v->vattr:empty);
	    add_attr(&v->vattr,vattr);
	  }
          if(ISFUNC(v->vtyp->flags)) fi_from_attr(v);
        }
        if(!isfunc){
          if(!ISARRAY(t->flags)||!zmeqto(t->size,l2zm(0L))){
            free(v->vtyp);
            v->vtyp=t;
          }
        }else{
          om=v->vtyp;
          if(t->exact->count>0){
            old=v->vtyp;v->vtyp=t;
          }
        }
      }
#ifdef HAVE_TARGET_VARHOOK_POST
      add_attr_haddecl=v;
      add_var_hook_post(v);
      add_attr_haddecl=0;
#endif
      
    }else{
      had_decl=0;
#ifdef HAVE_MISRA
/* removed */
#endif
      if(isfunc&&ctok->type!=COMMA&&ctok->type!=SEMIC&&ctok->type!=RPAR&&ctok->type!=ASGN&&nesting>0) nesting--;
      if(!zumeqto(mask,ul2zum(0UL))){
	sprintf(vident+strlen(vident),".%lu",zum2ul(mask));
      }
      v=add_var(vident,t,storage_class,0);
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
      v->reg=hard_reg;
      if(vattr)
	add_attr(&v->vattr,vattr);
      if(ISFUNC(v->vtyp->flags))
        fi_from_attr(v);
#ifdef HAVE_TARGET_ATTRIBUTES
      v->tattr=tattr;
#endif
      if(isfunc&&ctok->type!=COMMA&&ctok->type!=SEMIC&&ctok->type!=RPAR&&ctok->type!=ASGN&&nesting>=0) nesting++;
      if(!v) ierror(0);
      else{
        if(!isfunc&&!extern_flag){
          v->flags|=TENTATIVE;
          if(nesting>0){
            v->flags|=DEFINED;
            v->dfilename=filename;
            v->dline=line;
          }
        }
      }
      om=0;
    }
    if(isfunc&&inline_flag){
      v->flags|=INLINEFUNC;
      if(extern_flag) v->flags|=INLINEEXT;
    }
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
    if(disallow_statics&&v->storage_class==STATIC&&*v->identifier&&!is_const(v->vtyp))
      error(302,v->identifier);
    killsp();
    /*  Inline-Assembler-Code in Funktionsdeklarationen */
    if(ctok->type==ASGN&&ISFUNC(v->vtyp->flags)&&(header_cnt>0||!(c_flags[7]&USEDFLAG))){
      np tree;
      next_token();killsp();
      if(v->fi){free(v->fi->inline_asm);v->fi->inline_asm=0;}
      if(!v->fi) v->fi=new_fi();
      v->fi->inline_asm=get_string();
      /*STRBACK(v->fi->inline_asm);*/
      mdef=1;
    }else{
      /*if(v->fi){free(v->fi->inline_asm);v->fi->inline_asm=0;}*/
    }
    /*  Initialisierung von Variablen bei Deklaration   */
    if(ctok->type==ASGN){

      next_token();killsp();
      if(!had_decl&&v->nesting==0&&v->storage_class==EXTERN&&strcmp("main",v->identifier))
        error(168,v->identifier);
      if(v->flags&DEFINED){
        if(nesting==0) error(30,v->identifier);
      }else{
        v->flags|=DEFINED;
        v->dfilename=filename;
        v->dline=line;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
      }
      if(v->storage_class==TYPEDEF) error(114,v->identifier);
      if(extern_flag){
        if(nesting==0)
          error(118,v->identifier);
        else
          error(207,v->identifier);
        if(v->storage_class!=EXTERN){ error(77);v->storage_class=EXTERN;}
      }
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
      init_dyn_sz=l2zm(0L);
      init_dyn_cnt=0;
      init_const_sz=l2zm(0L);
      init_const_cnt=0;
      v->clist=initialization(v->vtyp,v->storage_class==AUTO||v->storage_class==REGISTER,0,0,0,0);
                /* MISRA Rule 9.2 violation checking and error reporting */
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
      if(v->clist){
        if(ISARRAY(v->vtyp->flags)&&zmeqto(v->vtyp->size,l2zm(0L))){
          const_list *p=v->clist;
          while(p){v->vtyp->size=zmadd(p->idx,l2zm(1L));p=p->next;}
          if(v->storage_class==AUTO||v->storage_class==REGISTER){
            local_offset[nesting]=zmadd(local_offset[nesting],szof(v->vtyp));
            if(zmleq(max_offset,local_offset[nesting])) max_offset=local_offset[nesting];
          }
        }
        if(v->storage_class==AUTO||v->storage_class==REGISTER){

	  init_local_compound(v);

        }else if(c_flags[19]&USEDFLAG){
          /*  Ohne Optimierung gleich erzeugen; das ist noch  */
          /*  etwas von der genauen Implementierung der Liste */
          /*  der Variablen abhaengig.                        */
          Var *merk=v->next;
          v->next=0;
          gen_vars(v);
          v->next=merk;
          v->clist=0;
        }
      }
    }else{
      if((v->flags&DEFINED)&&type_uncomplete(v->vtyp)) error(202,v->identifier);
      if((v->vtyp->flags&CONST)&&(v->storage_class==AUTO||v->storage_class==REGISTER))
        error(119,v->identifier);
    }
    if(ctok->type==COMMA) {next_token();killsp();mdef=1;} else notdone=0;
  }
  freetyp(ts);

  if(ISFUNC(t->flags)&&v->reg)
    t->next->reg=v->reg;

  if(!mdef&&t&&(t->flags&NQ)==FUNKT&&ctok->type!=SEMIC){
    /*  Funktionsdefinition*/
    int i,oldstyle=0;

#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
#ifdef HAVE_REGPARMS
    treg_handle reg_handle;
#endif
    if(DEBUG&1) printf("Funktionsdefinition! %s %p\n",v->identifier,(void *)v);
    {
      int i;
      for(i=1;i<=MAXR;i++) {regs[i]=regused[i]=regsa[i];regsbuf[i]=0;}
    }
    cur_func=v->identifier;
    cur_funcv=v;
    if(only_inline==2) only_inline=0;
    if(nesting<1) enter_block();
    if(nesting>1) error(32);
    if(v->flags&DEFINED){
      if(!inline_flag||!cross_module){
                                error(33,v->identifier);
      }else{
        if(v->fi->first_ic){
          free_IC(v->fi->first_ic);
          v->fi->first_ic=0;
        }
      }
    }else{
      v->flags|=DEFINED;
      v->dfilename=filename;
      v->dline=line;
#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
    }
    if(storage_class!=EXTERN&&storage_class!=STATIC) error(34);
    if(extern_flag&&!inline_flag) error(120);
    if(storage_class==EXTERN&&!strcmp(v->identifier,"main")&&(!t->next||t->next->flags!=INT)) error(121);
    if(!had_decl&&v->nesting==0&&v->storage_class==EXTERN&&strcmp("main",v->identifier))
      error(168,v->identifier);
    while(!ecpp&&ctok->type!=LBRA){
      /*  alter Stil  */
      type *nt=declaration_specifiers();notdone=1;oldstyle=OLDSTYLE;
      if(!ts) {error(35);}
      while(notdone){
        int found=0;
        imerk=ident;ident=vident;*vident=0;
        ts=declarator(clone_typ(nt));
        ident=imerk;
        if(!ts) {error(36);}
        else{
          for(i=0;i<t->exact->count;i++){
            if(!strcmp((*t->exact->sl)[i].identifier,vident)){
              found=1;
              if((*t->exact->sl)[i].styp){
                error(69,vident);
                freetyp((*t->exact->sl)[i].styp);
              }
              /*  typ[] in *typ   */
              if(ISARRAY(ts->flags)) ts->flags=POINTER_TYPE(ts);
              /*  typ() in *typ() */
              if(ISFUNC(ts->flags)){
                type *new=new_typ();
                new->flags=POINTER_TYPE(ts);
                new->next=ts;
                ts=new;
              }
              if(!return_sc) return_sc=AUTO;
              if(return_sc!=AUTO&&return_sc!=REGISTER)
                {error(122);return_sc=AUTO;}
              (*t->exact->sl)[i].storage_class=return_sc;
              (*t->exact->sl)[i].reg=return_reg;
              if(return_reg) error(219);
              (*t->exact->sl)[i].styp=ts;
            }
          }
        }
        if(!found) {error(37,vident);}
        killsp();
        if(ctok->type==COMMA) {next_token();killsp();} else notdone=0;
      }
      if(nt) freetyp(nt);
      if(ctok->type==SEMIC){
        next_token();killsp();
      }else{
        error(54);
        while(ctok->type!=LBRA&&ctok->type!=SEMIC){next_token();killsp();}
      }
    }
    if(!ecpp&&t->exact->count==0){
      struct_list sl[1];
      if(DEBUG&1) printf("prototype converted to (void)\n");
      t->exact->count=1;
      sl[0].identifier=empty;
      sl[0].storage_class=AUTO;
      sl[0].styp=new_typ();
      sl[0].styp->flags=VOID;
      sl[0].styp->next=0;
      sl[0].reg=0;
      nesting--;
      add_sl(t->exact,&sl);
      nesting++;
    }
    if(om&&om->exact&&!compare_sd(om->exact,t->exact)) {
      error(123);
#ifdef HAVE_MISRA
/* removed */
#endif
    }
    nocode=0;currentpri=1;
    /*        enter_block();*/
    local_offset[1]=l2zm(0L);
    return_var=0;
    if(!v->vtyp) ierror(0);
#ifdef HAVE_REGPARMS
    reg_handle=empty_reg_handle;
#endif
    if(v->vtyp->next->flags==VOID){
      return_typ=0;
    }else{
      return_typ=v->vtyp->next;
      if(!ffreturn(return_typ)&&(return_typ->flags&NQ)!=VOID){
        /*  Parameter fuer die Rueckgabe von Werten, die nicht in einem */
        /*  Register sind.                                              */
        type *rt=new_typ();int reg;
        rt->flags=POINTER_TYPE(return_typ);rt->next=return_typ;
#ifdef HAVE_REGPARMS
        reg=reg_parm(&reg_handle,rt,0,v->vtyp);
        if(!reg){
	  return_var=add_var(empty,clone_typ(rt),AUTO|PARAMETER|oldstyle,0);
	}else{
	  return_var=add_var(empty,clone_typ(rt),reg<0?(AUTO|PARAMETER|REGPARM|DBLPUSH|oldstyle):(AUTO|PARAMETER|REGPARM|oldstyle),0);
	  return_var->reg=reg;
	}
#else
        return_var=add_var(empty,clone_typ(rt),AUTO|PARAMETER|oldstyle,0);
#endif
        return_var->flags|=DEFINED;
        return_var->dfilename=filename;
        return_var->dline=line;
        free(rt);
      }
    }
    first_ic=last_ic=0;ic_count=0;max_offset=l2zm(0L);
    if(!zmleq(local_offset[1],Z0)) max_offset=local_offset[1];
    for(i=0;i<t->exact->count;i++){
      /* TODO: missing pointer for struct return */
#ifdef HAVE_REGPARMS
      int didrp=0;
      if((*t->exact->sl)[i].styp){
        int tr;
        tr=reg_parm(&reg_handle,(*t->exact->sl)[i].styp,0,t);
        didrp=1;
        if(!(*t->exact->sl)[i].reg) (*t->exact->sl)[i].reg=tr;
      }
#endif
      if(!(*t->exact->sl)[i].styp&&*(*t->exact->sl)[i].identifier){
        type *nt;
#ifdef HAVE_MISRA
/* removed */
#endif
        nt=new_typ();
        nt->flags=INT;
        (*t->exact->sl)[i].styp=nt;
        (*t->exact->sl)[i].storage_class=AUTO;
        (*t->exact->sl)[i].reg=0;
        error(124);
      }
      if(*(*t->exact->sl)[i].identifier){
        Var *tmp;int sc,tr;
        sc=((*t->exact->sl)[i].storage_class|PARAMETER|oldstyle);
#ifdef HAVE_REGPARMS
        if(!didrp){
          if(!t->exact->sl) ierror(0);
          if(!(*t->exact->sl)[i].styp) ierror(0);
          tr=reg_parm(&reg_handle,(*t->exact->sl)[i].styp,0,t);
          if(!(*t->exact->sl)[i].reg) (*t->exact->sl)[i].reg=tr;
        }
#endif
        if((*t->exact->sl)[i].reg>0) sc|=REGPARM;
        if((*t->exact->sl)[i].reg<0) sc|=(REGPARM|DBLPUSH);
        tmp=add_var((*t->exact->sl)[i].identifier,clone_typ((*t->exact->sl)[i].styp),sc,0);
        tmp->reg=(*t->exact->sl)[i].reg;
        tmp->flags|=DEFINED;
        tmp->dfilename=filename;
        tmp->dline=line;
        if(oldstyle){
#ifdef HAVE_MISRA
/* removed */
#endif
          freetyp((*t->exact->sl)[i].styp);
          (*t->exact->sl)[i].styp=0; /*  Prototype entfernen */
        }
      }
    }
    if(oldstyle) t->exact->count=0; /*  Prototype entfernen */
    /*        local_offset[1]=l2zm(0L);*/
    return_label=++label;
    function_calls=0;float_used=0;has_return=0;goto_used=0;vlas=0;
    did_return_label=0;
    for(i=1;i<=MAXR;i++) simple_scratch[i]=0;
    if(v->storage_class==EXTERN&&(v->flags&INLINEFUNC))
      disallow_statics=1;
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif

    if(c99){
      /* c99 predefined __func__ */
      type *ft=new_typ();
      Var *fnc;

      /* create type */
      ft->flags=ARRAY;
      ft->size=l2zm((long)strlen(cur_func)+1);
      ft->next=new_typ();
      ft->next->flags=CONST|CHAR;

      /* use string_expression() to create const_list */
      fnc=add_var("__func__",ft,STATIC,cl_from_string(cur_func,cur_func+strlen(cur_func)));
      fnc->flags|=DEFINED;
    }

    /* Generate intermediate code for function */
    compound_statement();

#ifdef HAVE_MISRA
/* removed */
#endif
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
#endif
    cur_funcv=0;
    disallow_statics=0;
    if(block_vla[nesting]) clearvl();
    if((v->vtyp->next->flags&NQ)!=VOID&&!has_return){
      if(strcmp(v->identifier,"main")) error(173,v->identifier);
      else error(174,v->identifier);
    }
#if 0
    {int i;
    for(i=1;i<=MAXR;i++) if(regs[i]!=regsa[i]) {printf("Register %s:\n",regnames[i]);ierror(0);}
    }
#endif
    if(!did_return_label){
      clear_main_ret();
      gen_label(return_label);
    }
    /* backpatch code for jumps out of vla-scope if necessary */
    if(vlas)
      vla_jump_fix();
    if(cross_module){
      if(!v->fi) v->fi=new_fi();
      v->fi->statics=first_var[0];
    }else if(first_ic&&errors==0){
      if((c_flags[2]&USEDFLAG)&&ic1){fprintf(ic1,"function %s\n",v->identifier); pric(ic1,first_ic);}
      vl1=first_var[0];
      vl2=first_var[1];
      vl3=merk_varf;
      optimize(optflags,v);
      if((c_flags[3]&USEDFLAG)&&ic2){fprintf(ic2,"function %s\n",v->identifier); pric(ic2,first_ic);}
      if(out&&!only_inline&&!(c_flags[5]&USEDFLAG)){
        memset(regs_modified,0,RSIZE);
        gen_code(out,first_ic,v,max_offset);
        static_stack_check(v);
        v->flags|=GENERATED;
#ifdef HAVE_REGS_MODIFIED
        if(!v->fi) v->fi=new_fi();
        if(v->fi->flags&ALL_REGS)
        {
          int i;
          for(i=1;i<=MAXR;i++){
            if(reg_pair(i,&rp)){
              if(BTST(regs_modified,i)){
                BSET(regs_modified,rp.r1);
                BSET(regs_modified,rp.r2);
              }else{
                if(BTST(regs_modified,rp.r1)||BTST(regs_modified,rp.r2))
                  BSET(regs_modified,i);
              }
            }
          }
          memcpy(v->fi->regs_modified,regs_modified,RSIZE);
          v->fi->flags|=ALL_REGS;
        }
#endif
      }
      /*if(DEBUG&8192){fprintf(ic2,"function %s, after gen_code\n",v->identifier); pric(ic2,first_ic);}*/
      free_IC(first_ic);
      first_ic=last_ic=0;
    }
    if(cross_module){
      if(!v->fi) v->fi=new_fi();
      v->fi->first_ic=first_ic;
      v->fi->last_ic=last_ic;
      first_ic=last_ic=0;
    }
    if(v->fi&&v->fi->first_ic){
      Var *vp;
      if(DEBUG&1) printf("leave block %d (inline-version)\n",nesting);
      if(block_vla[nesting]) clearvl();
      if(nesting!=1) ierror(0);
      if(merk_varl) merk_varl->next=first_var[nesting]; else merk_varf=first_var[nesting];
      if(last_var[nesting]) merk_varl=last_var[nesting];
      if(merk_sil) merk_sil->next=first_si[nesting]; else merk_sif=first_si[nesting];
      if(last_si[nesting]) merk_sil=last_si[nesting];
      if(merk_sdl) merk_sdl->next=first_sd[nesting]; else merk_sdf=first_sd[nesting];
      if(last_sd[nesting]) merk_sdl=last_sd[nesting];
      if(merk_ilistl) merk_ilistl->next=first_ilist[nesting]; else merk_ilistf=first_ilist[nesting];
      if(last_ilist[nesting]) merk_ilistl=last_ilist[nesting];
      
      if(merk_varf&&!only_inline&&!cross_module) gen_vars(merk_varf);
      if(first_llist) free_llist(first_llist);
      first_llist=0;
      if(first_clist) free_clist(first_clist);
      first_clist=0;
      if(merk_sif) free_si(merk_sif);
      /*  struct-declarations erst ganz am Schluss loeschen. Um zu vermeiden,     */
      /*  dass struct-declarations in Prototypen frei werden und dann eine        */
      /*  spaetere struct, dieselbe Adresse bekommt und dadurch gleich wird.      */
      /*  Nicht sehr schoen - wenn moeglich noch mal aendern.                     */
      /*            if(merk_sdf) free_sd(merk_sdf);*/
      /*  hier noch was ueberlegen    */
      /*            if(merk_ilistf) free_ilist(merk_ilistf);*/
      nesting--;
      v->fi->vars=merk_varf;
      /*            v->fi->vars=first_var[1];*/
      /*  keine echten Parameter=>keine negativen Offsets */
      /*            vp=first_var[1];*/
      if(!cross_module){
        vp=merk_varf;
        while(vp){
          if(vp->storage_class==AUTO||vp->storage_class==REGISTER){
            /*if(DEBUG&1024) printf("handling variable %s(%ld)/%p\n",vp->identifier,zm2l(vp->offset),(void*)vp);*/
            if(!zmleq(l2zm(0L),vp->offset)){
              vp->offset=l2zm(0L);
              if(DEBUG&1024) printf("converted parameter <%s>(%ld) for inlining\n",vp->identifier,(long)zm2l(vp->offset));
            }else vp->offset=l2zm(4L);  /*  Dummy, da recalc_offsets?   */
          }
          vp=vp->next;
        }
      }
    }else{
      leave_block();
    }
    if(only_inline==2) only_inline=0;
    cur_func="oops, I forgot it";
  }else{
    if(makeint) error(125);
    if(ctok->type==SEMIC) next_token(); else error(54);
    if(ISFUNC(t->flags)&&t->exact){
      struct_declaration *sd=t->exact;int i,f;
      for(f=0,i=0;i<sd->count;i++)
        if(!(*sd->sl)[i].styp){error(126);f=1;}
      if(f){
        for(i=0;i<sd->count;i++) if((*sd->sl)[i].styp) freetyp((*sd->sl)[i].styp);
        sd->count=0;
      }
    }
  }
  if(old) freetyp(old);
}
int compatible_types(type *a,type *b,int qual)
/*  Vergleicht, ob Typ beider Typen gleich ist, const/volatile      */
/*  werden laut ANSI nicht beruecksichtigt.                         */
{
  struct_declaration *sd;
  int af=a->flags&qual,bf=b->flags&qual;
  if(af!=bf) return(0);
  af&=NQ;bf&=NQ;
  if(ISFUNC(af)){
    if(a->exact->count&&!compare_sd(a->exact,b->exact)) return(0);
  }
  if(ISSTRUCT(af)||ISUNION(af)){
    if(cross_module&&a->exact->tunit!=b->exact->tunit) return 1;
    if(a->exact!=b->exact) return(0);
  }
  if(ISARRAY(af)){
    if(!zmeqto(a->size,l2zm(0L))&&!zmeqto(b->size,l2zm(0L))&&!zmeqto(a->size,b->size)) return(0);
  }
  if(a->next==0&&b->next!=0) return(0);
  if(a->next!=0&&b->next==0) return(0);
  if(a->next==0&&b->next==0) return(1);
  if(qual!=NQ) qual=(NU|CONST|VOLATILE);
  return(compatible_types(a->next,b->next,qual));
}
int compare_sd(struct_declaration *a,struct_declaration *b)
/*  Vergleicht, ob zwei struct_declarations identisch sind          */
/*  Wird nur nur fuer Prototypen benutzt, leere Liste immer gleich. */
{
  int i;
  if(!a->count||!b->count) return(1);
  if(a->count!=b->count) return(0);
  for(i=0;i<a->count;i++){
    if((*a->sl)[i].styp&&(*b->sl)[i].styp&&!compatible_types((*a->sl)[i].styp,(*b->sl)[i].styp,NU)) return(0);
    if((*a->sl)[i].reg!=(*b->sl)[i].reg) {error(368);return 0;}
#ifdef HAVE_MISRA
/* removed */
/* removed */
#endif
  }
  return(1);
}
void free_clist(const_list *p)
/*  Gibt clist frei.                                        */
{
  const_list *merk;
  return;
  while(p){
    merk=p->next;
    if(p->other) free_clist(p->other);
    if(p->tree) free_expression(p->tree);
    free(p);
    p=merk;
  }
}
void gen_clist(FILE *,type *,const_list *);

void gen_vars(Var *v)
/*  Generiert Variablen.                                    */
{
  int mode,al,first_pass=1;Var *p;
  if(errors!=0||(c_flags[5]&USEDFLAG)) return;
  if(optsize)
    al=zm2l(maxalign);
  else
    al=0;
  for(;al>=0;al--){
    for(mode=0;mode<3;mode++){
      int i,flag;
      for(p=v;p;p=p->next){
	if(p->flags&NEEDS) continue;
        if(optsize&&zm2l(falign(p->vtyp))!=al)
          continue;
        if(cross_module&&!(p->flags&REFERENCED)) continue;
        if(DEBUG&2) printf("gen_var(): %s\n",p->identifier);
        if(p->storage_class==STATIC||p->storage_class==EXTERN){
          if(!(p->flags&GENERATED)){
            if(p->storage_class==EXTERN&&!(p->flags&(USEDASSOURCE|USEDASDEST))&&!(p->flags&(TENTATIVE|DEFINED))) continue;
	    if(p->storage_class==STATIC&&p->nesting>0&&!(p->flags&(USEDASSOURCE|USEDASDEST))) continue;
            /*  erst konstante initialisierte Daten */
            if(mode==0){
              if(!p->clist) continue;
              if(!(p->vtyp->flags&(CONST|STRINGCONST))){
                type *t=p->vtyp;int f=0;
                do{
                  if(t->flags&(CONST|STRINGCONST)) break;
                  if(!ISARRAY(t->flags)){f=1;break;}
                  t=t->next;
                }while(1);
                if(f) continue;
              }
            }
            /*  dann initiolisierte */
            if(mode==1&&!p->clist) continue;
            /*  und dann der Rest   */
         
	    if(mode==2&&p->clist) continue;
   
            if(!(p->flags&(TENTATIVE|DEFINED))){
              if(!((p->vtyp->flags&NQ)==FUNKT)||!p->fi||!p->fi->inline_asm){
		if(mask_opt){
		  if((p->flags&PRINTFLIKE)&&!strstr(p->identifier,".")) needs("vfprintf");
		  if((p->flags&SCANFLIKE)&&!strstr(p->identifier,".")) needs("vfscanf");
		}
                gen_var_head(out,p);
	      }
              if(p->storage_class==STATIC&&(!p->fi||!p->fi->inline_asm)) error(127,p->identifier);
              continue;
            }else{
              /*gen_align(out,falign(p->vtyp));*/
            }
            if(!((p->vtyp->flags&NQ)==FUNKT)||!p->fi||!p->fi->inline_asm){
	      if(mask_opt){
		if((p->flags&PRINTFLIKE)&&!strstr(p->identifier,".")) needs("vfprintf");
		if((p->flags&SCANFLIKE)&&!strstr(p->identifier,".")) needs("vfscanf");
	      }
              gen_var_head(out,p);
	    }
            if(!p->clist){
              if(type_uncomplete(p->vtyp)) error(202,p->identifier);
              gen_ds(out,szof(p->vtyp),p->vtyp);
            }else{
              gen_clist(out,p->vtyp,p->clist);
            }
            p->flags|=GENERATED;
          }else if(p->flags&INLINEEXT){
            /* a function was declared extern inline and defined;
               we have to create external linkage */
            int m=p->flags;
            /* pretend, it was only declared, but not defined and remove
               INLINEEXT */
            p->flags&=~(DEFINED|INLINEEXT);
            gen_var_head(out,p);
            p->flags|=DEFINED;
          }
        }
      }
      first_pass=0;
    }
  }
  if(mask_opt){
    for(p=v;p;p=p->next)
      if(p->flags&NEEDS) gen_var_head(out,p);
  }
}

/* creates code that dynamically initializes a variable */
void dynamic_init(Var *v,type *t,const_list *cl,zmax of,int noconst)
{
  int f=t->flags;
  if(ISARRAY(f)){
    zmax i;
    for(i=l2zm(0L);!zmleq(t->size,i);i=zmadd(i,l2zm(1L))){
      if(cl&&zmeqto(cl->idx,i)){
	dynamic_init(v,t->next,cl->other,of,noconst);
	cl=cl->next;
      }else{
	dynamic_init(v,t->next,0,of,noconst);
      }
      of=zmadd(of,szof(t->next));
    }
  }else if(ISUNION(f)&&(!cl||!cl->tree)){
    dynamic_init(v,(*t->exact->sl)[cl?zm2l(cl->idx):0].styp,cl?cl->other:0,of,noconst);
  }else if(ISSTRUCT(f)&&(!cl||!cl->tree)){
    zmax al;int fl;type *st;
    int bfo,i;
    for(i=0;i<t->exact->count&&cl;i++){
      if(!cl->other){
	if(errors==0)
	  ierror(0);
	return;
      }
      st=(*t->exact->sl)[i].styp;
      al=(*t->exact->sl)[i].align;
      if(!(*t->exact->sl)[i].identifier) ierror(0);
      bfo=(*t->exact->sl)[i].bfoffset;
      if(!zmeqto(zmmod(of,al),l2zm(0L))){
        of=zmadd(of,zmsub(al,zmmod(of,al)));
      }
      if(bfo>=0){
	int bfs=(*t->exact->sl)[i].bfsize;
	static obj dest = {0};
	  
	dest.flags=VAR;
	dest.v=v;
	dest.val.vmax=of;

	if(bfo==0){
	  /* first clear entire bitfield */
	  IC *new=new_IC();
	  new->code=ASSIGN;
	  new->z=dest;
	  new->typf=st->flags;
	  new->q2.val.vmax=sizetab[st->flags&NQ];
	  new->q1.flags=KONST;
	  new->q1.val.vmax=l2zm(0L);
	  eval_const(&new->q1.val,MAXINT);
	  insert_const(&new->q1.val,st->flags&NU);
	  add_IC(new);
	}

	/* bitfield */
	if(!zmeqto(cl->idx,l2zm(i))||!cl->other){
	  /* nothing to do, initialized before */
	}else if(cl->other->tree){
	  obj dummy;
	  gen_IC(cl->other->tree,0,0);
	  convert(cl->other->tree,st->flags);
	  insert_bitfield(&dest,&cl->other->tree->o,&cl->other->tree->o,bfs,bfo,st->flags,1);
	  cl=cl->next;
	}else{
	  static obj val = {0};
	  val.flags=KONST;
	  val.val=cl->other->val;
	  insert_bitfield(&dest,&val,&val,bfs,bfo,st->flags,1);
	  cl=cl->next;
	}
	if(i+1>=t->exact->count||(*t->exact->sl)[i+1].bfoffset<=0||!cl){
	  of=zmadd(of,szof(st));
	}
      }else{
	if(zmeqto(l2zm((long)i),cl->idx)){
	  dynamic_init(v,st,cl->other,of,noconst);
	  cl=cl->next;
	}else
	  dynamic_init(v,st,0,of,noconst);
        of=zmadd(of,szof(st));
      }
    }
    for(;i<t->exact->count;i++){
      st=(*t->exact->sl)[i].styp;
      al=(*t->exact->sl)[i].align;
      bfo=(*t->exact->sl)[i].bfoffset;
      if(bfo>0) continue;
      if(!zmeqto(zmmod(of,al),l2zm(0L))){
        of=zmadd(of,zmsub(al,zmmod(of,al)));
      }
      dynamic_init(v,st,0,of,noconst);
      of=zmadd(of,szof(st));
    }
  }else{
    IC *new;
    if(noconst&&(!cl||!cl->tree))
      return;
    new=new_IC();
    new->code=ASSIGN;
    new->z.flags=VAR;
    new->z.v=v;
    new->z.val.vmax=of;
    new->typf=t->flags;
    new->q2.val.vmax=szof(t);
    if(!cl){
      new->q1.flags=KONST;
      gval.vmax=l2zm(0L);
      eval_const(&gval,MAXINT);
      insert_const(&new->q1.val,t->flags&NU);
    }else if(cl->tree){
      gen_IC(cl->tree,0,0);
      if(ISSCALAR(t->flags))
	convert(cl->tree,t->flags);
      new->q1=cl->tree->o;
    }else{
      new->q1.flags=KONST;
      new->q1.val=cl->val;
    }
    add_IC(new);
  }
}


void gen_clist(FILE *f,type *t,const_list *cl)
/*  Generiert dc fuer const_list.                           */
{
  int i,bfo,bfs;zmax sz;zumax bfval=ul2zum(0UL);

#if 0
  for(i=0;i<(int)szof(t);i++){
    zuchar c;int s;
    s=get_clist_byte(t,cl,i,&c);
    printf("%03d: 0x%02x (%d)\n",i,(int)c,s);
  }
#endif


  if(ISARRAY(t->flags)){
    for(sz=l2zm(0L);!zmleq(t->size,sz)&&cl;cl=cl->next){
      if(!cl->other){ierror(0);return;}
      if(!zmeqto(sz,cl->idx))
	gen_ds(f,zmmult(zmsub(cl->idx,sz),szof(t->next)),t->next);

      gen_clist(f,t->next,cl->other);
      sz=zmadd(cl->idx,l2zm(1L));
    }
    if(!zmleq(t->size,sz)) gen_ds(f,zmmult(zmsub(t->size,sz),szof(t->next)),t->next);
    return;
  }
  if(ISUNION(t->flags)){
    int i=zm2l(cl->idx);
    if(cl&&cl->tree){
      /* union initialized by another union */
      gen_ds(f,szof(t),t);
    }else{
      gen_clist(f,(*t->exact->sl)[i].styp,cl->other);
      sz=zmsub(szof(t),szof((*t->exact->sl)[i].styp));
      if(!zmeqto(sz,l2zm(0L))) gen_ds(f,sz,0);
    }
    return;
  }
  if(ISSTRUCT(t->flags)){
    zmax al;int fl;type *st;
    sz=l2zm(0L);
    if(cl&&cl->tree){
      /* initialized by another */
      gen_ds(f,szof(t),t);
      sz=zmadd(sz,szof(t));
    }else{
      for(i=0;i<t->exact->count&&cl;i++){
	if(!cl->other){ierror(0);return;}
	st=(*t->exact->sl)[i].styp;
	al=(*t->exact->sl)[i].align;
	if(!(*t->exact->sl)[i].identifier) ierror(0);
	bfo=(*t->exact->sl)[i].bfoffset;
	if(!zmeqto(zmmod(sz,al),l2zm(0L))){
	  gen_ds(f,zmsub(al,zmmod(sz,al)),0);
	  sz=zmadd(sz,zmsub(al,zmmod(sz,al)));
	}
	if(bfo>=0){
	  /* bitfield */
	  if((*t->exact->sl)[i].identifier[0]){
	    bfs=(*t->exact->sl)[i].bfsize;
	    if(zmeqto(l2zm((long)i),cl->idx)){
	      eval_const(&cl->other->val,st->flags);
	      cl=cl->next;
	    }else{
	      vumax=ul2zum(0UL);
	    }
	    vumax=zumand(vumax,zumsub(zumlshift(ul2zum(1UL),ul2zum((unsigned long)bfs)),ul2zum(1UL)));
	    bfval=zumor(bfval,zumlshift(vumax,ul2zum((unsigned long)bflayout(bfo,bfs,st->flags))));
	  }          
	  if(i+1>=t->exact->count||(*t->exact->sl)[i+1].bfoffset<=0||!cl){
	    /* last bitfield in integer */
	    const_list bfcl;
	    gval.vumax=bfval;
	    eval_const(&gval,UNSIGNED|MAXINT);
	    insert_const(&bfcl.val,st->flags&NU);
	    bfcl.tree=0;
	    gen_dc(f,st->flags&NU,&bfcl);
	    bfval=ul2zum(0L);
	    sz=zmadd(sz,szof(st));
	  }
	}else{
	  if(zmeqto(l2zm((long)i),cl->idx)){
	    gen_clist(f,st,cl->other);
	    cl=cl->next;
	  }else
	    gen_ds(f,szof(st),st);
	  sz=zmadd(sz,szof(st));
	}
      }
      for(;i<t->exact->count;i++){
	st=(*t->exact->sl)[i].styp;
	al=(*t->exact->sl)[i].align;
	bfo=(*t->exact->sl)[i].bfoffset;
	if(bfo>0) continue;
	if(!zmeqto(zmmod(sz,al),l2zm(0L))){
	  gen_ds(f,zmsub(al,zmmod(sz,al)),0);
	  sz=zmadd(sz,zmsub(al,zmmod(sz,al)));
	}
	gen_ds(f,szof((*t->exact->sl)[i].styp),(*t->exact->sl)[i].styp);
	sz=zmadd(sz,szof(st));
      }
    }
    al=falign(t);
    if(!zmeqto(zmmod(sz,al),l2zm(0L)))
      gen_ds(f,zmsub(al,zmmod(sz,al)),0);
    return;
  }

  if(cl->tree) cl->tree->o.am=0;

  if(zmeqto(cl->idx,l2zm(-1L)))
    gen_ds(f,szof(t),t);
  else
    gen_dc(f,t->flags&NU,cl);
}

/* finds the correct place in a const list to insert new initializer */
const_list *insert_cl(const_list *old,zmax idx)
{
  const_list *p,*cl=0;
  if(old&&zmleq(old->idx,idx)){
    p=old;
    do{
      if(zmeqto(p->idx,idx)){
	/* found existing entry */
	cl=p;
	break;
      }
      if(!p->next||!zmleq(p->next->idx,idx))
	break;
      p=p->next;
    }while(p);
  }else
    p=0;
  /* we need a new entry */
  if(!cl){
    cl=mymalloc(CLS);
    cl->tree=0;
    cl->other=0;
    cl->idx=idx;
    if(p){
      cl->next=p->next;
      p->next=cl;
    }else
      cl->next=old;
  }
  return cl;
}

const_list *designator(type *t,const_list *cl)
{
  int f=t->flags&NQ;
  np tree;
  if(!c99) return 0;
  if(ISARRAY(f)&&ctok->type==LBRK){
    next_token();
    killsp();
    tree=expression();
    if(ctok->type!=RBRK)
      error(62);
    else
      {next_token();killsp();}
    if(!type_expression(tree,0)){
      /*                    error("incorrect constant expression");*/
    }else{
      if(tree->sidefx) error(60);
      if(tree->flags!=CEXPR||!ISINT(tree->ntyp->flags)){
	error(19);
      }else{
	/* check index for valid range */
	eval_constn(tree);
	if(!zmleq(l2zm(0L),vmax)) {error(354);vmax=l2zm(0L);}
	if(!zmeqto(t->size,l2zm(0L))&&zmleq(t->size,vmax)) {error(354);vmax=l2zm(0L);}

	cl=insert_cl(cl,vmax);

	return cl;
      }
    }
  }else if((ISSTRUCT(f)||ISUNION(f))&&ctok->type==DOT){
    next_token();
    killsp();
    if(ctok->type!=NAME){
      error(53);
    }else{
      int i,n=-1;
      for(i=0;i<t->exact->count;i++)
	if(!strcmp((*t->exact->sl)[i].identifier,ctok->name)) n=i;
      if(n<0){
	error(23,ctok->name);
	return 0;
      }
      next_token();
      killsp();

      if(!ISUNION(f)||!cl)
	cl=insert_cl(cl,l2zm((long)n));

      return cl;
    }
  }
  return 0;
}

/* declare a builtin function with up to two scalar arguments */
Var *declare_builtin(char *name,int ztyp,int q1typ,int q1reg,int q2typ,int q2reg,int nosidefx,char *asm)
{
  struct_declaration *sd;
  type *t;
  Var *v;
  int args;
  if(!(v=find_ext_var(name))){
    sd=mymalloc(sizeof(*sd));
    if(q1typ==0) args=1;
    else if(q2typ!=0) args=3;
    else args=2;
    sd->sl=mymalloc(args*sizeof(struct_list));
    memset(sd->sl,0,args*sizeof(struct_list));
    sd->count=args;
    if(q1typ){
      (*sd->sl)[0].styp=new_typ();
      (*sd->sl)[0].styp->flags=q1typ;
      (*sd->sl)[0].reg=q1reg;
    }
    if(q2typ){
      (*sd->sl)[1].styp=new_typ();
      (*sd->sl)[1].styp->flags=q2typ;
      (*sd->sl)[1].reg=q2reg;
    }
    (*sd->sl)[args-1].styp=new_typ();
    (*sd->sl)[args-1].styp->flags=VOID;
    (*sd->sl)[args-1].reg=0;
    t=new_typ();
    t->flags=FUNKT;
    t->exact=add_sd(sd,FUNKT);
    t->next=new_typ();
    t->next->flags=ztyp;
    v=add_var(name,t,EXTERN,0);
    v->flags|=BUILTIN;
    if(asm||nosidefx){
      v->fi=new_fi();
      if(asm) v->fi->inline_asm=asm;
      if(nosidefx){
	v->fi->call_cnt=v->fi->use_cnt=v->fi->change_cnt=0;
	v->fi->flags=ALL_CALLS|ALL_USES|ALL_MODS|ALWAYS_RETURNS|NOSIDEFX;
      }
    }
  }
  return v;
}


const_list *initialization(type *t,int noconst,int level,int desi,struct_declaration *fstruct,const_list *first)
/*  Traegt eine Initialisierung in eine const_list ein.         */
{
  const_list *cl,**prev;
  np tree,tree2;
  int bracket,desi_follows=0;
  zmax i;
  token mtok;
  
  int f=t->flags&NQ;
  if(ISFUNC(f)){error(42);return(0);}
  if(ctok->type==LBRA){next_token();killsp();bracket=1;} else bracket=0;
  if(ISARRAY(f)){
#ifdef HAVE_MISRA
/* removed */
#endif
    if(t->dsize){
      error(358);
    }else if(zmeqto(t->size,l2zm(0L))&&level!=0){
      error(359);
    }else if(ctok->type==T_STRING&&t->next&&(t->next->flags&NQ)==CHAR){
      killsp();
      tree=string_expression();
      first=tree->cl;
      free_expression(tree);
    }else{
      const_list *last=first;
      if(level==0&&!bracket) error(157);
      for(i=l2zm(0L);desi_follows||((zmeqto(t->size,l2zm(0L))||!zmleq(t->size,i)||ctok->type==LBRK)&&ctok->type!=RBRA);i=zmadd(i,l2zm(1L))){
        if(!zmleq(i,0)){
          if(ctok->type==COMMA){next_token();killsp();} else break;
          if(ctok->type==RBRA) break;
        }
	/* check for first designated initializer */
	cl=designator(t,first);
	if(!cl){
	  /* no designator */
	  cl=insert_cl(last,i);
	  cl->other=initialization(t->next,c99?noconst:0,level+1,0,fstruct,cl->other);
	  if(cl->other&&zmeqto(cl->other->idx,l2zm(-2L))){
	    first=cl->other;
	    first->other=0;
	    break;
	  }
	}else{
	  /* designator: store current object and handle remaining designators */
	  i=cl->idx;
	  if(ctok->type!=ASGN){
	    if(ctok->type!=LBRK&&ctok->type!=DOT)
	      error(355);
	  }else{
	    cl->other=0;
	    next_token();killsp();
	  }
	  cl->other=initialization(t->next,c99?noconst:0,level+1,1,fstruct,cl->other);
	}
	if(cl->next==first) first=cl;
	last=cl;
        killsp();
	if(desi&&!bracket)
	  break;
	desi_follows=0;
	if(ctok->type==COMMA){
	  copy_token(&mtok,ctok);
	  next_token();killsp();
	  if(ctok->type==LBRK)
	    desi_follows=1;
	  push_token(&mtok);
	}
      }

      if(bracket&&zmeqto(i,l2zm(0L))) error(360);

#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
#endif
    }
  }else if(ISSTRUCT(f)&&(bracket||!noconst||c99)){
    if(t->exact->count<=0)
      {error(43);return(0);}
#ifdef HAVE_ECPP
/* removed */
#endif
    prev=0;
    if(level==0&&!bracket&&!c99) error(157);
    for(i=l2zm(0L);desi_follows||(!zmleq(t->exact->count,i)&&ctok->type!=RBRA);i=zmadd(i,l2zm(1L))){
      if(!desi_follows&&(*t->exact->sl)[zm2l(i)].identifier[0]==0) continue; /* unnamed bitfield */
      if(!zmleq(i,0)){
        if(ctok->type==COMMA){next_token();killsp();} else break;
        if(ctok->type==RBRA) break;
      }
      cl=designator(t,first);

      if(!cl){
	cl=insert_cl(first,l2zm((long)i));
	cl->other=initialization((*t->exact->sl)[zm2l(i)].styp,c99?noconst:0,level+1,0,!fstruct&&!bracket&&zmeqto(i,l2zm(0L))?t->exact:fstruct,cl->other);
	if(cl->other&&zmeqto(cl->other->idx,l2zm(-2L))){
	  if(fstruct){
	    first=cl->other;
	    first->other=0;
	  }else{
	    *cl=*cl->other;
	    cl->idx=l2zm(-1L);
	    cl->other=0;
	    first=cl;
	  }
	  break;
	}
      }else{
	i=zm2l(cl->idx);
	if(ctok->type!=ASGN){
	  if(ctok->type!=LBRK&&ctok->type!=DOT)
	    error(355);
	}else{
	  next_token();killsp();
	  cl->other=0;
	}
	cl->other=initialization((*t->exact->sl)[zm2l(i)].styp,c99?noconst:0,level+1,1,fstruct,cl->other);
      }
      if(cl->next==first) first=cl;
      if(desi&&!bracket)
	break;
      desi_follows=0;
      if(ctok->type==COMMA){
	copy_token(&mtok,ctok);
	next_token();killsp();
	if(ctok->type==DOT)
	  desi_follows=1;
	push_token(&mtok);
      }
    }

    if(bracket&&zmeqto(i,l2zm(0L))) error(360);

#ifdef HAVE_MISRA
/* removed */
/* removed */
/* removed */
/* removed */
#endif

  }else if(ISUNION(f)&&(c99||bracket||!noconst)){
    if(t->exact->count<=0)
      {error(44);return(0);}

    if(level==0&&!bracket&&!c99) error(157);
    desi_follows=1;
    while(desi_follows){
      cl=designator(t,first);

      if(!cl){
	cl=insert_cl(first,l2zm((long)0));
	cl->other=initialization((*t->exact->sl)[0].styp,c99?noconst:0,level+1,0,!fstruct&&!bracket?t->exact:fstruct,cl->other);
	if(cl->other&&zmeqto(cl->other->idx,l2zm(-2L))){
	  if(fstruct){
	    first=cl->other;
	    first->other=0;
	  }else{
	    *cl=*cl->other;
	    cl->other=0;
	    cl->idx=l2zm(-1L);
	    first=cl;
	  }
	  break;
	}
      }else{
	i=zm2l(cl->idx);
	if(ctok->type!=ASGN){
	  if(ctok->type!=LBRK&&ctok->type!=DOT)
	    error(355);
	}else{
	  next_token();killsp();
	  cl->other=0;
	}
	cl->other=initialization((*t->exact->sl)[zm2l(i)].styp,c99?noconst:0,level+1,1,fstruct,cl->other);
      }
      first=cl;
      if(desi&&!bracket)
	break;
      desi_follows=0;
      if(ctok->type==COMMA){
	copy_token(&mtok,ctok);
	next_token();killsp();
	if(ctok->type==DOT)
	  desi_follows=1;
	else
	  push_token(&mtok);
      }
    }
  }else{
    int oldconst=const_expr;
    tree2=tree=assignment_expression();

    if(!tree){error(45);return(0);}
    if(!noconst) const_expr=1;
    if(!type_expression(tree,t)){free_expression(tree); const_expr=oldconst;return 0;}
    const_expr=oldconst;

    tree=makepointer(tree);

    /* check for complete assignment in dynamic initialization */
    if(noconst&&(ISSTRUCT(tree->ntyp->flags)||ISUNION(tree->ntyp->flags))&&fstruct==tree->ntyp->exact){
      first=mymalloc(CLS);
      first->tree=tree;
      first->next=first->other=0;
      first->idx=l2zm(-2L);
      return first;
    }

    if(!test_assignment(t,tree)){free_expression(tree); return 0;}
    if(!noconst){
      /*  nur Konstanten erlaubt (bei Arrays/Strukturen etc. oder static) */
      if(tree->flags!=CEXPR){
        /*while(tree->flags==CAST) tree=tree->left;*/
        if(!tree->sidefx/*tree->flags==ADDRESS||tree->flags==ADDRESSS||tree->flags==ADDRESSA*/){
          const_expr=1;
          gen_IC(tree,0,0);
          const_expr=oldconst;
          if(!(tree->o.flags&VARADR)){
            /*  hier fehlen noch viele Pruefungen   */
            free_expression(tree);error(46);
            return(0);
          }
          tree->o.v->flags|=USEDASADR;
          first=mymalloc(CLS);
          first->next=first->other=0;
          first->tree=tree;
	  first->idx=l2zm(0L);
          killsp();
        }else{
          free_expression(tree);error(46);
          return(0);
        }
      }else{
        first=mymalloc(CLS);
	first->idx=l2zm(0L);
        first->next=first->other=0;
        first->tree=0;
        eval_constn(tree);
        tree->ntyp->flags=t->flags;
        insert_constn(tree);
        first->val=tree->val;
        free_expression(tree2);
        killsp();
      }
    }else{
      /*  auch anderes erlaubt    */
      first=mymalloc(CLS);
      first->next=first->other=0;
      first->tree=tree;
      killsp();
      if(!tree->sidefx){
	if(tree->flags==CEXPR){
	  eval_constn(tree);
	  tree->ntyp->flags=t->flags;
	  insert_constn(tree);
	  first->val=tree->val;
	  first->tree=0;
	  first->idx=l2zm(0L);
	  init_const_sz=zmadd(init_const_sz,szof(tree->ntyp));
	  init_const_cnt++;
	  free_expression(tree2);
	}else{
	  first->idx=l2zm(-1L);
	  init_dyn_sz=zmadd(init_dyn_sz,szof(tree->ntyp));
	  init_dyn_cnt++;
	}
      }else{
	first->idx=l2zm(-1L);
	init_dyn_sz=zmadd(init_dyn_sz,szof(tree->ntyp));
	init_dyn_cnt++;
      }
    }
  }
  if(bracket){
    if(ctok->type==COMMA){next_token();killsp();}
    if(ctok->type==RBRA){next_token();killsp();} else error(128);
  }
  return(first);
}
#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 */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* 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
