/*  $VER: vbcc (main.c) $Revision: 1.67 $    */
#include "vbcc_cpp.h"
#include "vbc.h"
#include "opt.h"
static char FILE_[]=__FILE__;
void do_function(Var *);
static function_info *current_fi;
token *ctok;
lexer_state ls;
int endok=1;
int line,errors;
bvtype task_preempt_regs[RSIZE/sizeof(bvtype)];
bvtype task_schedule_regs[RSIZE/sizeof(bvtype)];
char *multname[]={"","s"};

typedef struct deplist {char *name; struct deplist *next;} deplist;
deplist *deps;
FILE *depout;
void handle_deps(char *name,int string)
{
  deplist *p=deps;
  if(!depout||!name||!*name) return;
  /* by default omit <...> includes */
  if(!string&&!(c_flags[51]&USEDFLAG)) return;
  while(p){
    if(!strcmp(p->name,name)) return;
    p=p->next;
  }
  p=mymalloc(sizeof(*p));
  p->name=mymalloc(strlen(name)+1);
  strcpy(p->name,name);
  p->next=deps;
  deps=p;
  fprintf(depout," %s",name);
}

void raus(void)
/*  Beendet das Programm                                            */
{
  static int inraus;
  if(inraus) return;
  inraus = 1;
  if(DEBUG) printf("raus()\n");
  if(!endok) fprintf(stderr,"unexpected end of file\n");
  if(errors) fprintf(stderr,"%d error%s found!\n",errors,multname[errors>1]);
  if(debug_info&&out)
    cleanup_db(out);
  while(nesting>=0) leave_block();
  /*FIXME: do I have to close input-file? */
  if(!wpo)
    cleanup_cg(out);
  emit_flush(out);
  if(cmdfile) fclose(cmdfile);
  if(out) fclose(out);
  if(ic1) fclose(ic1);
  if(ic2) fclose(ic2);
  /*FIXME: need to cleanup something for ucpp?*/;
  if(endok&&!errors) exit(EXIT_SUCCESS); else exit(EXIT_FAILURE);
}
int eof;
void translation_unit(void)
/*  bearbeitet translation_unit                                     */
/*  hier z.Z. nur provisorisch                                      */
{
  Var *p;
  if(cross_module){
    for(p=first_ext;p;p=p->next)
      if(!(p->flags&BUILTIN))
	p->flags|=NOTINTU;
  }
  while(1){
    killsp();
    if(eof||ctok->type!=NAME){
      if(!eof){
	error(369);
	next_token();
	continue;
      }else{
	if(cross_module){
	  int n=0;
	  if(last_tunit){
	    last_tunit->next=mymalloc(sizeof(*first_tunit));
	    last_tunit=last_tunit->next;
	  }else{
	    first_tunit=last_tunit=mymalloc(sizeof(*first_tunit));
	  }
	  last_tunit->next=0;
	  for(p=first_var[0];p;p=p->next){
	    if(p->storage_class==STATIC) n++;
	  }
	  last_tunit->statics=first_var[0];
	  return;
	}else{
	  raus();
	}
      }
    }
    endok=0;
    var_declaration();
    endok=1;
  }
}
void reserve_reg(char *p)
     /* reserviert ein Register */
{
  int i;
  if(*p!='=') error(4,"-reserve-reg");
  for(i=1;i<=MAXR;i++){
    if(!strcmp(p+1,regnames[i]))
      break;
  }
  if(i>MAXR){
    error(331,p+1);
  }else{
    regsa[i]=1;
  }
}

void dontwarn(char *p)
/*  schaltet flags fuer Meldung auf DONTWARN    */
{
  if(*p!='=') error(4,"-dontwarn");
  do{
    int i=atoi(p+1);
    if(i>=err_num) error(159,i);
    if(i<0){
      for(i=0;i<err_num;i++)
        if(!(err_out[i].flags&(ANSIV|FATAL)))
    err_out[i].flags|=DONTWARN;
      return;
    }
    if(err_out[i].flags&(ANSIV|FATAL)) error(160,i);
    err_out[i].flags|=DONTWARN;
    p=strchr(p+1,',');
  } while(p);
}



#define MISRA_98_RULE_NUMBER	127
#define MISRA_04_CHAPTER			21
#define MISRA_04_MAX_RULE_IN_CHAPTER 17

static int misra_98_warn_flag[MISRA_98_RULE_NUMBER] = { 0 };
static int misra_04_warn_flag[MISRA_04_CHAPTER][MISRA_04_MAX_RULE_IN_CHAPTER] = { 0 };

void misrawarn(char *p) {
	int rule,subrule,misraoldrule;
	char* last;
	int not_found;
	tmisra_err_out* misr_err;
	rule = 0;
	subrule = 0;
	misraoldrule = 0;
  if(*p!='=') error(4,"-misrawarn");
	p++;
	if (!(strncmp("chapter",p,6))) {
		if (sscanf((p+7),"%d",&rule) != 1) {
			error(327,"-misrawarn");
		}
	} else if ( !(strncmp("misra98rule",p,11))) {
		if (sscanf((p+12),"%d",&misraoldrule) != 1) {
			error(327,"-misrawarn");
		}
	} else {
		if (last = strchr(p,'.')) {
			*last = 0;
			last++;
			if (sscanf(last,"%d",&subrule) != 1) error(327,"-misrawarn");
			if (sscanf(p,"%d",&rule) != 1) error(327,"-misrawarn");
			last--;
			*last='.';
		} else error(327,"-misrawarn");
	}

	p--;
	if (!misracheck) misracheck = 1;
	if (misraoldrule) {
		if (misraversion==2004) error(328,misraversion,"-misrawarn",p);
		if (!misraversion) misraversion=1998;
		if ((misraoldrule < 1) || (misraoldrule>MISRA_98_RULE_NUMBER)) error(329,misraoldrule,"-misrawarn",p);
		misra_98_warn_flag[misraoldrule-1] = 1;
	} else {
		if (misraversion==1998) error(328,misraversion,"-misrawarn",p);
		if (!misraversion) misraversion=2004;
		if (subrule) {
			misr_err = misra_err_out;
		  not_found = 1;
			while ( misr_err->text ) {
				if ((misr_err->chapter == rule) && (misr_err->rule == subrule)) {
					not_found = 0;
					break;
				}
				misr_err++;
			}
			if (not_found) error(330,rule,subrule,"-misrawarn",p);
			misra_04_warn_flag[rule-1][subrule-1] = 1;
		} else {
			misr_err = misra_err_out;
		  not_found = 1;
			while ( misr_err->text ) {
				if (misr_err->chapter == rule) {
					not_found = 0;
					misra_04_warn_flag[misr_err->chapter-1][misr_err->rule-1] = 1;
				}
				misr_err++;
			}
			if (not_found) error(330,rule,subrule,"-misrawarn",p);
		}
	}

}


void misradontwarn(char *p) {
	int rule,subrule,misraoldrule;
	char* last;
	int not_found;
	tmisra_err_out* misr_err;
	rule = 0;
	subrule = 0;
	misraoldrule = 0;
  if(*p!='=') error(4,"-misradontwarn");
	p++;
	if (!(strncmp("chapter",p,6))) {
		if (sscanf((p+7),"%d",&rule) != 1) {
			error(327,"-misradontwarn");
		}
	} else if ( !(strncmp("misra98rule",p,11))) {
		if (sscanf((p+12),"%d",&misraoldrule) != 1) {
			error(327,"-misradontwarn");
		}
	} else {
		if (last = strchr(p,'.')) {
			*last = 0;
			last++;
			if (sscanf(last,"%d",&subrule) != 1) error(327,"-misradontwarn");
			if (sscanf(p,"%d",&rule) != 1) error(327,"-misradontwarn");
			last--;
			*last='.';
		} else error(327,"-misradontwarn");
	}

	p--;
	if (misraoldrule) {
		if (misraversion==2004) error(328,misraversion,"-misradontwarn",p);
		if ((misraoldrule < 1) || (misraoldrule>MISRA_98_RULE_NUMBER)) error(329,misraoldrule,"-misradontwarn",p);
		misra_98_warn_flag[misraoldrule-1] = -1;
	} else {
		if (misraversion==1998) error(328,misraversion,"-misradontwarn",p);
		if (subrule) {
			misr_err = misra_err_out;
		  not_found = 1;
			while ( misr_err->text ) {
				if ((misr_err->chapter == rule) && (misr_err->rule == subrule)) {
					not_found = 0;
					break;
				}
				misr_err++;
			}
			if (not_found) error(330,rule,subrule,"-misradontwarn",p);
			misra_04_warn_flag[rule-1][subrule-1] = -1;
		} else {
			misr_err = misra_err_out;
		  not_found = 1;
			while ( misr_err->text ) {
				if (misr_err->chapter == rule) {
					not_found = 0;
					misra_04_warn_flag[misr_err->chapter-1][misr_err->rule-1] = -1;
				}
				misr_err++;
			}
			if (not_found) error(330,rule,subrule,"-misradontwarn",p);
		}
	}

}



void warn(char *p)
/*  schaltet Warnung fuer Meldung ein           */
/*  wenn Nummer<0 sind alle Warnungen ein       */
{
  int i;
  if(*p!='=') error(4,"-warn");
  i=atoi(p+1);
  if(i>=err_num) error(159,i);
  if(i<0){
    for(i=0;i<err_num;i++) err_out[i].flags&=~DONTWARN;
    return;
  }else err_out[i].flags&=~DONTWARN;
}
void gen_function(FILE *f,Var *v,int real_gen)
{
  IC *p,*new;int i,had_regs;
  if(DEBUG&1) printf("gen_function <%s>,f=%p,real_gen=%d\n",v->identifier,(void*)f,real_gen);
  if(!v->fi) ierror(0);
  if(errors!=0) return;
  first_ic=last_ic=0;
  for(i=1;i<=MAXR;i++) {regs[i]=regused[i]=regsa[i];regsbuf[i]=0;}
  function_calls=0;vlas=0;
  if(!real_gen){
    for(p=v->fi->first_ic;p;p=p->next){
      new=new_IC();
      *new=*p;
      p->copy=new;
      add_IC(new);
      new->file=p->file;
      new->line=p->line;
      if(p->code==CALL){
	int i;
	function_calls++;
	if((p->q1.flags&VAR)&&!strcmp(p->q1.v->identifier,"__allocvla")){
          vlas=1;
          v->fi->flags|=USES_VLA;
        }
	new->arg_list=mymalloc(sizeof(*new->arg_list)*new->arg_cnt);
	for(i=0;i<new->arg_cnt;i++) new->arg_list[i]=p->arg_list[i]->copy;      
      }
    }
  }else{
    for(i=1;i<=MAXR;i++) regused[i]=0;
    for(p=v->fi->opt_ic;p;p=p->next){
      if(p->code==ALLOCREG){
	regused[p->q1.reg]=1;
	if(reg_pair(p->q1.reg,&rp)){
	  regused[rp.r1]=1;
	  regused[rp.r2]=1;
	}
      }
      if(p->code==CALL){
	if((p->q1.flags&VAR)&&!strcmp(p->q1.v->identifier,"__allocvla")) vlas=1;
	function_calls++;
      }
    }
  }
  if(vlas&&FPVLA_REG) regs[FPVLA_REG]=regused[FPVLA_REG]=regsa[FPVLA_REG]=regscratch[FPVLA_REG]=1;
      
  if(!real_gen&&(c_flags[2]&USEDFLAG)&&ic1){
    fprintf(ic1,"function %s\n",v->identifier);
    pric(ic1,first_ic);
  }
  vl0=first_ext;
  vl1=v->fi->statics;
  vl2=0;
  vl3=v->fi->vars;
  nesting=1;
  first_var[nesting]=last_var[nesting]=0;
  cur_func=v->identifier;
  if(!real_gen){
    optimize(optflags,v);
    if((force_statics||prefer_statics)&&first_var[nesting]){
      
      last_var[nesting]->next=v->fi->vars;
      v->fi->vars=first_var[nesting];
    }
    memset(regs_modified,0,RSIZE);
    /* pseudeo generator pass to get regs_modified */
    v->fi->opt_ic=clone_ic(first_ic);
    v->fi->max_offset=max_offset;
    if(v->fi&&(v->fi->flags&ALL_REGS))
      had_regs=1;
    else
      had_regs=0;
    gen_code(0,first_ic,v,max_offset);
#ifdef HAVE_REGS_MODIFIED
    if(!v->fi) v->fi=new_fi();
    {
      int i;IC *p;
      for(i=1;i<=MAXR;i++){
	if(BTST(regs_modified,i)&&reg_pair(i,&rp)){
	  BSET(regs_modified,rp.r1);
	  BSET(regs_modified,rp.r2);
	}
      }
#if 1
      for(i=1;i<=MAXR;i++){
	if(reg_pair(i,&rp)){
	  if(BTST(regs_modified,rp.r1)||BTST(regs_modified,rp.r2))
	    BSET(regs_modified,i);
	}
      }
#endif
      if(had_regs){
	if(memcmp(regs_modified,v->fi->regs_modified,RSIZE))
	  error(321,v->identifier);
      }else
	memcpy(v->fi->regs_modified,regs_modified,RSIZE);
#if 0
      printf("regs for %s (ALL_REGS=%d):\n",v->identifier,v->fi->flags&ALL_REGS);
      for(i=1;i<MAXR;i++) if(BTST(regs_modified,i)) printf("%s ",regnames[i]);
      printf("\n");
#endif
    }
#endif
    v->flags|=GENERATED;
    free_IC(first_ic);
    first_ic=last_ic=0;
    /*free_var(first_var[nesting]);*/
    nesting=0;
  }else{
    if((c_flags[3]&USEDFLAG)&&ic2){
      fprintf(ic2,"function %s\n",v->identifier);
      pric(ic2,v->fi->opt_ic);
    }
    gen_code(f,v->fi->opt_ic,v,v->fi->max_offset);
    static_stack_check(v);
  }
}
/* handle functions in a const list before caller */
static void do_clist_calls(const_list *cl)
{
  while(cl){
    if(cl->tree&&(cl->tree->o.flags&VARADR)){
      Var *v=cl->tree->o.v;
      if(ISFUNC(v->vtyp->flags)){
	if(DEBUG&1)
	  printf(":: %s\n",v->identifier);
	do_function(v);
      }
    }
    if(cl->other)
      do_clist_calls(cl->other);
    cl=cl->next;
  }
}
void do_function(Var *v)
{
  int i;IC *p;
  if((v->flags&(GENERATED|DEFINED))!=DEFINED) return;
  v->flags|=GENERATED;
  if(!v->fi) v->fi=new_fi();
#if 0  
  for(i=0;i<v->fi->call_cnt;i++){
    if(v->fi->call_list[i].v->flags&DEFINED)
      do_function(v->fi->call_list[i].v);
  }
#endif
  /* handle callees before caller */
  for(p=v->fi->first_ic;p;p=p->next){
    /* direct call */
    if(p->code==CALL&&(p->q1.flags&(VAR|DREFOBJ))==VAR)
      do_function(p->q1.v);
    /* function address is also a candidate */
    if((p->q1.flags&(VAR|VARADR))&&ISFUNC(p->q1.v->vtyp->flags))
      do_function(p->q1.v);
    if((p->q2.flags&(VAR|VARADR))&&ISFUNC(p->q2.v->vtyp->flags))
      do_function(p->q2.v);
    if((p->z.flags&(VAR|VARADR))&&ISFUNC(p->z.v->vtyp->flags))
      do_function(p->z.v);
    /* indirect call, handle special case */
    if(p->code==CALL&&(p->q1.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ)){
      Var *v=p->q1.v;
      if(v->storage_class==AUTO||v->storage_class==REGISTER){
	IC *m=p->prev;Var *tmp=0;
	while(m&&(m->code<LABEL||m->code>=BRA)){
	  if(!tmp&&(m->z.flags&(VAR|DREFOBJ))==VAR&&m->z.v==v&&
	     (m->q1.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ))
	    tmp=m->q1.v;
	  if(tmp&&(m->z.flags&(VAR|DREFOBJ))==VAR&&m->z.v==tmp&&
	     (m->q1.flags&(VAR|VARADR))==(VAR|VARADR)&&
	     m->q1.v->clist&&is_const(m->q1.v->vtyp)){
	    do_clist_calls(m->q1.v->clist);
	  }
	  m=m->prev;
	}
      }
    }
  }
  gen_function(0,v,0);
}



extern char *copyright;
int main(int argc,char *argv[])
{
  int i,j,*fname=malloc(argc*sizeof(int)),files=0;
  unsigned long ucpp_flags=LEXER|WARN_TRIGRAPHS|WARN_STANDARD|WARN_ANNOYING/*|CCHARSET*/|HANDLE_PRAGMA|COPY_LINE|WARN_TRIGRAPHS_MORE|HANDLE_TRIGRAPHS;
  if(!fname) ierror(0);
  memset(fname,0,argc*sizeof(int));
  c_flags_val[9].f=dontwarn;
  c_flags_val[10].f=warn;
  c_flags_val[42].f=misrawarn;
  c_flags_val[43].f=misradontwarn;
  c_flags_val[44].f=reserve_reg;
  for(i=1;i<argc;i++){
    if(*argv[i]!='-'){  /*  kein Flag   */
      fname[i]=1;
      files++;
      if(!inname) inname=argv[i];
    }else{
      int flag=0;
      if(argv[i][1]=='D'||argv[i][1]=='I') flag=1;
      for(j=0;j<MAXCF&&flag==0;j++){
	size_t l;
	if(!c_flags_name[j]) continue;
	l=strlen(c_flags_name[j]);
	if(l>0&&!strncmp(argv[i]+1,c_flags_name[j],l)&&(argv[i][1+l]==0||argv[i][1+l]=='=')){
	  flag=1;
	  if((c_flags[j]&(USEDFLAG|FUNCFLAG))==USEDFLAG){error(2,argv[i]);break;}
	  c_flags[j]|=USEDFLAG;
	  if(c_flags[j]&STRINGFLAG){
	    if(argv[i][l+1]!='='){error(3,argv[i]);}
	    if(argv[i][l+2]||i>=argc-1)
	      c_flags_val[j].p=&argv[i][l+2];
	    else
	      c_flags_val[j].p=&argv[++i][0];
	  }
	  if(c_flags[j]&VALFLAG){
	    if(argv[i][l+1]!='='){error(4,argv[i]);}
	    if(argv[i][l+2]||i>=argc-1)
	      c_flags_val[j].l=atol(&argv[i][l+2]);
	    else
	      c_flags_val[j].l=atol(&argv[++i][0]);
	  }
	  if(c_flags[j]&FUNCFLAG) c_flags_val[j].f(&argv[i][l+1]);
	}
      }
      for(j=0;j<MAXGF&&flag==0;j++){
	size_t l;
	if(!g_flags_name[j]) continue;
	l=strlen(g_flags_name[j]);
	if(l>0&&!strncmp(argv[i]+1,g_flags_name[j],l)){
	  flag=1;
	  if((g_flags[j]&(USEDFLAG|FUNCFLAG))==USEDFLAG){error(2,argv[i]);break;}
	  g_flags[j]|=USEDFLAG;
	  if(g_flags[j]&STRINGFLAG){
	    if(argv[i][l+1]!='='){error(3,argv[i]);}
	    if(argv[i][l+2]||i>=argc-1)
	      g_flags_val[j].p=&argv[i][l+2];
	    else
	      g_flags_val[j].p=&argv[++i][0];
	  }
	  if(g_flags[j]&VALFLAG){
	    if(argv[i][l+1]!='='){error(4,argv[i]);}
	    if(argv[i][l+2]||i>=argc-1)
	      g_flags_val[j].l=atol(&argv[i][l+2]);
	    else
	      g_flags_val[j].l=atol(&argv[++i][0]);
	  }
	  if(g_flags[j]&FUNCFLAG) g_flags_val[j].f(&argv[i][l+1]);
	}
      }
      if(!flag){error(5,argv[i]);}
    }
  }
  if(!(c_flags[6]&USEDFLAG)){
#ifdef SPECIAL_COPYRIGHT
    printf("%s\n",SPECIAL_COPYRIGHT);
#else
    printf("%s\n",copyright);
    printf("%s\n",cg_copyright);
#endif
  }
  if(c_flags[4]&USEDFLAG) DEBUG=c_flags_val[4].l; else DEBUG=0;
  if(c_flags[13]&USEDFLAG) ucpp_flags|=CPLUSPLUS_COMMENTS;
  if(c_flags[14]&USEDFLAG) ucpp_flags|=CPLUSPLUS_COMMENTS;
  if(c_flags[15]&USEDFLAG) ucpp_flags&=~HANDLE_TRIGRAPHS;
  if(c_flags[52]&USEDFLAG) ucpp_flags&=~(WARN_STANDARD|WARN_ANNOYING);
  if(c_flags[16]&USEDFLAG) no_inline_peephole=1;
  if(c_flags[17]&USEDFLAG) final=1;
  if(!(c_flags[8]&USEDFLAG)) c_flags_val[8].l=10; /* max. Fehlerzahl */
  if(c_flags[22]&USEDFLAG) c_flags[7]|=USEDFLAG;   /*  iso=ansi */
  if(c_flags[7]&USEDFLAG) error(209);
  if(c_flags[0]&USEDFLAG) optflags=c_flags_val[0].l;
  if(optflags&16384) cross_module=1;
  if(c_flags[11]&USEDFLAG) maxoptpasses=c_flags_val[11].l;
  if(c_flags[12]&USEDFLAG) inline_size=c_flags_val[12].l;
  if(c_flags[21]&USEDFLAG) fp_assoc=1;
  if(c_flags[25]&USEDFLAG) unroll_size=c_flags_val[25].l;
  if(c_flags[23]&USEDFLAG) noaliasopt=1;
  if(c_flags[27]&USEDFLAG) optspeed=1;
  if(c_flags[28]&USEDFLAG) optsize=1;
  if(c_flags[29]&USEDFLAG) unroll_all=1;
  if(c_flags[30]&USEDFLAG) stack_check=1;  
  if(c_flags[31]&USEDFLAG) inline_depth=c_flags_val[31].l;
  if(c_flags[32]&USEDFLAG) debug_info=1;
  if(c_flags[33]&USEDFLAG) c99=1;
  if(c_flags[60]&USEDFLAG) c99=0;
  if(c_flags[34]&USEDFLAG) {wpo=1;no_emit=1;}
  if(c_flags[36]&USEDFLAG) {noitra=1;}
  if(c_flags[37]&USEDFLAG) {
		misracheck=1;
		if ((misraversion==1998) && (c_flags_val[37].l == 2004)) error(328,c_flags_val[37].l,"-misra","");
		if ((misraversion==2004) && (c_flags_val[37].l == 1998)) error(328,c_flags_val[37].l,"-misra","");
		misraversion=c_flags_val[37].l;

		if (!((misraversion==2004) || (misraversion==1998))) error(328,misraversion,"-misra","");
		if (misraversion==1998) {
			int misra_set_iterator;
			for (misra_set_iterator = 0; misra_set_iterator < MISRA_98_RULE_NUMBER; misra_set_iterator++ ) {
				if (misra_98_warn_flag[misra_set_iterator] != -1) misra_98_warn_flag[misra_set_iterator] = 1;
			}
		} else {
			int m1, m2;
			for (m1 = 0; m1 < MISRA_04_CHAPTER; m1++) {
				for (m2 = 0; m2 < MISRA_04_MAX_RULE_IN_CHAPTER; m2++) {
					if (misra_04_warn_flag[m1][m2] != -1) misra_04_warn_flag[m1][m2] = 1;
				}
			}
		}
	}
  if(c_flags[38]&USEDFLAG) {coloring=c_flags_val[38].l;}
  if(c_flags[39]&USEDFLAG) {dmalloc=1;}
  if(c_flags[40]&USEDFLAG) {disable=c_flags_val[40].l;}
  if(c_flags[41]&USEDFLAG) {softfloat=1;}
  if(c_flags[45]&USEDFLAG) {ecpp=1;}
  if(c_flags[46]&USEDFLAG) {short_push=1;}
  if(c_flags[47]&USEDFLAG) {default_unsigned=1;}
  if(c_flags[48]&USEDFLAG) {opencl=1;}
  {
    size_t hs=1000;
    if(c_flags[53]&USEDFLAG) hs=c_flags_val[53].l;
    if(hs!=0) hash_ext=new_hashtable(hs);
  }


  if(wpo){
    cross_module=1;
    optflags=-1;
  }
  if(optsize){
    if(!(c_flags[25]&USEDFLAG)) unroll_size=0;
    clist_copy_pointer=clist_copy_stack;
  }

  if(optspeed){
    clist_copy_pointer=256;
  }

  if(ecpp&&c99){
	  error(333, "c99", "ecpp");
  }
  if(c99){
    ucpp_flags|=CPLUSPLUS_COMMENTS|MACRO_VAARG;
    err_out[67].flags|=ANSIV;
    err_out[67].flags&=~DONTWARN;
    err_out[161].flags|=ANSIV;
    err_out[161].flags&=~DONTWARN;
    err_out[155].flags|=ANSIV;
    err_out[155].flags&=~DONTWARN;
    err_out[156].flags|=ANSIV;
    err_out[156].flags&=~DONTWARN;
  }
  if(ecpp){
#ifndef HAVE_ECPP
	error(334, "EC++");
#endif
    ucpp_flags|=CPLUSPLUS_COMMENTS|MACRO_VAARG;
  }
  if(!cross_module&&files>1) error(1);
  if(files<=0&&!(c_flags[35]&USEDFLAG)) error(6);
  stackalign=l2zm(0L);
  if(!init_cg()) exit(EXIT_FAILURE);

  if(c_flags[55]&USEDFLAG) {clist_copy_stack=c_flags_val[55].l;}
  if(c_flags[56]&USEDFLAG) {clist_copy_static=c_flags_val[56].l;}
  if(c_flags[57]&USEDFLAG) {clist_copy_pointer=c_flags_val[57].l;}
  if(c_flags[58]&USEDFLAG) {inline_memcpy_sz=c_flags_val[58].l;}
  if(c_flags[61]&USEDFLAG) {force_statics=1;}
  if(c_flags[62]&USEDFLAG) {prefer_statics=1;}
  if(c_flags[63]&USEDFLAG) {range_opt=1;}
  if(c_flags[64]&USEDFLAG) {merge_strings=1;}
  if(c_flags[65]&USEDFLAG) {sec_per_obj=1;}
  if(c_flags[66]&USEDFLAG) {no_eff_ics=1;}
  if(c_flags[67]&USEDFLAG) {early_eff_ics=1;}
  if(c_flags[68]&USEDFLAG) {mask_opt=1;}


  if(!(optflags&2)){
    for(i=1;i<=MAXR;i++){
      sregsa[i]=regsa[i];
      if(regsa[i]==REGSA_TEMPS) regsa[i]=0;
    }
  }
  if(zmeqto(stackalign,l2zm(0L)))
    stackalign=maxalign;
  for(i=0;i<=MAX_TYPE;i++)
    if(zmeqto(align[i],l2zm(0L)))
      align[i]=l2zm(1L);
  for(i=0;i<EMIT_BUF_DEPTH;i++)
    emit_buffer[i]=mymalloc(EMIT_BUF_LEN);
  emit_p=emit_buffer[0];
  /*FIXME: multiple-ccs don't work */
  if(c_flags[24]&USEDFLAG) multiple_ccs=0;
  if(!(c_flags[5]&USEDFLAG)){
    if(c_flags[1]&USEDFLAG){
      out=open_out(c_flags_val[1].p,0);
    }else{
      if(wpo)
	out=open_out(inname,"o");
      else
	out=open_out(inname,"asm");
    }
    if(!out){
      exit(EXIT_FAILURE);
    }
  }
  if(wpo){
    wpo_key=MAGIC_WPO;
    fprintf(out,"%cVBCC",0);
  }
  if(debug_info) init_db(out);
  if(c_flags[2]&USEDFLAG) ic1=open_out(inname,"ic1");
  if(c_flags[3]&USEDFLAG) ic2=open_out(inname,"ic2");
  c99_compliant=0;
  init_cpp();
  if(c_flags[35]&USEDFLAG){
    /* we have a command file */
    cmdfile=fopen(c_flags_val[35].p,"r");
    if(!cmdfile) error(7,c_flags_val[35].p);
  }
  for(i=1;cmdfile||i<argc;i++){
    FILE *in;
    int first_byte;
    if(i<argc){
      if(!fname[i]) continue;
      inname=argv[i];
    }else{
      static char nbuf[1024];
      if(!fgets(nbuf,1023,cmdfile)) break;
      inname=nbuf;
      while(isspace((unsigned char)*inname)) inname++;
      if(*inname=='\"') inname++;
      if(inname[strlen(inname)-1]=='\n') inname[strlen(inname)-1]=0;
      if(inname[strlen(inname)-1]=='\"') inname[strlen(inname)-1]=0;
      if(!*inname) break;
    }
    if(DEBUG&1) printf("starting translation-unit <%s>\n",inname);
    in=fopen(inname,"r");
    if(!in) {error(7,inname);}
    misratok=0;
    first_byte=fgetc(in);
    if(first_byte==0){
      input_wpo=in;
      if(fgetc(in)!='V') error(300);
      if(fgetc(in)!='B') error(300);
      if(fgetc(in)!='C') error(300);
      if(fgetc(in)!='C') error(300);
      wpo_key=MAGIC_WPO;
    }else{
      ungetc(first_byte,in);
      input_wpo=0;
    }
    if(c_flags[50]&USEDFLAG){
      char *p;
      depout=open_out(inname,"dep");
      /* nicht super schoen (besser letzten Punkt statt ersten), aber kurz.. */
      if(c_flags[59]&USEDFLAG){
	fprintf(depout,"%s: %s",c_flags_val[59].p,inname);
      }else{
	for(p=inname;*p&&*p!='.';p++) fprintf(depout,"%c",*p);
	fprintf(depout,".o: %s",inname);
      }
    }
    if(c_flags[18]&USEDFLAG) ppout=open_out(inname,"i");
    if(!input_wpo){
      int mcmerk=misracheck;
      misracheck=0;
      init_tables(0);
      init_include_path(0);
      set_init_filename(inname,1);
      init_lexer_state(&ls);
      init_lexer_mode(&ls);
      ls.flags=ucpp_flags;
      ls.input=in;
      for(j=1;j<argc;j++){
	if(argv[j][0]=='-'&&argv[j][1]=='I')
	  add_incpath(&argv[j][2]);
	if(argv[j][0]=='-'&&argv[j][1]=='D')
	  define_macro(&ls,&argv[j][2]);      
      }
      if(target_macros){
	char **m=target_macros;
	while(*m)
	  define_macro(&ls,*m++);
      }
      define_macro(&ls,"__VBCC__");
      define_macro(&ls,"__entry=__vattr(\"entry\")");
      define_macro(&ls,"__str(x)=#x");
      define_macro(&ls,"__asm(x)=do{static void inline_assembly()=x;inline_assembly();}while(0)");
      define_macro(&ls,"__regsused(x)=__vattr(\"regused(\"x\")\")");
      define_macro(&ls,"__varsused(x)=__vattr(\"varused(\"x\")\")");
      define_macro(&ls,"__varsmodified(x)=__vattr(\"varchanged(\"x\")\")");
      define_macro(&ls,"__noreturn=__vattr(\"noreturn()\")");
      define_macro(&ls,"__alwaysreturn=__vattr(\"alwaysreturn()\")");
      define_macro(&ls,"__nosidefx=__vattr(\"nosidefx()\")");
      define_macro(&ls,"__stack(x)=__vattr(__str(stack1(x)))");
      define_macro(&ls,"__stack2(x)=__vattr(__str(stack2(x)))");
      define_macro(&ls,"__noinline=__vattr(\"noinline()\")");
      if(c99)
	define_macro(&ls,"__STDC_VERSION__=199901L");
      if(optspeed)
	define_macro(&ls,"__OPTSPEED__");
      if(optsize)
	define_macro(&ls,"__OPTSIZE__");
      misracheck=mcmerk;
      enter_file(&ls,ls.flags);
    }
    filename=current_filename;
    switch_count=0;break_label=0;
    line=0;eof=0;
    next_token();
    killsp();
    nesting=-1;enter_block();
    translation_unit();
    fclose(in); /*FIXME: do I have to close??*/   
    if((c_flags[18]&USEDFLAG)&&ppout) fclose(ppout);
    if((c_flags[50]&USEDFLAG)&&depout){fprintf(depout,"\n");fclose(depout);}
    if(!input_wpo)
      free_lexer_state(&ls);
  }
  if(wpo)
    raus();
  if(!cross_module){
    ierror(0);
  }else{
    tunit *t;
    Var *v,*sf;
#if HAVE_OSEK
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* removed */
/* 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(DEBUG&1) printf("first optimizing\n");
    for(v=first_ext;v;v=v->next){
      if(ISFUNC(v->vtyp->flags)&&(v->flags&DEFINED)&&(!v->vattr||!strstr(v->vattr,"taskprio("))){
	do_function(v);
      }      
    }
    for(t=first_tunit;t;t=t->next){
      for(v=t->statics;v;v=v->next){
	if(ISFUNC(v->vtyp->flags)&&(v->flags&DEFINED)){
	  do_function(v);
	}
      }
    }
    if(DEBUG&1) printf("determining used objects\n");
    for(v=first_ext;v;v=v->next){
      if((v->flags&(DEFINED|TENTATIVE))&&(v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC){
	if(!final||!strcmp(v->identifier,"main")||(v->vattr&&strstr(v->vattr,"entry"))){
#ifndef NO_OPTIMIZER
	  used_objects(v);
#endif
	  if(ISFUNC(v->vtyp->flags)) do_function(v);
	}
      }
    }
    if(!(c_flags[5]&USEDFLAG)){
      if(DEBUG&1) printf("generating external functions:\n");
      for(v=first_ext;v;v=v->next){
	if(ISFUNC(v->vtyp->flags)&&(v->flags&(REFERENCED|DEFINED))==(REFERENCED|DEFINED)){
	  gen_function(out,v,1);
	}
      }
      if(DEBUG&1024) printf("generating static functions\n");
      i=0;
      for(t=first_tunit;t;t=t->next){
	if(DEBUG&1) printf("translation-unit %d:\n",++i);
	if(DEBUG&1) printf("generating statics:\n");
	for(v=t->statics;v;v=v->next){
	  if(DEBUG&1) printf(" %s\n",v->identifier);
	  if(ISFUNC(v->vtyp->flags)&&(v->flags&(REFERENCED|DEFINED))==(REFERENCED|DEFINED)){
	    gen_function(out,v,1);
	  }
	}
      }
      
      if(DEBUG&1) printf("generating vars:\n");
      gen_vars(first_ext);
      for(t=first_tunit;t;t=t->next)
	gen_vars(t->statics);
      for(v=first_ext;v;v=v->next){
	if(ISFUNC(v->vtyp->flags)&&(v->flags&DEFINED))
	  gen_vars(v->fi->vars);
      }
      for(t=first_tunit;t;t=t->next){
	for(v=t->statics;v;v=v->next){
	  if(ISFUNC(v->vtyp->flags)&&(v->flags&DEFINED))
	    gen_vars(v->fi->vars);
	}
      }
    }
  }
  raus();
}
int mcmp(const char *s1,const char *s2)
/*  Einfachere strcmp-Variante.     */
{
  char c;
  do{
    c=*s1++;
    if(c!=*s2++) return(1);
  }while(c);
  return 0;
}
int is_keyword(char *p)
{
  char *n=p+1;
  switch(*p){
  case 'a':
    if(!mcmp(n,"uto")) return 1;
    return 0;
  case 'b': 
    if(ecpp&&!mcmp(n,"ool")) return 1;
    if(!mcmp(n,"reak")) return 1;
    return 0;
  case 'c': 
    if(!mcmp(n,"ase")) return 1;
    if(ecpp&&!mcmp(n,"atch")) return 1;
    if(!mcmp(n,"har")) return 1;
    if(ecpp&&!mcmp(n,"lass")) return 1;
    if(!mcmp(n,"onst")) return 1;
    if(ecpp&&!mcmp(n,"ons_cast")) return 1;
    if(!mcmp(n,"ontinue")) return 1;
    return 0;
  case 'd': 
    if(!mcmp(n,"efault")) return 1;
    if(ecpp&&!mcmp(n,"elete")) return 1;
    if(!mcmp(n,"o")) return 1;
    if(!mcmp(n,"ouble")) return 1;
    if(ecpp&&!mcmp(n,"ynamic_cast")) return 1;
    return 0;
  case 'e': 
    if(!mcmp(n,"lse")) return 1;
    if(!mcmp(n,"num")) return 1;
    if(ecpp&&!mcmp(n,"xplicit")) return 1;
    if(ecpp&&!mcmp(n,"xport")) return 1;
    if(!mcmp(n,"xtern")) return 1;
    return 0;
  case 'f': 
    if(ecpp&&!mcmp(n,"alse")) return 1;
    if(!mcmp(n,"loat")) return 1;
    if(!mcmp(n,"or")) return 1;
    if(ecpp&&!mcmp(n,"riend")) return 1;
    return 0;
  case 'g': 
    if(!mcmp(n,"oto")) return 1;
    return 0;
  case 'i':
    if(!mcmp(n,"f")) return 1;
    if(c99&&!mcmp(n,"nline")) return 1;
    if(!mcmp(n,"nt")) return 1;
    return 0;
  case 'l':
    if(!mcmp(n,"ong")) return 1;
    return 0;
  case 'm': 
    if(ecpp&&!mcmp(n,"utable")) return 1;
    return 0;
  case 'n': 
    if(ecpp&&!mcmp(n,"amespace")) return 1;
    if(ecpp&&!mcmp(n,"ew")) return 1;
    return 0;
  case 'o': 
    if(ecpp&&!mcmp(n,"perator")) return 1;
    return 0;
  case 'p': 
    if(ecpp&&!mcmp(n,"rivate")) return 1;
    if(ecpp&&!mcmp(n,"rotected")) return 1;
    if(ecpp&&!mcmp(n,"ublic")) return 1;
    return 0;
  case 'r': 
    if(!mcmp(n,"egister")) return 1;
    if(ecpp&&!mcmp(n,"einterpret_cast")) return 1;
    if(c99&&!mcmp(n,"estrict")) return 1;
    if(!mcmp(n,"eturn")) return 1;
    return 0;
  case 's':
    if(!mcmp(n,"hort")) return 1;
    if(!mcmp(n,"igned")) return 1;
    if(!mcmp(n,"izeof")) return 1;
    if(!mcmp(n,"tatic")) return 1;
    if(ecpp&&!mcmp(n,"tatic_cast")) return 1;
    if(!mcmp(n,"truct")) return 1;
    if(!mcmp(n,"witch")) return 1;
    return 0;
  case 't':
    if(ecpp&&!mcmp(n,"emplate")) return 1;
   /* if(ecpp&&!mcmp(n,"his")) return 1;*/
    if(ecpp&&!mcmp(n,"hrow")) return 1;
    if(ecpp&&!mcmp(n,"rue")) return 1;
    if(ecpp&&!mcmp(n,"ry")) return 1;
    if(!mcmp(n,"ypedef")) return 1;
    if(ecpp&&!mcmp(n,"ypeid")) return 1;
    if(ecpp&&!mcmp(n,"ypename")) return 1;
    return 0;
  case 'u': 
    if(!mcmp(n,"nion")) return 1;
    if(!mcmp(n,"nsigned")) return 1;
    if(ecpp&&!mcmp(n,"sing")) return 1;
    return 0;
  case 'v': 
    if(ecpp&&!mcmp(n,"irtual")) return 1;
    if(!mcmp(n,"oid")) return 1;
    if(!mcmp(n,"olatile")) return 1;
    return 0;
  case 'w':
    if(ecpp&&!mcmp(n,"char_t")) return 1;
    if(!mcmp(n,"hile")) return 1;
    return 0;
  case '_': 
    if(c99&&!mcmp(n,"Bool")) return 1;
    if(c99&&!mcmp(n,"Complex")) return 1;
    if(c99&&!mcmp(n,"Imaginary")) return 1;
  default:
    return 0;
  }
}
void cpbez(char *m,int check_keyword)
/*  Kopiert den naechsten Bezeichner von s nach m. Wenn check_keyord!=0 */
/*  wird eine Fehlermeldung ausgegeben, falls das Ergebnis ein          */
/*  reserviertes Keyword von C ist.                                     */
{
  if(ctok->type!=NAME){
    *m=0;
    return;
  }
  if(strlen(ctok->name)>=MAXI){
    error(206,MAXI-1);
    strncpy(m,ctok->name,MAXI-1);
    m[MAXI-1]=0;
  }else{
    strcpy(m,ctok->name);
  }
  if(check_keyword&&is_keyword(m))
    error(216,m);
}
void cpnum(char *m)
/* kopiert die naechste int-Zahl von s nach m   */
/* muss noch erheblich erweiter werden          */
{
  if(ctok->type!=NUMBER){
    *m=0;
    return;
  }
  strcpy(m,ctok->name);
}
void copy_token(token *d,token *s)
{
  size_t l;
  *d=*s;
  if(S_TOKEN(s->type)){
    l=strlen(s->name)+1;
    d->name=mymalloc(l);
    memcpy(d->name,s->name,l);
  }else
    d->name=0;
}
static token back_token;
static int have_back_token;
void push_token(token *t)
{
  static char back_name[MAXI+1];
  if(have_back_token) ierror(0);
  back_token=*t;
  if(S_TOKEN(t->type)){
    strcpy(back_name,t->name);
    back_token.name=back_name;
  }else
    back_token.name=0;
  have_back_token=1;
  ctok=&back_token;
}
void next_token(void)
{
  if(eof){
    if(!endok)
      raus();
    else
      return;
  }
  if(input_wpo){
    int c;
    static token wpo_tok;
    static size_t sz;
    char *p;size_t cs;
  
    if(have_back_token){
      have_back_token=0;
      ctok=&wpo_tok;
      return;
    }
    ctok=&wpo_tok;
    c=fgetc(input_wpo);
    if(c==EOF){
      eof=1;
      return;
    }else
      c^=wpo_key++;
    wpo_tok.type=(unsigned char)c;
    /*printf("wpoget: %d (%s)\n",ctok->type,operators_name[ctok->type]);*/
    if(S_TOKEN(wpo_tok.type)){
      p=wpo_tok.name;
      cs=0;
      do{
	if(cs>=sz){
	  sz+=1000;
	  wpo_tok.name=myrealloc(wpo_tok.name,sz);
	  p=wpo_tok.name+cs;
	}
	c=fgetc(input_wpo);
	if(c!=EOF){
	  c^=wpo_key++;
	  *p++=c;
	  cs++;
	}else
	  eof=1;
      }while(((unsigned char)c)!=0&&c!=EOF);
      *p=0;
      /*printf("name=%s\n",ctok->name);*/
    }
    return;
  }
  if(have_back_token){
    have_back_token=0;
    if(S_TOKEN(ctok->type)&&!ctok->name)
      ierror(0);
  }else{
    static int last_line=1,last_token=NONE;
    static char *last_fname;static size_t last_size;
    eof=lex(&ls);
    if(ctok&&S_TOKEN(ls.ctok->type)&&!ls.ctok->name)
      ierror(0);
    if(wpo){
      fprintf(out,"%c",ls.ctok->type^wpo_key++);
      if(S_TOKEN(ls.ctok->type)){
	char *p=ls.ctok->name;
	while(*p){
	  fprintf(out,"%c",*p^wpo_key++);
	  p++;
	}
	fprintf(out,"%c",0^wpo_key++);
      }
    }
    if((c_flags[18]&USEDFLAG)&&ppout&&!input_wpo){
      if(!last_fname){
	last_fname=mymalloc(1);
	*last_fname=0;
      }
      if(strcmp(last_fname,current_filename)){
	fprintf(ppout,"\n#line %d \"%s\"\n",(int)ls.ctok->line,current_filename);
	last_line=ls.ctok->line;
	if(strlen(current_filename)>=last_size)
	  last_fname=myrealloc(last_fname,strlen(current_filename)+1);
	strcpy(last_fname,current_filename);
      }else{
	for(;last_line<ls.ctok->line;last_line++)
	  fprintf(ppout,"\n");
      }
      if(S_TOKEN(ls.ctok->type)){
	if(ls.ctok->type==PRAGMA)
	  fprintf(ppout,"#pragma");
	fprintf(ppout," %s",ls.ctok->name);
      }else
	fprintf(ppout," %s",operators_name[ls.ctok->type]);
      last_token=ls.ctok->type;
    }
  }
  ctok=ls.ctok;
  line=ctok->line;
  if(misracheck&&ctok->type!=PRAGMA&&ctok->type!=NONE&&ctok->type!=NEWLINE&&ctok->type!=COMMENT)
    misratok=1;
  /*FIXME: do not store multiple */
  if(filename!=current_filename&&strcmp(filename,current_filename)){
    filename=mymalloc(strlen(current_filename)+1);
    strcpy(filename,current_filename);
  }
  /*filename=current_filename;*/
  if(DEBUG&2) printf("current token (type %d): %s\n",(int)ctok->type,ucpp_token_name(ctok));
}
char *pragma_cpbez(char *buff,char *s);
/* calculate fi entries (regs_modifed,uses,changes,flags etc.) from
   attributes */
void fi_from_attr(Var *v)
{
  char *attr;
  attr=v->vattr;
  if(!attr) return;
  while(attr=strstr(attr,"readmem(")){
    int f;
    attr+=8;
    if(sscanf(attr,"%d",&f)!=1) ierror(0);
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=ALL_USES;
    v->fi->use_cnt++;
    v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(varlist));
    v->fi->use_list[v->fi->use_cnt-1].v=0;
    v->fi->use_list[v->fi->use_cnt-1].flags=f;
  }
  attr=v->vattr;
  while(attr=strstr(attr,"writemem(")){
    int f;
    attr+=9;
    if(sscanf(attr,"%d",&f)!=1) ierror(0);
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=ALL_MODS;
    v->fi->change_cnt++;
    v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(varlist));
    v->fi->change_list[v->fi->change_cnt-1].v=0;
    v->fi->change_list[v->fi->change_cnt-1].flags=f;
  }
  attr=v->vattr;
  while(attr=strstr(attr,"varused(")){
    Var *n;
    attr+=8;
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=ALL_USES;
    while(1){
      while(isspace((unsigned char)*attr)) attr++;
      if(*attr==')') break;
      attr=pragma_cpbez(buff,attr);
      if(buff[0]==0){
	error(76);
	break;
      }
      n=find_ext_var(buff);
      if(!n){
	error(82,buff);
	break;
      }
      v->fi->use_cnt++;
      v->fi->use_list=myrealloc(v->fi->use_list,v->fi->use_cnt*sizeof(varlist));
      v->fi->use_list[v->fi->use_cnt-1].v=n;
      v->fi->use_list[v->fi->use_cnt-1].flags=n->vtyp->flags;
      while(isspace((unsigned char)*attr)) attr++;
      if(*attr==','||*attr=='/') attr++;
    }
  }
  attr=v->vattr;
  while(attr=strstr(attr,"varchanged(")){
    Var *n;
    attr+=11;
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=ALL_MODS;
    while(1){
      while(isspace((unsigned char)*attr)) attr++;
      if(*attr==')') break;
      attr=pragma_cpbez(buff,attr);
      if(buff[0]==0){
	error(76);
	break;
      }
      n=find_ext_var(buff);
      if(!n){
	error(82,buff);
	break;
      }
      v->fi->change_cnt++;
      v->fi->change_list=myrealloc(v->fi->change_list,v->fi->change_cnt*sizeof(varlist));
      v->fi->change_list[v->fi->change_cnt-1].v=n;
      v->fi->change_list[v->fi->change_cnt-1].flags=n->vtyp->flags;
      while(isspace((unsigned char)*attr)) attr++;
      if(*attr==','||*attr=='/') attr++;
    }
  }
  attr=v->vattr;
  while(attr=strstr(attr,"regused(")){
    int r,i;
    static char rname[MAXI];
    attr+=8;
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=ALL_REGS;
    while(1){
      while(isspace((unsigned char)*attr)) attr++;
      for(i=0;i<MAXI-1&&*attr&&!isspace((unsigned char)*attr)&&*attr!=','&&*attr!=')'&&*attr!='/';i++)
	rname[i]=*attr++;
      rname[i]=0;
      for(r=1;r<=MAXR;r++){
	if(!reg_pair(r,&rp)&&!strcmp(rname,regnames[r])){
	  BSET(v->fi->regs_modified,r);
	  while(isspace((unsigned char)*attr)) attr++;
	  if(*attr==','||*attr=='/') attr++;
	  break;
	}
      }
      if(r>MAXR){
	if(rname[0]) error(220,rname);
	break;
      }
    }
  }
  attr=v->vattr;
  while(attr=strstr(attr,"stack1(")){
    unsigned long sz;
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=ALL_STACK;
    attr+=7;
    if(sscanf(attr,"%lu",&sz)!=1) ierror(0); /*FIXME*/
    v->fi->stack1=ul2zum(sz);
  }
  attr=v->vattr;
  while(attr=strstr(attr,"stack2(")){
    unsigned long sz;
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=ALL_STACK;
    attr+=7;
    if(sscanf(attr,"%lu",&sz)!=1) ierror(0); /*FIXME*/
    v->fi->stack2=ul2zum(sz);
  }  
  if(strstr(v->vattr,"noreturn()")){
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=NEVER_RETURNS;
  }
  if(strstr(v->vattr,"alwaysreturn()")){
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=ALWAYS_RETURNS;
  }  
  if(strstr(v->vattr,"nosidefx()")){
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=NOSIDEFX;
  }
  if(strstr(v->vattr,"noinline()")){
    if(!v->fi) v->fi=new_fi();
    v->fi->flags|=NO_INLINE;
  }
}
#define pragma_killsp() while(isspace((unsigned char)*s)) s++;
char *pragma_cpbez(char *buff,char *s)
{
  int cnt=0;
  if(*s=='_'||isalpha((unsigned char)*s)){
    *buff++=*s++;
    cnt++;
    while(cnt<MAXI-1&&(*s=='_'||isalnum((unsigned char)*s))){
      *buff++=*s++;
      cnt++;
    }
  }
  *buff++=0;
  return s;
}
#define WARNSTACKSIZE 128
static int widx,warn_num[WARNSTACKSIZE],warn_flags[WARNSTACKSIZE];
#define PACKSTACKSIZE 128
static int pidx,pack[PACKSTACKSIZE];
void do_pragma(char *s)
{
  error(163);
  pragma_killsp();
  if(!strncmp("opt",s,3)){
    s+=3;pragma_killsp();
    c_flags_val[0].l=optflags=atol(s);
    if(DEBUG&1) printf("#pragma opt %ld\n",c_flags_val[0].l);
  }else if(!strncmp("dontwarn",s,8)){
    int i;
    s+=8;pragma_killsp();
    if(widx>=WARNSTACKSIZE) ierror(0);
    if(sscanf(s,"%d",&i)==1){
      if(i>=err_num) error(159,i);
      warn_num[widx]=i;
      warn_flags[widx]=err_out[i].flags;
      widx++;
      err_out[i].flags|=DONTWARN;
    }
  }else if(!strncmp("warn",s,4)){
    int i;
    s+=4;pragma_killsp();
    if(widx>=WARNSTACKSIZE) ierror(0);
    if(sscanf(s,"%d",&i)==1){
      if(i>=err_num) error(159,i);
      warn_num[widx]=i;
      warn_flags[widx]=err_out[i].flags;
      widx++;
      err_out[i].flags&=~DONTWARN;
    }
  }else if(!strncmp("popwarn",s,7)){
    if(widx<=0) error(303);
    widx--;
    err_out[warn_num[widx]].flags=warn_flags[widx];
  }else if(!strncmp("begin_header",s,12)){
    header_cnt++;
  }else if(!strncmp("end_header",s,10)){
    header_cnt--;
  }else if(!strncmp("pfi",s,3)){
    Var *v;
    s+=3;pragma_killsp();
    pragma_cpbez(buff,s);
    if(DEBUG&1) printf("print function_info %s\n",buff);
    v=find_var(buff,0);
    if(v&&v->fi) print_fi(stdout,v->fi);
  }else if(!strncmp("finfo",s,5)){
    Var *v;
    s+=5;pragma_killsp();
    pragma_cpbez(buff,s);
    if(DEBUG&1) printf("new function_info %s\n",buff);
    v=find_var(buff,0);
    if(v){
      if(!v->fi) v->fi=new_fi();
      current_fi=v->fi;
    }
  }else if(!strncmp("fi_flags",s,8)){
    unsigned long flags;
    s+=8;pragma_killsp();
    sscanf(s,"%lu",&flags);
    if(DEBUG&1) printf("fi_flags %lu\n",flags);
    if(current_fi) current_fi->flags=flags;
  }else if(!strncmp("fi_uses",s,7)){
    int t;Var *v;
    s+=7;pragma_killsp();
    s=pragma_cpbez(buff,s);
    t=nesting;nesting=0;
    v=find_var(buff,0);
    nesting=t;
    sscanf(s,"%d",&t);
    if(DEBUG&1) printf("new fi_use %s,%d\n",buff,t);
    if(current_fi){
      current_fi->use_cnt++;
      current_fi->use_list=myrealloc(current_fi->use_list,current_fi->use_cnt*sizeof(varlist));
      current_fi->use_list[current_fi->use_cnt-1].v=v;
      current_fi->use_list[current_fi->use_cnt-1].flags=t;
    }
  }else if(!strncmp("fi_changes",s,10)){
    int t;Var *v;
    s+=10;pragma_killsp();
    s=pragma_cpbez(buff,s);
    t=nesting;nesting=0;
    v=find_var(buff,0);
    nesting=t;
    sscanf(s,"%d",&t);
    if(DEBUG&1) printf("new fi_change %s,%d\n",buff,t);
    if(current_fi){
      current_fi->change_cnt++;
      current_fi->change_list=myrealloc(current_fi->change_list,current_fi->change_cnt*sizeof(varlist));
      current_fi->change_list[current_fi->change_cnt-1].v=v;
      current_fi->change_list[current_fi->change_cnt-1].flags=t;
    }
  }else if(!strncmp("fi_calls",s,8)){
    int t;Var *v;
    s+=8;pragma_killsp();
    s=pragma_cpbez(buff,s);
    t=nesting;nesting=0;
    v=find_var(buff,0);
    nesting=t;
    sscanf(s,"%d",&t);
    if(DEBUG&1) printf("new fi_call %s,%d\n",buff,t);
    if(current_fi){
      current_fi->call_cnt++;
      current_fi->call_list=myrealloc(current_fi->call_list,current_fi->call_cnt*sizeof(varlist));
      current_fi->call_list[current_fi->call_cnt-1].v=v;
      current_fi->call_list[current_fi->call_cnt-1].flags=t;
    }
  }else if(!strncmp("fi_regs",s,7)){
    int r;
    s+=7;pragma_killsp();
    pragma_cpbez(buff,s);
    for(r=1;r<=MAXR;r++)
      if(!strcmp(buff,regnames[r])) break;
    if(r<=MAXR&&current_fi)
      BSET(current_fi->regs_modified,r);
  }else if(!strncmp("printflike",s,10)){
    Var *v;
    s+=10;pragma_killsp();
    pragma_cpbez(buff,s);
    if(DEBUG&1) printf("printflike %s\n",buff);
    v=find_var(buff,0);
    if(v){
      v->flags|=PRINTFLIKE;
      if(DEBUG&1) printf("succeeded\n");
    }
  }else if(!strncmp("scanflike",s,9)){
    Var *v;
    s+=9;pragma_killsp();
    pragma_cpbez(buff,s);
    if(DEBUG&1) printf("scanflike %s\n",buff);
    v=find_var(buff,0);
    if(v){
      v->flags|=SCANFLIKE;
      if(DEBUG&1) printf("succeeded\n");
    }
  }else if(!strncmp("only-inline",s,11)){
    s+=11;pragma_killsp();
    if(!strncmp("on",s,2)){
      if(DEBUG&1) printf("only-inline on\n");
      only_inline=1;
    }else{
      if(DEBUG&1) printf("only-inline off\n");
      only_inline=2;
    }
  }else if(!strncmp("pack",s,4)){
    /* packing of structures */
    s+=4;pragma_killsp();
    if(*s=='(') { s++;pragma_killsp();}
    if(!strncmp("push",s,4)){
      if(pidx==PACKSTACKSIZE){
        memmove(pack,pack+1,(PACKSTACKSIZE-1)*sizeof(pack[0]));
        pidx--;
      }
      pack[pidx++]=pack_align;
      s+=4;pragma_killsp();
      if(*s==','){
        s++;pragma_killsp();
        sscanf(s,"%i",&pack_align);
      }
    }else if(!strncmp("pop",s,3)){
      if(pidx>0) pack_align=pack[--pidx];
      else pack_align=0;
    }else if(*s==')')
      pack_align=0;
    else
      sscanf(s,"%i",&pack_align);
#if 0
  }else if(!strncmp("type",s,4)){
    /*  Typ eines Ausdrucks im Klartext ausgeben    */
    np tree;
    s+=4;strcat(s,";");
    tree=expression();
    if(tree&&type_expression(tree)){
      printf("type of %s is:\n",string+7);
      prd(stdout,tree->ntyp);printf("\n");
    }
    if(tree) free_expression(tree);
  }else if(!strncmp("tree",s,4)){
    /*  gibt eine expression aus    */
    np tree;
    s+=4;strcat(s,";");
    tree=expression();
    if(tree&&type_expression(tree)){
      printf("tree of %s is:\n",string+7);
      pre(stdout,tree);printf("\n");
    }
    if(tree) free_expression(tree);
#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 */
#endif
  }else{
#ifdef HAVE_TARGET_PRAGMAS
    handle_pragma(s);
#endif
  }
}
void killsp(void)
/*  Ueberspringt Fuellzeichen                   */
/*  noch einige unschoene Dinge drin            */
{
  /*FIXME: #pragma etc. */
  while(!eof&&(ttWHI(ctok->type)||ctok->type==PRAGMA||(!input_wpo&&!ls.condcomp))){
    if(ctok->type==PRAGMA)
      do_pragma(ctok->name);
    next_token();
  }
}
void enter_block(void)
/*  Setzt Zeiger/Struckturen bei Eintritt in neuen Block    */
{
    if(nesting>=MAXN){error(9,nesting);return;}
    nesting++;
    if(DEBUG&1) printf("enter block %d\n",nesting);
    first_ilist[nesting]=last_ilist[nesting]=0;
    first_sd[nesting]=last_sd[nesting]=0;
    first_si[nesting]=last_si[nesting]=0;
    first_var[nesting]=last_var[nesting]=0;
    if(nesting==1){
        first_llist=last_llist=0;
        first_clist=last_clist=0;
        merk_varf=merk_varl=0;
        merk_ilistf=merk_ilistl=0;
        merk_sif=merk_sil=0;
/*  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.                     */
/*        merk_sdf=merk_sdl=0;*/
        afterlabel=0;
    }
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
#endif
}
void leave_block(void)
/*  Setzt Zeiger/Struckturen bei Verlassen eines Blocks     */
{
  static int inleave;
  int i;
  if(inleave) return;
  inleave=1;
#ifdef HAVE_ECPP
/* removed */
/* removed */
/* removed */
#endif
  for(i=1;i<=MAXR;i++)
    if(regbnesting[i]==nesting) regsbuf[i]=0;
  if(nesting<0){error(10);inleave=0;return;}
  if(DEBUG&1) printf("leave block %d vla=%p\n",nesting,(void *)block_vla[nesting]);
  if(block_vla[nesting]) clearvl();
  if(nesting>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(nesting==1){
    if(cross_module){
      /* anything to do? */
    }else{
      if(merk_varf) 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_varf) free_var(merk_varf);
      merk_varf=0;
      if(merk_sif) free_si(merk_sif);
      merk_sif=0;
      /*  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);*/
      if(merk_ilistf) free_ilist(merk_ilistf);
      merk_ilistf=0;
    }
  }
  if(nesting==0){
    if(/*ecpp||*/cross_module){
      /* don't free struct_declarations in EC++ for now, since they can be */
      /* referenced even when they are not in scope */
      /* anything to do? */
    }else{
      /*  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(first_si[0]) free_si(first_si[0]);
      if(first_ext)
	gen_vars(first_ext);
      if(first_var[0])
	gen_vars(first_var[0]);
      if(first_ext)
	free_var(first_ext);
      if(first_var[0])
	free_var(first_var[0]);
      if(merk_sdf) free_sd(merk_sdf);
      if(first_sd[0]) free_sd(first_sd[0]);
      if(first_ilist[0]) free_ilist(first_ilist[0]);
    }
  }
  nesting--;
  inleave=0;
}
void pra(FILE *f,argument_list *p)
/*  Gibt argument_list umgekehrt auf Bildschirm aus             */
{
    if(p->next){ pra(f,p->next);fprintf(f,",");}
    if(p->arg) pre(f,p->arg);
}
void pre(FILE *f,np p)
/*  Gibt expression auf Bildschirm aus                          */
{
    int c;
    c=p->flags;
    if(p->sidefx) fprintf(f,"/");
    if(p->lvalue) fprintf(f,"|");
    if(c==CALL){fprintf(f,"call-function(");pre(f,p->left);fprintf(f,")(");
                if(p->alist) pra(f,p->alist);
                fprintf(f,")");return;}
    if(c==CAST){fprintf(f,"cast(");pre(f,p->left);
                fprintf(f,"->");prd(f,p->ntyp);
                fprintf(f,")");return;}
    if(c==MEMBER){if(p->identifier) fprintf(f,".%s",p->identifier);return;}
    if(c==IDENTIFIER){if(p->identifier) fprintf(f,"%s",p->identifier);
        fprintf(f,"+");printval(f,&p->val,LONG); return;}
    fprintf(f,"%s(",ename[c]);
    if(p->left) pre(f,p->left);
    if(p->right){
        fprintf(f,",");
        pre(f,p->right);
    }
    fprintf(f,")");
    if(c==CEXPR||c==PCEXPR){fprintf(f,"(value="); printval(f,&p->val,p->ntyp->flags); fprintf(f,")");}
}
static int pp_line;
void do_error(int errn,va_list vl)
/*  Behandelt Ausgaben wie Fehler und Meldungen */
{
  int type,have_stack=0;
    int treat_warning_as_error=0;
    char *errstr="",*txt=filename;
    if(c_flags_val[8].l&&c_flags_val[8].l<=errors)
      return;
    if(errn==-1) errn=158;
    type=err_out[errn].flags;
    treat_warning_as_error=(type&WARNING)&&(c_flags[54]&USEDFLAG);
#ifdef HAVE_MISRA
/* removed */
#endif
    if(type&DONTWARN) return;
    if(type&WARNING) errstr="warning";
    if(type&ERROR) errstr="error";
    if(input_wpo){
      fprintf(stderr,"%s %d: ",errstr,errn);
    }else if((type&NOLINE)/*||((type&PREPROC)&&pp_line<=0)*/){
      fprintf(stderr,"%s %d: ",errstr,errn);
    }else if(type&(INFUNC|INIC)){
      if((type&INIC)&&err_ic&&err_ic->line){
	fprintf(stderr,"%s %d in line %d of \"%s\": ",errstr,errn,err_ic->line,err_ic->file);


      }else{
	fprintf(stderr,"%s %d in function \"%s\": ",errstr,errn,cur_func);
      }
    }else if(!input_wpo){
      int n;
      if(eof){
	fprintf(stderr,">EOF\n");
      }else{
	if(ls.cli!=0) ls.copy_line[ls.cli]=0;
	fprintf(stderr,">%s\n",ls.copy_line);
      }
      if(type&PREPROC){
	      txt=current_filename;
	      n=pp_line;
      }else{
	if(ctok)
	  n=ctok->line;
	else
	  n=-1;
      }
      if(c_flags[20]&USEDFLAG){   /*  strip-path from filename */
	char *p=txt,c;
	while(c=*p++)
	  if(c==':'||c=='/'||c=='\\') txt=p;
      }
      fprintf(stderr,"%s %d in line %d of \"%s\": ",errstr,errn,n,txt);
      have_stack=1; /* we can report the include stack */
    }
    vfprintf(stderr,err_out[errn].text,vl);
    fprintf(stderr,"\n");
    if(have_stack&&(!(c_flags[49]&USEDFLAG))){
      int i;
      stack_context *sc = report_context();
      for(i=0;;i++){
	if(sc[i].line==-1) break;
	fprintf(stderr,"\tincluded from file \"%s\":%ld\n",sc[i].long_name?sc[i].long_name:sc[i].name,sc[i].line);
      }
    }
    if(treat_warning_as_error){fprintf(stderr,"warning %d treated as error [-warnings-as-errors]\n",errn);}
    if(type&ERROR||treat_warning_as_error){
      errors++;
      if(c_flags_val[8].l&&c_flags_val[8].l<=errors&&!(type&NORAUS))
	{fprintf(stderr,"Maximum number of errors reached!\n");raus();}
    }
    if(type&FATAL){fprintf(stderr,"aborting...\n");raus();}
}
void error(int errn,...)
{
  va_list vl;
  va_start(vl,errn);
  do_error(errn,vl);
  va_end(vl);
}
void ucpp_ouch(char *fmt, ...)
{
  ierror(0);
}
void do_ucpp_error(char *fmt,va_list vl)
{
  int i;
  for(i=0;i<err_num;i++){
    if(!strcmp(fmt,err_out[i].text))
      break;
  }
  if(*fmt=='#'){
    /* #error/#warning-directive */
    i=*(fmt+1)=='w'?325:292;
  }
  if(i>=err_num){
    puts(fmt);
    ierror(0);
  }
  do_error(i,vl);
}
void ucpp_error(long line, char *fmt, ...)
{
  va_list ap;
  pp_line=line;
  va_start(ap, fmt);
  do_ucpp_error(fmt,ap);
  va_end(ap);
}
void ucpp_warning(long line, char *fmt, ...)
{
  va_list ap;
  pp_line=line;
  va_start(ap, fmt);
  do_ucpp_error(fmt,ap);
  va_end(ap);
}

void misra(int n,...)
{
  va_list vl;
  if(!misracheck) return;
  va_start(vl,n);
  fprintf(stderr,"MISRA error %d\n",n);
  va_end(vl);
}

void misra_error(int n, int rule, int subrule, int line, ...) {
	va_list vl;
	tmisra_err_out* misr_err;
	char* mis_vers_string;
	char mis_numb_string[100];
	char* rule_text;
	int not_found;
	if (!misracheck) return;
	mis_vers_string = 0;
	va_start(vl,line);

	if (line == 0) line = ctok->line;

	if ((n) && (misraversion==1998)) {
		if (misra_98_warn_flag[n-1] != 1) return; /* TODO: Zhler setzen wenn nur ein paar nicht ausgegeben werden sollen */
		mis_vers_string = mystrdup("1998");
		sprintf(mis_numb_string,"%d",n);
		misr_err = NULL;			
	} else if ((rule) && (misraversion==2004)) {
		if (misra_04_warn_flag[rule-1][subrule-1] != 1) return;/* TODO: Zhler setzen wenn nur ein paar nicht ausgegeben werden sollen */
		mis_vers_string = mystrdup("2004");
		sprintf(mis_numb_string,"Chapter %d, Rule %d",rule,subrule);
		if (subrule) {
  		misr_err = misra_err_out;
	  	not_found = 1;
		  while ( not_found ) {
				if ((misr_err->chapter == rule) && (misr_err->rule == subrule)) {
					not_found = 0;
					break;
				}
				misr_err++;
			}
		}
	}
	if (!mis_vers_string) return;
	if (misr_err) fprintf(stderr,"MISRA(%s) Rule violation (%s) in line <%d>\n%s\n",mis_vers_string,mis_numb_string,line,misr_err->text);
	else fprintf(stderr,"MISRA(%s) Rule violation (%s) in line <%d>: No description found\n",mis_vers_string,mis_numb_string,line);

	if (mis_vers_string) free(mis_vers_string);

	va_end(vl);
}

void misra_neu(int n,int rule,int subrule, int line, ...)
{
  va_list vl;
	int mis_warn = 0;
	misra_error(n,rule,subrule,line);
	return;
	va_start(vl,line);
  va_end(vl);

}

FILE *open_out(char *name,char *ext)
/*  Haengt ext an name an und versucht diese File als output zu oeffnen */
{
  char *s,*p;FILE *f;
  if(ext){
    s=mymalloc(strlen(name)+strlen(ext)+2);
    strcpy(s,name);
    p=s+strlen(s);
    while(p>=s){
      if(*p=='.'){*p=0;break;}
      p--;
    }
    strcat(s,".");
    strcat(s,ext);
  }else
    s=name;
  f=fopen(s,"w");
  if(!f) fprintf(stderr,"Couldn't open <%s> for output!\n",s);
  if(ext) free(s);
  return(f);
}
