blob: 5e102f47c38bf965607cf9d236c5418058ff9e34 [file] [log] [blame]
/* $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);
}