| /* $VER: vbcc (declaration.c) $Revision: 1.90 $ */ |
| |
| #include <string.h> |
| #include <stdio.h> |
| |
| #include "vbcc_cpp.h" |
| #include "vbc.h" |
| |
| static char FILE_[]=__FILE__; |
| |
| #define PLAIN_STORAGE_CLASS 7 |
| #define PARAMETER 8 |
| #define OLDSTYLE 16 |
| |
| void dynamic_init(Var *v,type *t,const_list *cl,zmax of,int noconst); |
| int test_assignment(type *,np); |
| int return_sc,return_reg,has_return,return_inline; |
| char *return_vattr; |
| static int did_return_label; |
| #ifdef HAVE_TARGET_ATTRIBUTES |
| unsigned long return_tattr; |
| #endif |
| zumax return_mask; |
| zmax init_dyn_sz,init_const_sz; |
| int init_dyn_cnt,init_const_cnt; |
| |
| void init_sl(struct_list *sl); |
| |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| |
| extern np gen_libcall(char *,np,type *,np,type *); |
| extern int float_used; |
| extern void optimize(long,Var *); |
| |
| extern type uct; |
| |
| void needs(char *s) |
| { |
| Var *v; |
| if(!(v=find_ext_var(s))||!strcmp(v->identifier,s)){ |
| Var *needs=add_var(s,clone_typ(&uct),EXTERN,0); |
| needs->flags|=(USEDASSOURCE|REFERENCED|NEEDS); |
| } |
| } |
| |
| static void clear_main_ret(void) |
| { |
| if(c99&&!strcmp(cur_func,"main")&&return_typ&&ISSCALAR(return_typ->flags)){ |
| /* in c99, main returns 0 if it falls from back */ |
| IC *new=new_IC(); |
| new->code=SETRETURN; |
| new->q1.val.vmax=l2zm(0L); |
| eval_const(&new->q1.val,MAXINT); |
| insert_const(&new->q1.val,return_typ->flags&NU); |
| new->q1.flags=KONST; |
| new->typf=return_typ->flags; |
| new->q2.val.vmax=szof(return_typ); |
| new->q2.flags=new->z.flags=0; |
| new->z.reg=freturn(return_typ); |
| add_IC(new); |
| } |
| } |
| |
| static char *get_string(void) |
| /* Liest Stringkonstante und liefert Wert als String (malloced) */ |
| { |
| np tree;int l;char *p; |
| const_list *cl; |
| killsp(); |
| if(ctok->type!=T_STRING) {error(74);return 0;} |
| tree=string_expression(); |
| if(!tree||tree->flags!=STRING){ |
| error(229); |
| return 0; |
| } |
| cl=tree->cl;l=0; |
| while(cl){ |
| l++; |
| cl=cl->next; |
| } |
| p=mymalloc(l); |
| cl=tree->cl;l=0; |
| while(cl){ |
| p[l]=CHARBACK(zm2l(zc2zm(cl->other->val.vchar))); |
| l++; |
| cl=cl->next; |
| } |
| if(tree) free_expression(tree); |
| killsp(); |
| return p; |
| } |
| |
| /* checks whether string is a valid vector type */ |
| /* returns the dimension */ |
| static int check_vect(char *s,char *base) |
| { |
| int i=strlen(base),dim; |
| if(strncmp(s,base,i)) return 0; |
| dim=s[i]; |
| if(dim=='2'||dim=='3'||dim=='4'||dim=='8'){ |
| if(s[i+1]==0) |
| return dim-'0'; |
| else |
| return 0; |
| } |
| if(s[i]=='1'&&s[i+1]=='6'&&s[i+2]==0) |
| return 16; |
| return 0; |
| } |
| |
| int settyp(int typnew, int typold) |
| /* Unterroutine fuer declaration_specifiers(). */ |
| { |
| if(DEBUG&2) printf("settyp: new=%d old=%d\n",typnew,typold); |
| if(typold==LONG&&typnew==FLOAT){ error(203); return DOUBLE;} |
| if(typold==LONG&&typnew==DOUBLE) return LDOUBLE; |
| if(c99&&typold==LONG&&typnew==LONG) return LLONG; |
| if(typold==INT&&(typnew==SHORT||typnew==LONG)) return typnew; |
| if(typold!=0&&typnew!=INT){error(47);return(typnew);} |
| if(typold==0&&typnew==INT) return(INT); |
| if(typold==0) return(typnew); |
| if(typold==SHORT||typold==LONG||typold==LLONG) return(typold); |
| error(48); |
| return(typnew); |
| } |
| |
| #define dsc if(storage_class) error(49); if(typ||type_qualifiers) error(50) |
| #define XSIGNED 16384 |
| |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| |
| type *declaration_specifiers(void) |
| /* Erzeugt neuen Typ und gibt Zeiger darauf zurueck, */ |
| /* parst z.B. unsigned int, bla etc. */ |
| { |
| int typ=0,type_qualifiers=0,notdone,storage_class,hard_reg,have_inline; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| char *imerk,sident[MAXI],sbuff[MAXI],*attr=0,*vattr=0; |
| zumax mask=ul2zum(0UL); |
| type *new=new_typ(),*t,*ts; |
| struct_declaration *ssd; |
| struct_list (*sl)[]; |
| size_t slsz; |
| Var *v; |
| int dim; |
| #ifdef HAVE_TARGET_ATTRIBUTES |
| unsigned long tattr=0; |
| #endif |
| storage_class=hard_reg=have_inline=0; |
| do{ |
| killsp();notdone=0; |
| if(ctok->type==NAME){ |
| if(!strcmp("struct",ctok->name)||!strcmp("union",ctok->name)||(ecpp&&!strcmp("class",ctok->name))){ |
| if(!strcmp("struct",ctok->name)) notdone=STRUCT; |
| if(!strcmp("union",ctok->name)) { |
| notdone=UNION; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| next_token(); |
| killsp(); |
| if(ctok->type!=LBRA){ |
| cpbez(sident,1); |
| next_token(); |
| killsp(); |
| ssd=find_struct(sident,0); |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| if(ssd&&ctok->type==LBRA&&find_struct(sident,nesting)&&ssd->count>0) error(13,sident); |
| if(!ssd||((ctok->type==LBRA||ctok->type==SEMIC)&&!find_struct(sident,nesting))){ |
| typ=settyp(notdone,typ); |
| ssd=mymalloc(sizeof(*ssd)); |
| ssd->count=0; |
| new->exact=ssd=add_sd(ssd,notdone); |
| if(!ecpp)add_struct_identifier(sident,ssd); |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| }else{ |
| new->exact=ssd; |
| typ=settyp(new->flags=notdone,typ); |
| } |
| }else{ |
| *sident=0; |
| typ=settyp(notdone,typ); |
| ssd=mymalloc(sizeof(*ssd)); |
| ssd->count=0; |
| new->exact=ssd=add_sd(ssd,notdone); |
| } |
| if(ssd->typ!=notdone) error(230,sident); |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(ctok->type==LBRA){ |
| int bfoffset,bfsize,flex_array=0,cbfo=0; |
| int scount; |
| zmax off=l2zm(0L); |
| next_token(); |
| killsp(); |
| slsz=SLSIZE; |
| imerk=ident; |
| sl=mymalloc(slsz*sizeof(struct_list)); |
| ssd->count=0; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| scount=ssd->count; |
| ts=declaration_specifiers(); |
| while(ctok->type!=RBRA&&ts){ |
| if(flex_array) error(231); |
| ident=sbuff; |
| t=declarator(clone_typ(ts)); |
| killsp(); |
| bfsize=bfoffset=-1; |
| if(ctok->type==T_COLON){ |
| np tree; |
| if((ts->flags&NQ)!=INT) { |
| error(51); |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| } |
| next_token();killsp();tree=assignment_expression(); |
| |
| if(type_expression(tree,0)){ |
| int tsize; |
| if(tree->flags!=CEXPR) error(52); |
| if(!ISINT(tree->ntyp->flags)) error(52); |
| eval_const(&tree->val,tree->ntyp->flags); |
| bfsize=(int)zm2l(vmax); |
| tsize=(int)zm2l(zmmult(sizetab[t->flags&NQ],char_bit)); |
| if(bfsize<0||bfsize>tsize||(bfsize==0&&*ident)){ |
| error(332);bfsize=1; |
| } |
| if(bfsize+cbfo>tsize){ |
| bfoffset=cbfo=0; |
| }else{ |
| bfoffset=cbfo; |
| } |
| if(bfsize!=0) |
| cbfo+=bfsize; |
| else |
| cbfo=0; |
| } |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(tree) free_expression(tree); |
| }else{ |
| if(!ecpp&&*ident==0) error(53); |
| cbfo=0; |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(type_uncomplete(t)){ |
| if(!c99||notdone!=STRUCT||flex_array||(t->flags&NQ)!=ARRAY||type_uncomplete(t->next)){ |
| error(14,sbuff); |
| freetyp(t); |
| break; |
| }else{ |
| flex_array=1; |
| } |
| } |
| if(ISARRAY(t->flags)&&t->dsize){ |
| error(352,sbuff); |
| } |
| if(ISFUNC(t->flags)){ |
| if(!ecpp){ |
| error(15,sbuff); |
| } |
| } |
| if(*ident!=0){ |
| int i=scount; |
| while(--i>=0) |
| if(!strcmp((*sl)[i].identifier,ident)) |
| error(16,ident); |
| } |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| (*sl)[scount].bfoffset=bfoffset; |
| (*sl)[scount].bfsize=bfsize; |
| (*sl)[scount].styp=t; |
| if(!ecpp) (*sl)[scount].identifier=add_identifier(ident,strlen(ident)); |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(pack_align>0&&pack_align<falign(t)) |
| (*sl)[scount].align=pack_align; |
| else |
| (*sl)[scount].align=falign(t); |
| { |
| zmax m,al=(*sl)[scount].align; |
| zmax sz=szof(t); |
| m=off; |
| if((zmeqto(al,l2zm(0L))||zmeqto(sz,l2zm(0L)))&&!flex_array){ |
| if (!ecpp){ |
| error(316,ident); |
| } |
| }else{ |
| off=zmmult(zmdiv(zmadd(off,zmsub(al,l2zm(1L))),al),al); |
| if(!zmeqto(m,off)) error(306,ident); |
| if(!flex_array){ |
| m=zmmult(zmdiv(zmadd(off,zmsub(sz,l2zm(1L))),sz),sz); |
| if(!zmeqto(m,off)) error(307,ident); |
| off=zmadd(off,sz); |
| } |
| } |
| } |
| scount++; |
| if(scount>=slsz-1){ |
| slsz+=SLSIZE; |
| sl=myrealloc(sl,slsz*sizeof(struct_list)); |
| } |
| killsp(); |
| if(ctok->type==COMMA) {next_token();killsp();continue;} |
| if(ctok->type!=SEMIC) error(54); else next_token(); |
| killsp(); |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| if(ctok->type!=RBRA){ |
| if(ts) freetyp(ts); |
| ts=declaration_specifiers();killsp(); |
| } |
| } |
| if(ts) freetyp(ts); |
| ssd->count=scount; |
| if(ssd->count==0) error(55); |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| ident=imerk; |
| add_sl(ssd,sl); |
| free(sl); |
| if(ctok->type!=RBRA) error(56); else next_token(); |
| new->flags=notdone|type_qualifiers; |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| notdone=1; |
| }else if(!strcmp("enum",ctok->name)){ |
| /* enumerations; die Namen werden leider noch ignoriert */ |
| next_token();killsp();notdone=1; |
| if(ctok->type!=LBRA){cpbez(buff,1);next_token();killsp();} |
| if(ctok->type==LBRA){ |
| /* mode: 0=start 1=first was not init 2=first was init 3=more init */ |
| zmax val; Var *v; type *t;int mode=0; |
| val=l2zm(0L); |
| next_token();killsp(); |
| while(ctok->type!=RBRA){ |
| cpbez(sident,1);next_token();killsp(); |
| if(*sident==0) {error(56);break;} |
| t=new_typ(); |
| t->flags=CONST|INT; |
| if(find_var(sident,nesting)) error(17,sident); |
| v=add_var(sident,t,AUTO,0); /* AUTO hier klug? */ |
| if(ctok->type==ASGN){ |
| if(mode==2) mode=3; |
| if(mode==0) mode=2; |
| #ifdef HAVE_MISRA /* MISRA Rule 9.3 checking */ |
| /* removed */ |
| #endif |
| next_token();killsp(); |
| v->clist=initialization(v->vtyp,0,0,0,0,0); |
| val=zi2zm(v->clist->val.vint);killsp(); |
| }else{ |
| if(mode==0) mode=1; |
| #ifdef HAVE_MISRA /* MISRA Rule 9.3 checking */ |
| /* removed */ |
| #endif |
| v->clist=mymalloc(CLS); |
| v->clist->val.vint=zm2zi(val); |
| v->clist->next=v->clist->other=0; |
| v->clist->tree=0; |
| v->clist->idx=l2zm(0L); |
| } |
| vmax=l2zm(1L);val=zmadd(val,vmax); |
| v->vtyp->flags=CONST|ENUM; |
| if(ctok->type!=RBRA&&ctok->type!=COMMA) {error(56);break;} |
| if(ctok->type==COMMA) next_token(); |
| killsp(); |
| if(ctok->type==RBRA) {next_token(); break;} |
| } |
| } |
| killsp(); |
| typ=settyp(INT,typ); |
| }else if(!strcmp("__readsmem",ctok->name)||!strcmp("__writesmem",ctok->name)){ |
| enum {READS,WRITES} op; |
| char *imerk,tbuf[MAXI]; |
| type *tmp; |
| if(!strcmp("__readsmem",ctok->name)) |
| op=READS; |
| else |
| op=WRITES; |
| next_token();killsp(); |
| if(ctok->type==LPAR) next_token(); else error(151); |
| imerk=ident;ident=tbuf; |
| tmp=declarator(declaration_specifiers()); |
| ident=imerk; |
| if(tmp){ |
| if(vattr) |
| vattr=myrealloc(vattr,strlen(vattr)+25); |
| else{ |
| vattr=mymalloc(25); |
| vattr[0]=0; |
| } |
| sprintf(vattr+strlen(vattr),";%s(%d)",op==READS?"readmem":"writemem",tmp->flags); |
| } |
| killsp(); |
| if(ctok->type==RPAR) next_token(); else error(59); |
| killsp(); |
| notdone=1; |
| }else if(!strcmp("void",ctok->name)){ |
| next_token(); |
| typ=settyp(VOID,typ);notdone=1; |
| }else if(!strcmp("char",ctok->name)){ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| #endif |
| next_token(); |
| typ=settyp(CHAR,typ); |
| notdone=1; |
| if(default_unsigned&&!(type_qualifiers&XSIGNED)) |
| type_qualifiers|=UNSIGNED; |
| }else if(!strcmp("short",ctok->name)){ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| next_token(); |
| typ=settyp(SHORT,typ);notdone=1; |
| }else if(!strcmp("int",ctok->name)){ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| next_token(); |
| typ=settyp(INT,typ);notdone=1; |
| }else if(!strcmp("long",ctok->name)){ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| next_token(); |
| typ=settyp(LONG,typ);notdone=1; |
| }else if(!strcmp("float",ctok->name)){ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| next_token(); |
| typ=settyp(FLOAT,typ);notdone=1; |
| }else if(!strcmp("double",ctok->name)){ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| next_token(); |
| typ=settyp(DOUBLE,typ);notdone=1; |
| }else if(!strcmp("const",ctok->name)){ |
| next_token(); |
| if(type_qualifiers&CONST) error(58); |
| type_qualifiers|=CONST;notdone=1; |
| }else if(!strcmp("volatile",ctok->name)){ |
| next_token(); |
| if(type_qualifiers&VOLATILE) error(58); |
| type_qualifiers|=VOLATILE;notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"bool"))){ |
| next_token(); |
| typ=settyp(VECBOOL+dim-1,typ); |
| notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"char"))){ |
| next_token(); |
| typ=settyp(VECCHAR+dim-1,typ); |
| notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"uchar"))){ |
| next_token(); |
| typ=settyp((VECCHAR+dim-1)|UNSIGNED,typ); |
| notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"short"))){ |
| next_token(); |
| typ=settyp(VECSHORT+dim-1,typ); |
| notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"ushort"))){ |
| next_token(); |
| typ=settyp((VECSHORT+dim-1)|UNSIGNED,typ); |
| notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"int"))){ |
| next_token(); |
| typ=settyp(VECINT+dim-1,typ); |
| notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"uint"))){ |
| next_token(); |
| typ=settyp((VECINT+dim-1)|UNSIGNED,typ); |
| notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"long"))){ |
| next_token(); |
| typ=settyp(VECLONG+dim-1,typ); |
| notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"ulong"))){ |
| next_token(); |
| typ=settyp((VECLONG+dim-1)|UNSIGNED,typ); |
| notdone=1; |
| }else if(opencl&&(dim=check_vect(ctok->name,"float"))){ |
| next_token(); |
| typ=settyp(VECFLOAT+dim-1,typ); |
| notdone=1; |
| #if 0 |
| }else if(c99&&!strcmp("restrict",ctok->name)){ |
| next_token(); |
| if(type_qualifiers&RESTRICT) error(58); |
| type_qualifiers|=RESTRICT;notdone=1; |
| #endif |
| }else if(!strcmp("unsigned",ctok->name)){ |
| next_token(); |
| if(type_qualifiers&(XSIGNED|UNSIGNED)) error(58); |
| notdone=1;type_qualifiers|=UNSIGNED; |
| }else if(!strcmp("signed",ctok->name)){ |
| next_token(); |
| if(type_qualifiers&(XSIGNED|UNSIGNED)) error(58); |
| notdone=1;type_qualifiers|=XSIGNED; |
| }else if(!strcmp("auto",ctok->name)){ |
| next_token(); |
| dsc;storage_class=AUTO;notdone=1; |
| }else if(!strcmp("register",ctok->name)){ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| next_token(); |
| dsc;storage_class=REGISTER;notdone=1; |
| }else if(!strcmp("static",ctok->name)){ |
| next_token(); |
| dsc;storage_class=STATIC;notdone=1; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| }else if(!strcmp("extern",ctok->name)){ |
| next_token(); |
| dsc;storage_class=EXTERN;notdone=1; |
| }else if(!strcmp("typedef",ctok->name)){ |
| next_token(); |
| dsc;storage_class=TYPEDEF;notdone=1; |
| }else if(c99&&!strcmp("inline",ctok->name)){ |
| next_token(); |
| have_inline=1;notdone=1; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| }else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__reg",ctok->name)){ |
| char *d; |
| next_token();killsp(); |
| if(ctok->type==LPAR) next_token(); else error(151); |
| killsp(); |
| if(d=get_string()){ |
| for(hard_reg=1;hard_reg<=MAXR;hard_reg++){ |
| if(!strcmp(d,regnames[hard_reg])) break; |
| } |
| if(hard_reg>MAXR){ hard_reg=0;error(220,d);} |
| notdone=1; |
| free(d); |
| } |
| killsp(); |
| if(ctok->type==RPAR) next_token(); else error(59); |
| killsp(); |
| }else if(!strcmp("__mask",ctok->name)){ |
| np tree; |
| next_token();killsp(); |
| if(ctok->type==LPAR) next_token(); else error(151); |
| tree=expression(); |
| if(tree&&type_expression(tree,0)){ |
| if(tree->flags==CEXPR&&ISINT(tree->ntyp->flags)){ |
| eval_const(&tree->val,tree->ntyp->flags); |
| mask=vumax; |
| }else |
| error(18); |
| free_expression(tree); |
| }else |
| error(18); |
| killsp(); |
| if(ctok->type==RPAR) next_token(); else error(59); |
| killsp(); |
| notdone=1; |
| }else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__attr",ctok->name)){ |
| char *d; |
| next_token();killsp(); |
| if(ctok->type==LPAR) next_token(); else error(151); |
| killsp(); |
| if(d=get_string()){ |
| if(!attr){ |
| attr=d; |
| }else{ |
| attr=myrealloc(attr,strlen(attr)+strlen(d)+2); |
| strcat(attr,";"); |
| strcat(attr,d); |
| free(d); |
| } |
| notdone=1; |
| } |
| killsp(); |
| if(ctok->type==RPAR) next_token(); else error(59); |
| killsp(); |
| }else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__vattr",ctok->name)){ |
| char *d; |
| next_token();killsp(); |
| if(ctok->type==LPAR) next_token(); else error(151); |
| killsp(); |
| if(d=get_string()){ |
| if(!vattr){ |
| vattr=d; |
| }else{ |
| vattr=myrealloc(vattr,strlen(vattr)+strlen(d)+2); |
| strcat(vattr,";"); |
| strcat(vattr,d); |
| free(d); |
| } |
| notdone=1; |
| } |
| killsp(); |
| if(ctok->type==RPAR) next_token(); else error(59); |
| killsp(); |
| }else{ |
| #ifdef HAVE_TARGET_ATTRIBUTES |
| int i; |
| for(i=0;g_attr_name[i];i++){ |
| if(!strcmp(g_attr_name[i],ctok->name)){ |
| if(tattr&(1L<<i)) error(227,ctok->name); |
| tattr|=(1L<<i); |
| next_token(); |
| notdone=1;break; |
| } |
| } |
| #endif |
| if(!notdone&&typ==0&&!(type_qualifiers&(XSIGNED|UNSIGNED))){ |
| v=find_var(ctok->name,0); |
| if(v&&v->storage_class==TYPEDEF){ |
| free(new); |
| new=clone_typ(v->vtyp); |
| typ=settyp(new->flags,typ); |
| notdone=1; |
| next_token(); |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| } |
| } |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(DEBUG&2) printf("typ:%d\n",typ); |
| }while(notdone); |
| killsp(); |
| return_sc=storage_class; |
| return_reg=hard_reg; |
| return_vattr=vattr; |
| return_mask=mask; |
| return_inline=have_inline; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| #ifdef HAVE_TARGET_ATTRIBUTES |
| return_tattr=tattr; |
| #endif |
| if(typ==0){ |
| if(storage_class==0&&type_qualifiers==0&&!hard_reg){ |
| free(new); |
| return 0; |
| } |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| typ=INT; |
| } |
| if(type_qualifiers&(XSIGNED|UNSIGNED)) |
| if(!ISINT(typ)) |
| error(58); |
| new->flags=typ|type_qualifiers; |
| new->attr=attr; |
| return new; |
| } |
| |
| type *declarator(type *a) |
| /* Erzeugt einen neuen Typ, auf Basis des Typs a. */ |
| /* a wird hiermit verkettet. */ |
| { |
| type *t; |
| killsp();*ident=0; |
| t=direct_declarator(pointer(a)); |
| if(!a) |
| {if(t) freetyp(t);return 0;} |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| #ifdef HAVE_EXT_TYPES |
| conv_typ(t); |
| #endif |
| return t; |
| } |
| type *pointer(type *a) |
| /* Unterroutine fuer declarator(), behandelt Zeiger auf Typ. */ |
| { |
| type *t;char *attr;int notdone; |
| if(!a) return(0); |
| killsp(); |
| while(ctok->type==STAR){ |
| next_token(); |
| t=new_typ(); |
| t->flags=POINTER_TYPE(a); |
| t->next=a; |
| attr=0; |
| a=t; |
| do{ |
| killsp(); |
| notdone=0; |
| if(ctok->type==NAME&&!strcmp("const",ctok->name)){ |
| a->flags|=CONST; |
| notdone=1; |
| next_token(); |
| }else if(ctok->type==NAME&&!strcmp("volatile",ctok->name)){ |
| a->flags|=VOLATILE; |
| notdone=1; |
| next_token(); |
| }else if(c99&&ctok->type==NAME&&!strcmp("restrict",ctok->name)){ |
| a->flags|=RESTRICT; |
| notdone=1; |
| next_token(); |
| }else if(ctok->type==NAME&&!strcmp("__attr",ctok->name)){ |
| char *d; |
| next_token(); |
| killsp(); |
| if(ctok->type==LPAR) next_token(); else error(151); |
| killsp(); |
| if(d=get_string()){ |
| if(!attr){ |
| attr=d; |
| }else{ |
| attr=myrealloc(attr,strlen(attr)+strlen(d)+2); |
| strcat(attr,";"); |
| strcat(attr,d); |
| free(d); |
| } |
| notdone=1; |
| } |
| killsp(); |
| if(ctok->type==RPAR) next_token(); else error(59); |
| killsp(); |
| } |
| }while(notdone); |
| a->attr=attr; |
| } |
| return a; |
| } |
| type *direct_declarator(type *a) |
| /* Unterroutine zu declarator() */ |
| /* behandelt [],(funkt),(dekl). */ |
| { |
| type *rek=0,*merk,*p,*t=0,*first,*last=0; |
| struct_declaration *fsd; |
| struct_list (*sl)[]; |
| size_t slsz;char *imerk; |
| char fbuff[MAXI]; |
| killsp(); |
| if(ctok->type!=NAME&&ctok->type!=LPAR&&ctok->type!=LBRK) |
| return a; |
| if(ctok->type==NAME){ |
| cpbez(ident,1); |
| next_token(); |
| if(!a) return(0); |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| } |
| else if(ctok->type==LPAR&&a){ |
| /* Rekursion */ |
| token mtok; |
| copy_token(&mtok,ctok); |
| next_token(); killsp(); |
| if(ctok->type!=RPAR&&*ident==0&&!declaration(0)){ |
| merk=a; |
| rek=declarator(a); |
| if(ctok->type!=RPAR) error(59); else next_token(); |
| }else |
| |
| push_token(&mtok); |
| free(mtok.name); |
| } |
| if(!a)return(0); |
| killsp(); |
| while(ctok->type==LBRK||ctok->type==LPAR){ |
| if(ctok->type==LBRK){ |
| next_token(); |
| killsp(); |
| p=new_typ(); |
| p->flags=ARRAY; |
| p->next=0; |
| if(ctok->type==RBRK){ |
| p->size=l2zm(0L); |
| }else{ |
| np tree; |
| tree=expression(); |
| if(!type_expression(tree,0)){ |
| /* error("incorrect constant expression");*/ |
| }else{ |
| if(tree->sidefx&&!c99) error(60); |
| if(tree->flags!=CEXPR||!ISINT(tree->ntyp->flags)){ |
| if(!c99||!ALLOCVLA_INLINEASM) |
| error(19); |
| else{ |
| type *st;IC *new; |
| st=new_typ(); |
| st->flags=HAVE_INT_SIZET?(UNSIGNED|INT):(UNSIGNED|LONG); |
| p->dsize=add_tmp_var(st); |
| gen_IC(tree,0,0); |
| convert(tree,st->flags); |
| new=new_IC(); |
| new->code=ASSIGN; |
| new->typf=st->flags; |
| new->q1=tree->o; |
| new->z.flags=VAR; |
| new->z.v=p->dsize; |
| new->z.val.vmax=l2zm(0L); |
| new->q2.val.vmax=szof(st); |
| add_IC(new); |
| } |
| }else{ |
| eval_constn(tree); |
| p->size=vmax; |
| if(zmleq(p->size,l2zm(0L))) {error(61);p->size=l2zm(1L);} |
| } |
| } |
| free_expression(tree); |
| } |
| if(ctok->type!=RBRK) error(62); else next_token(); |
| if(last){ |
| last->next=p; |
| last=p; |
| }else{ |
| first=last=p; |
| } |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(ctok->type==LPAR){ |
| int komma,firstparm,oldstyle=0; |
| #if 0 /*#ifdef HAVE_REGPARMS*/ |
| treg_handle reg_handle=empty_reg_handle; |
| type rpointer={0}; |
| if(!ffreturn(a)&&(a->flags&NQ)!=VOID){ |
| rpointer.flags=POINTER_TYPE(a); |
| rpointer.next=a; |
| reg_parm(®_handle,&rpointer,0,a); /*TODO: a might be incomplete */ |
| } |
| #endif |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| #endif |
| next_token(); |
| killsp(); |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| fsd=mymalloc(sizeof(*fsd)); |
| slsz=SLSIZE; |
| sl=mymalloc(sizeof(struct_list)*slsz); |
| fsd->count=0; |
| imerk=ident;komma=0; |
| enter_block(); |
| firstparm=1; |
| while(ctok->type!=RPAR&&ctok->type!=MDOTS){ |
| int hard_reg; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| if(!firstparm&&!komma) error(57); |
| komma=firstparm=0; |
| ident=fbuff;*fbuff=0; |
| t=declaration_specifiers(); |
| hard_reg=return_reg; |
| t=declarator(t); |
| if(!t){ |
| oldstyle=1; |
| if(*ident==0) {error(20);freetyp(t);continue;} |
| } |
| if(fsd->count){ |
| if((t&&!(*sl)[fsd->count-1].styp)|| |
| (!t&&(*sl)[fsd->count-1].styp)) |
| error(63); |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(!return_sc) return_sc=AUTO; |
| if(return_sc!=AUTO&&return_sc!=REGISTER) |
| {error(21);return_sc=AUTO;} |
| (*sl)[fsd->count].styp=t; |
| (*sl)[fsd->count].storage_class=return_sc; |
| { |
| int m=nesting; |
| nesting=0; |
| (*sl)[fsd->count].identifier=add_identifier(ident,strlen(ident)); |
| nesting=m; |
| } |
| if(t){ |
| if(((*sl)[fsd->count].styp->flags&NQ)==VOID&&fsd->count!=0) |
| error(22); |
| /* Arrays in Zeiger umwandeln */ |
| if(ISARRAY((*sl)[fsd->count].styp->flags)) |
| (*sl)[fsd->count].styp->flags=POINTER_TYPE((*sl)[fsd->count].styp->next); |
| /* Funktionen in Zeiger auf Funktionen umwandeln */ |
| if(ISFUNC((*sl)[fsd->count].styp->flags)){ |
| type *new; |
| new=new_typ(); |
| new->next=(*sl)[fsd->count].styp; |
| new->flags=POINTER_TYPE(new->next); |
| (*sl)[fsd->count].styp=new; |
| } |
| } |
| if(hard_reg&®ok(hard_reg,t->flags,-1)<=0) error(217,regnames[hard_reg]); |
| #if 0 /*#ifdef HAVE_REGPARMS*/ |
| if(t) (*sl)[fsd->count].reg=reg_parm(®_handle,t,0,a); /*TODO: a might be incomplete */ |
| if(hard_reg) (*sl)[fsd->count].reg=hard_reg; |
| #else |
| (*sl)[fsd->count].reg=hard_reg; |
| #endif |
| fsd->count++; |
| if(fsd->count>=slsz-2){ /* eins Reserve fuer VOID */ |
| slsz+=SLSIZE; |
| sl=myrealloc(sl,slsz*sizeof(struct_list)); |
| } |
| killsp(); /* Hier Syntaxpruefung strenger machen */ |
| if(ctok->type==COMMA) {next_token();komma=1; killsp();} |
| } |
| ident=imerk; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| if(ctok->type!=MDOTS||!komma){ |
| int ecpp_addvoid=0; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| if(ecpp_addvoid||(!ecpp&&fsd->count>0&&(!(*sl)[fsd->count-1].styp||((*sl)[fsd->count-1].styp->flags&NQ)!=VOID))){ |
| (*sl)[fsd->count].styp=new_typ(); |
| (*sl)[fsd->count].styp->flags=VOID; |
| (*sl)[fsd->count].styp->next=0; |
| (*sl)[fsd->count].reg=0; |
| (*sl)[fsd->count].identifier=empty; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| fsd->count++; |
| } |
| if(ecpp&&ctok->type==MDOTS){next_token();killsp();} |
| }else if(komma){ |
| next_token();komma=0; |
| if(oldstyle) error(221); |
| } |
| p=new_typ(); |
| p->flags=FUNKT; |
| { |
| int m=nesting; |
| nesting=0; |
| p->exact=add_sd(fsd,FUNKT); |
| add_sl(fsd,sl); |
| free(sl); |
| nesting=m; |
| } |
| #ifdef HAVE_REGPARMS |
| { |
| treg_handle reg_handle=empty_reg_handle; |
| int i,r; |
| |
| p->next=a; |
| |
| if(!ffreturn(a)&&(a->flags&NQ)!=VOID){ |
| type rpointer={0}; |
| |
| rpointer.flags=POINTER_TYPE(a); |
| rpointer.next=a; |
| reg_parm(®_handle,&rpointer,0,p); |
| } |
| |
| for(i=0;i<p->exact->count;i++){ |
| if((*p->exact->sl)[i].styp) |
| r=reg_parm(®_handle,(*p->exact->sl)[i].styp,0,p); |
| else |
| r=0; |
| if((*p->exact->sl)[i].reg==0) (*p->exact->sl)[i].reg=r; |
| } |
| } |
| #endif |
| killsp(); |
| if(komma) error(59); |
| if(ctok->type!=RPAR) error(59); else next_token(); |
| killsp(); |
| if(ctok->type==COMMA||ctok->type==SEMIC||ctok->type==RPAR||ctok->type==ASGN) |
| leave_block(); |
| if(last){ |
| last->next=p; |
| last=p; |
| }else{ |
| first=last=p; |
| } |
| } |
| killsp(); |
| } |
| if(last){last->next=a;last=a;a=first;} |
| if(rek!=0&&rek!=merk){ |
| /* Zweite Liste anhaengen */ |
| p=rek; |
| while(p->next!=merk) p=p->next; |
| if(p) p->next=a; else ierror(0); |
| return rek; |
| } |
| return a; |
| } |
| int declaration(int offset) |
| /* Testet, ob eine Typangabe kommt. Wenn offset!=0 ist, */ |
| /* muss s auf '(' zeigen und es wird getestet, ob nach der */ |
| /* Klammer eine Typangabe kommt. */ |
| /* In jedem Fall zeigt s danach wieder auf dieselbe Stelle */ |
| /* im Source. */ |
| { |
| Var *v;token mtok; |
| int fl=0; |
| if(offset){ |
| copy_token(&mtok,ctok); |
| next_token(); |
| killsp(); |
| } |
| if(ctok->type==NAME){ |
| if(!strcmp("auto",ctok->name)) fl=1; |
| else if(!strcmp("char",ctok->name)) fl=1; |
| else if(!strcmp("const",ctok->name)) fl=1; |
| else if(!strcmp("double",ctok->name)) fl=1; |
| else if(!strcmp("enum",ctok->name)) fl=1; |
| else if(!strcmp("extern",ctok->name)) fl=1; |
| else if(!strcmp("float",ctok->name)) fl=1; |
| else if(!strcmp("int",ctok->name)) fl=1; |
| else if(!strcmp("long",ctok->name)) fl=1; |
| else if(!strcmp("register",ctok->name)) fl=1; |
| else if(c99&&!strcmp("restrict",ctok->name)) fl=1; |
| else if(!strcmp("short",ctok->name)) fl=1; |
| else if(!strcmp("signed",ctok->name)) fl=1; |
| else if(!strcmp("static",ctok->name)) fl=1; |
| else if(!strcmp("struct",ctok->name)) fl=1; |
| else if(!strcmp("typedef",ctok->name)) fl=1; |
| else if(!strcmp("union",ctok->name)) fl=1; |
| else if(!strcmp("unsigned",ctok->name)) fl=1; |
| else if(!strcmp("void",ctok->name)) fl=1; |
| else if(!strcmp("volatile",ctok->name)) fl=1; |
| else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__reg",ctok->name)) fl=1; |
| else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__attr",ctok->name)) fl=1; |
| else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__vattr",ctok->name)) fl=1; |
| else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__mask",ctok->name)) fl=1; |
| else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__readsmem",ctok->name)) fl=1; |
| else if(/*!(c_flags[7]&USEDFLAG)&&*/!strcmp("__writesmem",ctok->name)) fl=1; |
| else{ |
| v=find_var(ctok->name,0); |
| if(v&&v->storage_class==TYPEDEF) fl=1; |
| } |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(offset){ |
| push_token(&mtok); |
| free(mtok.name); |
| } |
| return fl; |
| } |
| void init_sl(struct_list *sl){ |
| if(!sl){ierror(0);return;} |
| sl->identifier=0; |
| sl->styp=0; |
| sl->align=0; |
| sl->bfoffset=-1; |
| sl->bfsize=-1; |
| sl->reg=0; |
| sl->storage_class=0; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| } |
| void add_sl(struct_declaration *sd,struct_list (*sl)[]) |
| /* Fuegt ein struct_list-Array in eine struct_declaration ein. */ |
| /* Das Array muss mind. sd->count Elements haben und wird kopiert. */ |
| { |
| size_t sz=sizeof(struct_list)*sd->count; |
| sd->sl=mymalloc(sz); |
| memcpy(sd->sl,sl,sz); |
| } |
| struct_declaration *add_sd(struct_declaration *new,int typ) |
| /* Fuegt eine Declaration in Liste ein. */ |
| { |
| new->next=0; |
| new->label=0; |
| new->typ=typ; |
| new->identifier=0; |
| new->tunit=last_tunit; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(first_sd[nesting]==0){ |
| first_sd[nesting]=last_sd[nesting]=new; |
| }else{ |
| last_sd[nesting]->next=new; |
| last_sd[nesting]=new; |
| } |
| return new; |
| } |
| void free_sd(struct_declaration *p) |
| /* Gibt eine struct_declaration-List inkl. struct_lists und */ |
| /* allen Typen jeder struct_list frei, nicht aber identifier. */ |
| { |
| int i;struct_declaration *merk; |
| while(p){ |
| merk=p->next; |
| if(p->sl){ |
| for(i=0;i<p->count;i++){ |
| if((*p->sl)[i].styp) freetyp((*p->sl)[i].styp); |
| } |
| if(p->count>0) free(p->sl); |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| free(p); |
| p=merk; |
| } |
| } |
| char *add_identifier(char *identifier,int length) |
| /* Kopiert identifier an sicheren Ort, der spaeter zentral */ |
| /* freigegeben werden kann. */ |
| /* Sollte noch einbauen, dass ueberprueft wird, ob schon */ |
| /* vorhanden und dann nicht zweimal speichern. */ |
| { |
| identifier_list *new; |
| if((*identifier==0&&length==0)||identifier==empty) return(empty); |
| new=mymalloc(sizeof(identifier_list)); |
| new->identifier=mymalloc(length+1); |
| memcpy(new->identifier,identifier,length+1); |
| new->next=0;new->length=length; |
| if(last_ilist[nesting]){ |
| last_ilist[nesting]->next=new; |
| last_ilist[nesting]=new; |
| }else{ |
| last_ilist[nesting]=first_ilist[nesting]=new; |
| } |
| return(new->identifier); |
| } |
| void free_ilist(identifier_list *p) |
| /* Gibt eine verkettete identifier_liste und saemtliche darin */ |
| /* gespeicherten Identifier frei. */ |
| { |
| identifier_list *merk; |
| while(p){ |
| merk=p->next; |
| if(p->identifier) free(p->identifier); |
| free(p); |
| p=merk; |
| } |
| } |
| int type_uncomplete(type *p) |
| /* Testet, ob Typ unvollstaendig ist. Momentan gelten nur */ |
| /* unvollstaendige Strukturen und Arrays von solchen als */ |
| /* unvollstaendig, aber keine Zeiger oder Funktionen darauf. */ |
| { |
| struct_declaration *sd; |
| if(!p){ierror(0);return(0);} |
| if(ISSTRUCT(p->flags)||ISUNION(p->flags)) |
| if(p->exact->count<=0) return 1; |
| if(ISARRAY(p->flags)){ |
| if(!p->dsize&&zmleq(p->size,l2zm(0L))) return 1; |
| if(!p->next) ierror(0); |
| if(type_uncomplete(p->next)) return 1; |
| } |
| return 0; |
| } |
| void add_struct_identifier(char *identifier,struct_declaration *sd) |
| /* Erzeugt neuen struct_identifier, fuegt ihn in Liste an und */ |
| /* vervollstaendigt unvollstaendige Typen dieser Struktur. */ |
| { |
| struct_identifier *new; |
| /* type *t;*/ |
| if(DEBUG&1) printf("add_si %s (nesting=%d)->%p\n",identifier,nesting,(void *)sd); |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| new=mymalloc(sizeof(struct_identifier)); |
| new->identifier=add_identifier(identifier,strlen(identifier)); |
| new->sd=sd; |
| new->next=0; |
| if(first_si[nesting]==0){ |
| first_si[nesting]=new;last_si[nesting]=new; |
| }else{ |
| last_si[nesting]->next=new;last_si[nesting]=new; |
| } |
| sd->identifier=new->identifier; |
| } |
| void free_si(struct_identifier *p) |
| /* Gibt eine struct_identifier-Liste frei, aber nicht die */ |
| /* identifiers und struct_declarations. */ |
| { |
| struct_identifier *merk; |
| while(p){ |
| merk=p->next; |
| p->sd->identifier="<prototype-only>"; |
| free(p); |
| p=merk; |
| } |
| } |
| struct_declaration *find_struct(char *identifier,int endnesting) |
| |
| /* Sucht angegebene Strukturdefinition und liefert */ |
| /* entsprechende struct_declaration. */ |
| { |
| struct_identifier *si; int i,l; |
| if(misracheck) l=strlen(identifier); |
| for(i=nesting;i>=endnesting;i--){ |
| si=first_si[i]; |
| while(si){ |
| if(!strcmp(si->identifier,identifier)){ |
| if(DEBUG&1) printf("found tag <%s> at nesting %d->%p\n",identifier,i,(void *)si->sd); |
| return(si->sd); |
| } |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| si=si->next; |
| } |
| } |
| if(DEBUG&1) printf("didn't find tag <%s>\n",identifier); |
| return(0); |
| } |
| |
| /* generate code to create a variable-lenght-array */ |
| static void create_allocvl(Var *v) |
| { |
| np tree,ds; |
| IC *new;Var *fv; |
| |
| /* check if we got a frame-pointer */ |
| if(FPVLA_REG&&!regsa[FPVLA_REG]){ |
| if(regused[FPVLA_REG]) |
| ierror(0); |
| else |
| regsa[FPVLA_REG]=regscratch[FPVLA_REG]=regused[FPVLA_REG]=1; |
| } |
| |
| /* if this is the first vla in this block, save old sp */ |
| if(!block_vla[nesting]){ |
| /* declare function - may be done by the backend, if necessary */ |
| if(!(fv=find_ext_var("__oldvlasp"))){ |
| type *t; |
| static type voidt={VOID}; |
| struct_declaration *sd=mymalloc(sizeof(*sd)); |
| t=new_typ(); |
| t->flags=FUNKT; |
| |
| t->next=new_typ(); |
| t->next->flags=POINTER_TYPE(&voidt); |
| t->next->next=clone_typ(&voidt); |
| sd->count=0; |
| t->exact=add_sd(sd,FUNKT); |
| fv=add_var("__oldvlasp",t,EXTERN,0); |
| fv->fi=new_fi(); |
| fv->fi->flags|=(ALL_USES|ALL_MODS); |
| fv->fi->inline_asm=mystrdup(OLDSPVLA_INLINEASM); |
| } |
| block_vla[nesting]=add_tmp_var(clone_typ(fv->vtyp->next)); |
| tree=gen_libcall("__oldvlasp",0,0,0,0); |
| new=new_IC(); |
| new->code=ASSIGN; |
| new->z.flags=VAR; |
| new->z.v=block_vla[nesting]; |
| new->z.val.vmax=l2zm(0L); |
| new->q1=tree->o; |
| new->q2.flags=0; |
| new->typf=block_vla[nesting]->vtyp->flags; |
| new->q2.val.vmax=sizetab[new->typf]; |
| add_IC(new); |
| free_expression(tree); |
| } |
| |
| /* make room on the stack */ |
| ds=new_node(); |
| ds->flags=IDENTIFIER; |
| ds->identifier=empty; |
| ds->dsize=vlength_szof(v->vtyp); |
| ds->val.vmax=l2zm(0L); |
| ds->ntyp=clone_typ(ds->dsize->vtyp); |
| ds->o.flags=VAR; |
| ds->o.v=ds->dsize; |
| ds->o.val.vmax=l2zm(0L); |
| ds->left=ds->right=0; |
| |
| if(!find_ext_var("__allocvla")){ |
| /* declare function */ |
| struct_declaration *sd=mymalloc(sizeof(*sd)); |
| type *t=new_typ(); |
| sd->count=1; |
| sd->sl=mymalloc(sizeof(struct_list)); |
| (*sd->sl)[0].storage_class=AUTO; |
| (*sd->sl)[0].styp=clone_typ(ds->dsize->vtyp); |
| (*sd->sl)[0].reg=ALLOCVLA_REG; |
| t->flags=FUNKT; |
| t->exact=add_sd(sd,FUNKT); |
| t->next=new_typ(); |
| t->next->flags=POINTER_TYPE(v->vtyp); |
| t->next->next=new_typ(); |
| t->next->next->flags=v->vtyp->flags; |
| fv=add_var("__allocvla",t,EXTERN,0); |
| fv->fi=new_fi(); |
| fv->fi->flags|=(ALL_USES|ALL_MODS); |
| fv->fi->inline_asm=mystrdup(ALLOCVLA_INLINEASM); |
| } |
| |
| if(!type_expression(ds,0)) ierror(0); |
| tree=gen_libcall("__allocvla",ds,0,0,0); |
| new=new_IC(); |
| new->code=ASSIGN; |
| new->z.flags=VAR; |
| new->z.v=v; |
| new->z.val.vmax=l2zm(0L); |
| new->q1=tree->o; |
| new->q2.flags=0; |
| new->typf=POINTER_TYPE(v->vtyp); |
| new->q2.val.vmax=sizetab[new->typf]; |
| add_IC(new); |
| free_expression(tree); |
| vlas=1; |
| } |
| |
| /* reset sp to remove variable-length-arrays */ |
| void freevl(void) |
| { |
| np tree,ds; |
| Var *fv; |
| dontdelete=1; /* never remove them, otherwise, fix_vla_jump get confused */ |
| if(!find_ext_var("__resetvlasp")){ |
| struct_declaration *sd=mymalloc(sizeof(*sd)); |
| type *t=new_typ(); |
| sd->count=1; |
| sd->sl=mymalloc(sizeof(struct_list)); |
| (*sd->sl)[0].storage_class=AUTO; |
| (*sd->sl)[0].styp=clone_typ(block_vla[nesting]->vtyp); |
| (*sd->sl)[0].reg=FREEVLA_REG; |
| t->flags=FUNKT; |
| t->exact=add_sd(sd,FUNKT); |
| t->next=new_typ(); |
| t->next->flags=VOID; |
| fv=add_var("__resetvlasp",t,EXTERN,0); |
| fv->fi=new_fi(); |
| fv->fi->flags|=(ALL_USES|ALL_MODS); |
| fv->fi->inline_asm=mystrdup(FREEVLA_INLINEASM); |
| } |
| if(nesting==1){ |
| clear_main_ret(); |
| gen_label(return_label); |
| did_return_label=1; |
| } |
| ds=new_node(); |
| ds->flags=IDENTIFIER; |
| ds->identifier=empty; |
| ds->dsize=block_vla[nesting]; |
| ds->val.vmax=l2zm(0L); |
| ds->ntyp=clone_typ(ds->dsize->vtyp); |
| ds->left=ds->right=0; |
| ds->o.flags=VAR; |
| ds->o.v=ds->dsize; |
| ds->o.val.vmax=l2zm(0L); |
| if(!type_expression(ds,0)) ierror(0); |
| tree=gen_libcall("__resetvlasp",ds,0,0,0); |
| free_expression(tree); |
| dontdelete=0; |
| } |
| |
| void clearvl(void) |
| { |
| llist *p,*n; |
| vlaadjust_list *vl,*vn; |
| /* look for stack-adjusts that have to be removed */ |
| vl=vlaadjusts[nesting]; |
| while(vl){ |
| int ln; |
| IC *ic=vl->branch; |
| if(ic){ |
| ln=ic->typf; |
| if(ic->code!=BRA) ierror(0); |
| p=vladeflabels[nesting]; |
| while(p){ |
| if(p->label==ln) break; |
| p=p->next; |
| } |
| if(!p){ |
| ic=ic->prev; |
| while(ic!=vl->first->prev){ |
| if(!ic) ierror(0); |
| ic->code=NOP; |
| ic->q1.flags=ic->q2.flags=ic->z.flags=0; |
| ic=ic->prev; |
| } |
| } |
| } |
| vn=vl->next; |
| free(vl); |
| vl=vn; |
| } |
| freevl(); |
| block_vla[nesting]=0; |
| p=vladeflabels[nesting]; |
| while(p){ |
| n=p->next; |
| free(p); |
| p=n; |
| } |
| p=vlajmplabels[nesting]; |
| while(p){ |
| n=p->next; |
| free(p); |
| p=n; |
| } |
| vladeflabels[nesting]=vlajmplabels[nesting]=0; |
| vlaadjusts[nesting]=0; |
| } |
| |
| /* Handle a stack of stored sp variables when traversing an IC list; */ |
| void vla_nesting(IC *p,Var **vn,int *nest) |
| { |
| if(p->code==CALL&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p->q1.v->identifier,"__oldvlasp")){ |
| IC *p2=p->next; |
| while(p2&&(p2->code==ALLOCREG||p2->code==FREEREG)) p2=p2->next; |
| if(!p2||p2->code!=GETRETURN||(p2->z.flags&(VAR|DREFOBJ))!=VAR) ierror(0); |
| /*printf("found save sp to %p\n",p2->z.v);*/ |
| vn[*nest]=p2->z.v; |
| (*nest)++; |
| vn[*nest]=0; |
| if(*nest>=MAXN) ierror(0); |
| return; |
| } |
| if(p->code==CALL&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p->q1.v->identifier,"__resetvlasp")){ |
| /*printf("found reset\n");*/ |
| if(*nest<=0) ierror(0); |
| (*nest)--; |
| return; |
| } |
| } |
| |
| static int return_vla_nest; |
| static Var *return_last_vlasp; |
| |
| /* Find the stack pointer that is needed when jumping to label lab */ |
| Var *vla_find_sp(int lab) |
| { |
| IC *p;int nest=0; |
| static Var *vn[MAXN]; |
| for(p=first_ic;p;p=p->next){ |
| if(p->code==LABEL&&p->typf==lab){ |
| return_vla_nest=nest; |
| return_last_vlasp=vn[nest]; |
| if(nest<=0) |
| return 0; |
| else |
| return vn[nest-1]; |
| } |
| vla_nesting(p,vn,&nest); |
| } |
| ierror(0); |
| } |
| |
| void vla_jump_fix(void) |
| { |
| IC *p;int nest=0; |
| static Var *vn[MAXN],*savedsp; |
| if(DEBUG&1) printf("searching for vla-jump-fixes\n"); |
| for(p=first_ic;p;p=p->next){ |
| /*pric2(stdout,p);*/ |
| if(p->code>=BEQ&&p->code<=BRA){ |
| /*printf("jump found\n");*/ |
| p->savedsp=0; |
| if(1/*nest>0*/){ |
| /*printf("is in vla context!\n");*/ |
| savedsp=vla_find_sp(p->typf); |
| if(return_vla_nest>nest||(nest>0&&return_vla_nest==nest&&savedsp!=vn[nest-1])){ |
| err_ic=p; |
| error(351); |
| }else if(nest==0||savedsp==vn[nest-1]){ |
| /*printf("jump within the same context\n");*/ |
| }else{ |
| if(vn[nest]){ |
| if(DEBUG&1) printf("have to set sp to %p\n",return_last_vlasp); |
| p->savedsp=return_last_vlasp; |
| }else{ |
| int ndiff=nest-return_vla_nest-1; |
| IC *p2; |
| /*printf("have to search oldsp ndiff=%d\n",ndiff);*/ |
| for(p2=p->prev;p2;p2=p2->prev){ |
| if(p2->code==CALL&&(p2->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p2->q1.v->identifier,"__oldvlasp")){ |
| if(ndiff==0){ |
| /*printf("found savesp\n");*/ |
| p2=p2->next; |
| while(p2&&(p2->code==ALLOCREG||p2->code==FREEREG)) p2=p2->next; |
| if(!p2||p2->code!=GETRETURN) ierror(0); |
| if((p2->z.flags&(VAR|DREFOBJ))!=VAR) ierror(0); |
| /*printf("found oldsp %p\n",p2->z.v);*/ |
| p->savedsp=p2->z.v; |
| break; |
| } |
| ndiff--; |
| } |
| if(p2->code==CALL&&(p2->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p2->q1.v->identifier,"__resetvlasp")){ |
| ndiff++; |
| } |
| } |
| if(!p2) ierror(0); |
| } |
| } |
| }else{ |
| /*printf("not in vla context\n");*/ |
| } |
| } |
| vla_nesting(p,vn,&nest); |
| } |
| for(p=first_ic;p;p=p->next){ |
| if(p->code>=BEQ&&p->code<=BRA){ |
| if(p->savedsp){ |
| IC *merkfic,*merklic,*newcode,*m,*new,*setr=0; |
| np ds,tree; |
| if(DEBUG&1) printf("generating sp-adjust\n"); |
| merkfic=first_ic;merklic=last_ic; |
| first_ic=0;last_ic=0; |
| ds=new_node(); |
| ds->flags=IDENTIFIER; |
| ds->identifier=empty; |
| ds->dsize=p->savedsp; |
| ds->val.vmax=l2zm(0L); |
| ds->ntyp=clone_typ(ds->dsize->vtyp); |
| ds->left=ds->right=0; |
| ds->o.flags=VAR; |
| ds->o.v=ds->dsize; |
| ds->o.val.vmax=l2zm(0L); |
| if(!type_expression(ds,0)) ierror(0); |
| tree=gen_libcall("__resetvlasp",ds,0,0,0); |
| free_expression(tree); |
| newcode=first_ic; |
| first_ic=merkfic;last_ic=merklic; |
| if(p->code==BRA){ |
| /* check if the branch was preceded by a SETRETURN */ |
| IC *p2=p->prev; |
| while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) |
| p2=p2->prev; |
| if(p2->code==SETRETURN&&p2->z.reg) |
| setr=p2; |
| }else{ |
| new=new_IC(); |
| new->typf=++label; |
| if(p->code==BEQ) new->code=BRA; |
| else if(p->code==BNE) new->code=BEQ; |
| else if(p->code==BLT) new->code=BGE; |
| else if(p->code==BGT) new->code=BLE; |
| else if(p->code==BLE) new->code=BGT; |
| else if(p->code==BGE) new->code=BLT; |
| insert_IC(p->prev,new); |
| } |
| while(newcode){ |
| m=newcode->next; |
| insert_IC(p->prev,newcode); |
| newcode=m; |
| } |
| if(p->code!=BRA){ |
| p->code=BRA; |
| new=new_IC(); |
| new->code=LABEL; |
| new->typf=label; |
| insert_IC(p,new); |
| } |
| if(setr){ |
| /* save the return value to save it from being overwritten */ |
| /* could be optimized further */ |
| Var *v; |
| if(ISSCALAR(setr->typf)){ |
| static type t={0}; |
| t.flags=setr->typf; |
| v=add_tmp_var(clone_typ(&t)); |
| }else ierror(0); |
| new=new_IC(); |
| *new=*setr; |
| new->q1.flags=VAR; |
| new->q1.v=v; |
| new->q1.val.vmax=l2zm(0L); |
| setr->z=new->q1; |
| setr->code=ASSIGN; |
| insert_IC(p->prev,new); |
| } |
| } |
| } |
| } |
| } |
| |
| |
| Var *add_tmp_var(type *t) |
| { |
| t->flags&=NU; |
| return add_var(empty,t,AUTO,0); |
| } |
| Var *add_var(char *identifier, type *t, int storage_class,const_list *clist) |
| /* Fuegt eine Variable mit Typ in die var_list ein. */ |
| /* In der storage_class werden die Flags PARAMETER und evtl. */ |
| /* OLDSTYLE und REGPARM erkannt. */ |
| { |
| Var *new;int f; |
| struct_declaration *sd; |
| static zmax paroffset; |
| zmax al; |
| /*if(*identifier==0) return;*/ /* sollte woanders bemaekelt werden */ |
| if(DEBUG&2) printf("add_var(): %s\n",identifier); |
| #ifdef HAVE_TARGET_VARHOOK_PRE |
| add_var_hook_pre(identifier,t,storage_class,clist); |
| #endif |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(ISFUNC(t->flags&NQ)&&(ISARRAY(t->next->flags)||ISFUNC(t->next->flags))) |
| error(25); |
| new=mymalloc(sizeof(Var)); |
| if(!*identifier&&identifier!=empty) ierror(0); |
| new->clist=clist; |
| new->vtyp=t; |
| new->storage_class=storage_class&PLAIN_STORAGE_CLASS; |
| new->reg=0; |
| new->vattr=0; |
| new->next=0; |
| new->flags=0; |
| new->inr=0; |
| new->fi=0; |
| new->nesting=nesting; |
| new->filename=filename; |
| new->line=line; |
| new->dfilename=0; |
| new->dline=0; |
| new->description=0; |
| new->tunit=last_tunit; |
| new->inline_copy=0; |
| new->index=-1; |
| #ifdef HAVE_TARGET_ATTRIBUTES |
| new->tattr=0; |
| #endif |
| /* if((storage_class&PLAIN_STORAGE_CLASS)==STATIC||(storage_class&PLAIN_STORAGE_CLASS)==EXTERN) new->flags=USEDASSOURCE|USEDASDEST;*/ |
| if(DEBUG&2) printf("storage_class=%d\n",storage_class); |
| if(storage_class&PARAMETER) new->flags|=USEDASDEST; |
| if(storage_class®PARM){ |
| new->flags|=REGPARM; |
| if(!(storage_class&DBLPUSH)){ |
| if((storage_class&OLDSTYLE)&&(t->flags&NQ)==FLOAT) |
| new->flags|=CONVPARAMETER; |
| storage_class&=~PARAMETER; |
| } |
| } |
| if(DEBUG&2) printf("storage_class=%d\n",storage_class); |
| if(DEBUG&2) printf("max_offset=%ld\n",zm2l(max_offset)); |
| if(is_vlength(t)&&storage_class!=AUTO&&storage_class!=REGISTER) |
| error(315); |
| if((storage_class&PLAIN_STORAGE_CLASS)==REGISTER) new->priority=registerpri; else new->priority=0; |
| if(/*nesting==0&&*/new->storage_class==EXTERN){ |
| int m=nesting; |
| nesting=0; |
| new->identifier=add_identifier(identifier,strlen(identifier)); |
| nesting=m; |
| if(last_ext){ |
| last_ext->next=new; |
| last_ext=new; |
| }else{ |
| first_ext=last_ext=new; |
| vl0=first_ext; |
| } |
| if(hash_ext) add_hashentry(hash_ext,new->identifier,new); |
| }else{ |
| new->identifier=add_identifier(identifier,strlen(identifier)); |
| if(last_var[nesting]){ |
| new->offset=zmadd(last_var[nesting]->offset,szof(last_var[nesting]->vtyp)); |
| last_var[nesting]->next=new; |
| last_var[nesting]=new; |
| }else{ |
| new->offset=l2zm(0L); |
| paroffset=l2zm(0L);; |
| first_var[nesting]=last_var[nesting]=new; |
| if(nesting==0) vl1=new; |
| if(nesting==1) vl2=new; |
| } |
| } |
| f=t->flags&NQ; |
| if((storage_class&PLAIN_STORAGE_CLASS)==AUTO||(storage_class&PLAIN_STORAGE_CLASS)==REGISTER){ |
| if(DEBUG&2) printf("auto\n"); |
| al=falign(t); |
| if((c_flags_val[0].l&2)&&nesting==1&&!(storage_class&PARAMETER)){ |
| new->offset=max_offset; |
| }else{ |
| if(storage_class&PARAMETER){ |
| new->offset=paroffset; |
| if(align_arguments) |
| new->offset=zmmult(zmdiv(zmadd(new->offset,zmsub(al,l2zm(1L))),al),al); |
| }else{ |
| new->offset=local_offset[nesting]; |
| new->offset=zmmult(zmdiv(zmadd(new->offset,zmsub(al,l2zm(1L))),al),al); |
| } |
| } |
| if(storage_class&PARAMETER){ |
| new->offset=zmmult(zmdiv(zmadd(new->offset,zmsub(stackalign,l2zm(1L))),stackalign),stackalign); |
| if(ISINT(f)&&f<INT&&!short_push){ |
| /* Integer-Erweiterungen fuer alle Funktionsparameter */ |
| paroffset=zmadd(new->offset,sizetab[INT]); |
| }else{ |
| if(f==FLOAT&&(storage_class&OLDSTYLE)){ |
| /* Bei alten Funktionen werden FLOAT als DOUBLE uebergeben */ |
| new->offset=zmmult(zmdiv(zmadd(new->offset,zmsub(align[DOUBLE],l2zm(1L))),align[DOUBLE]),align[DOUBLE]); |
| paroffset=zmadd(new->offset,sizetab[DOUBLE]); |
| }else{ |
| paroffset=zmadd(new->offset,szof(new->vtyp)); |
| } |
| } |
| }else{ |
| local_offset[nesting]=zmadd(new->offset,szof(new->vtyp)); |
| } |
| if(!(storage_class&PARAMETER)) |
| if(zmleq(max_offset,local_offset[nesting])) max_offset=local_offset[nesting]; |
| if(DEBUG&2) printf("max_offset=%ld\n",zm2l(max_offset)); |
| } |
| if((storage_class&PLAIN_STORAGE_CLASS)==STATIC) new->offset=l2zm((long)++label); |
| if(storage_class&PARAMETER){ |
| |
| if(DEBUG&2) printf("parameter\n"); |
| |
| if(ISINT(f)&&f<INT&&!zmleq(sizetab[INT],sizetab[f])){ |
| if(BIGENDIAN){ |
| new->offset=zmadd(new->offset,zmsub(sizetab[INT],sizetab[f])); |
| }else{ |
| if(!LITTLEENDIAN) |
| ierror(0); |
| } |
| } |
| if((storage_class&OLDSTYLE)&&f==FLOAT){ |
| /* Bei alten Funktionen werden DOUBLE nach FLOAT konvertiert */ |
| if(!(storage_class®PARM)){ |
| #if HAVE_LIBCALLS |
| static type dt={DOUBLE},ft={FLOAT}; |
| static node n,nn; |
| IC *conv=new_IC(); |
| n.flags=REINTERPRET; |
| n.left=&nn; |
| n.ntyp=&dt; |
| nn.flags=IDENTIFIER; |
| nn.identifier=identifier; |
| nn.ntyp=&ft; |
| nn.o.flags=VAR|DONTREGISTERIZE; |
| nn.o.v=new; |
| nn.o.val.vmax=l2zm(0L); |
| n.o=nn.o; |
| convert(&n,FLOAT); |
| |
| |
| conv->code=ASSIGN; |
| conv->typf=FLOAT; |
| conv->q1=n.o; |
| conv->z.v=new; |
| conv->z.flags=VAR; |
| conv->z.val.vmax=l2zm(0L); |
| conv->q2.val.vmax=sizetab[FLOAT]; |
| conv->z.v=new; |
| add_IC(conv); |
| #else |
| IC *conv=new_IC(); |
| conv->code=CONVERT; |
| conv->typf=FLOAT; |
| conv->typf2=DOUBLE; |
| conv->q1.flags=VAR|DONTREGISTERIZE; |
| conv->z.flags=VAR; |
| conv->q2.flags=0; |
| conv->q1.v=conv->z.v=new; |
| conv->q1.val.vmax=conv->z.val.vmax=l2zm(0); |
| add_IC(conv); |
| #endif |
| } |
| new->flags|=CONVPARAMETER; |
| } |
| new->offset=zmsub(l2zm(0L),zmadd(maxalign,new->offset)); |
| } |
| if((storage_class&PLAIN_STORAGE_CLASS)==EXTERN){ |
| if(!strcmp("fprintf",identifier)) new->flags|=PRINTFLIKE; |
| if(!strcmp("printf",identifier)) new->flags|=PRINTFLIKE; |
| if(!strcmp("sprintf",identifier)) new->flags|=PRINTFLIKE; |
| if(!strcmp("fscanf",identifier)) new->flags|=SCANFLIKE; |
| if(!strcmp("scanf",identifier)) new->flags|=SCANFLIKE; |
| if(!strcmp("sscanf",identifier)) new->flags|=SCANFLIKE; |
| } |
| if(is_vlength(new->vtyp)) |
| create_allocvl(new); |
| #ifdef HAVE_TARGET_VARHOOK_POST |
| add_var_hook_post(new); |
| #endif |
| return(new); |
| } |
| void free_var(Var *p) |
| /* Gibt Variablenliste inkl. Typ, aber ohne Identifier frei. */ |
| { |
| Var *merk; |
| while(p){ |
| if(!*p->identifier&&p->identifier!=empty) ierror(0); |
| free(p->description); |
| free(p->vattr); |
| merk=p->next; |
| if(!(p->flags&USEDASADR)&&(p->storage_class==AUTO||p->storage_class==REGISTER)){ |
| if(*p->identifier&&!(p->flags&USEDASDEST)&&ISSCALAR(p->vtyp->flags)) error(64,p->identifier); |
| if(*p->identifier&&!(p->flags&USEDASSOURCE)&&ISSCALAR(p->vtyp->flags)) error(65,p->identifier); |
| } |
| if(DEBUG&2) printf("free_var %s, pri=%d\n",p->identifier,p->priority); |
| if(p->vtyp) freetyp(p->vtyp); |
| if(p->clist) free_clist(p->clist); |
| if(p->fi){ |
| if(DEBUG&2) printf("free_fi of function %s\n",p->identifier); |
| free_fi(p->fi); |
| if(DEBUG&2) printf("end free_fi of function %s\n",p->identifier); |
| } |
| free(p); |
| p=merk; |
| } |
| } |
| Var *find_ext_var(char *identifier) |
| { |
| Var *v;int l; |
| if(misracheck) l=strlen(identifier); |
| if(hash_ext) return find_name(hash_ext,identifier); |
| for(v=first_ext;v;v=v->next){ |
| if(!strcmp(v->identifier,identifier)) return v; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| |
| } |
| return 0; |
| } |
| Var *find_var(char *identifier,int endnesting) |
| /* Sucht Variable mit Bezeichner und liefert Zeiger zurueck */ |
| /* es werden nur Variablen der Bloecke endnesting-nesting */ |
| /* durchsucht. */ |
| { |
| int i,l;Var *v; |
| if(identifier==0||*identifier==0) return 0; |
| if(misracheck) l=strlen(identifier); |
| for(i=nesting;i>=endnesting;i--){ |
| for(v=first_var[i];v;v=v->next){ |
| if(!strcmp(v->identifier,identifier)) |
| return v; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| } |
| } |
| if(endnesting==0){ |
| v=find_ext_var(identifier); |
| if(v&&!(v->flags&NOTINTU)) |
| return v; |
| else |
| return 0; |
| }else |
| return 0; |
| } |
| |
| |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| #endif |
| |
| |
| |
| int check_zero_initialisation(const_list* cl, int typ) |
| { |
| |
| if (cl->next) return 0; |
| if (cl->tree) return 0; |
| if (cl->other) { |
| return check_zero_initialisation(cl->other,typ); |
| } else { |
| eval_const(&cl->val,typ); |
| if ( (zmeqto(vmax,l2zm(0L))) && (zumeqto(vumax,ul2zum(0UL))) && (zldeqto(vldouble,d2zld(0.0))) ) { |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| /* decide whether a initialization shall be performed only be generated code |
| or if a table copy should be used first */ |
| int use_only_dyn_init(zmax sz,zmax dyn_sz,zmax const_sz,int dyn_cnt,int const_cnt) |
| { |
| if(zmleq(sz,l2zm(clist_copy_stack))) |
| return 1; |
| if(zmeqto(dyn_sz,l2zm(0L))) |
| return 0; |
| if(!zmleq(zmdiv(sz,dyn_sz),l2zm(2L))) |
| return 0; |
| else |
| return 1; |
| } |
| |
| void init_local_compound(Var *v) |
| { |
| if(v->storage_class==AUTO||v->storage_class==REGISTER){ |
| IC *new; |
| /* Initialisierung von auto-Variablen */ |
| new=new_IC(); |
| new->code=ASSIGN; |
| new->typf=v->vtyp->flags; |
| new->q2.flags=0; |
| new->q2.val.vmax=szof(v->vtyp); |
| new->z.flags=VAR; |
| new->z.v=v; |
| new->z.val.vmax=l2zm(0L); |
| if(v->clist->tree){ |
| /* einzelner Ausdruck */ |
| gen_IC(v->clist->tree,0,0); |
| convert(v->clist->tree,v->vtyp->flags&NU); |
| new->q1=v->clist->tree->o; |
| add_IC(new); |
| /* v->clist=0;*/ |
| }else{ |
| /* Array etc. */ |
| Var *nv; |
| if(!ISSCALAR(v->vtyp->flags)&&!use_only_dyn_init(szof(v->vtyp),init_dyn_sz,init_const_sz,init_dyn_cnt,init_const_cnt)){ |
| nv=add_var(empty,clone_typ(v->vtyp),STATIC,v->clist); |
| nv->flags|=DEFINED; |
| nv->dfilename=filename; |
| nv->dline=line; |
| nv->vtyp->flags|=CONST; |
| /* v->clist=0;*/ |
| new->q1.flags=VAR; |
| new->q1.v=nv; |
| new->q1.val.vmax=l2zm(0L); |
| |
| add_IC(new); |
| |
| dynamic_init(v,v->vtyp,v->clist,0,1); |
| }else{ |
| dynamic_init(v,v->vtyp,v->clist,0,0); |
| } |
| } |
| } |
| } |
| |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| |
| void var_declaration(void) |
| /* Bearbeitet eine Variablendeklaration und erzeugt alle */ |
| /* noetigen Strukturen. */ |
| { |
| type *ts,*t,*old=0,*om=0;char *imerk,vident[MAXI]; |
| int mdef=0,makeint=0,notdone,storage_class,msc,extern_flag,isfunc, |
| had_decl,hard_reg,mhr,diffunit=0,inline_flag; |
| Var *v; |
| char *vattr; |
| zumax mask; |
| int base_type; |
| #ifdef HAVE_TARGET_ATTRIBUTES |
| unsigned long tattr; |
| #endif |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| ts=declaration_specifiers();notdone=1; |
| |
| storage_class=return_sc;hard_reg=return_reg;vattr=return_vattr;mask=return_mask; |
| inline_flag=return_inline; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| if(for_decl&&storage_class!=0&&storage_class!=AUTO&&storage_class!=REGISTER){ |
| error(299); |
| storage_class=AUTO; |
| } |
| |
| #ifdef HAVE_TARGET_ATTRIBUTES |
| tattr=return_tattr; |
| #endif |
| if(storage_class==EXTERN) extern_flag=1; else extern_flag=0; |
| killsp(); |
| if(ctok->type==SEMIC){ |
| if(!ts) error(0); |
| if(storage_class||(!ISSTRUCT(ts->flags)&&!ISUNION(ts->flags)&&(ts->flags&NQ)!=INT)) |
| error(36); |
| freetyp(ts); |
| next_token();killsp(); |
| return; |
| } |
| if(nesting==0&&(storage_class==AUTO||storage_class==REGISTER)) |
| {error(66);storage_class=EXTERN;} |
| if(!ts){ |
| if(nesting<=1){ |
| ts=new_typ(); |
| ts->flags=INT;ts->next=0; |
| makeint=1; |
| if(!storage_class) storage_class=EXTERN; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| error(67); |
| }else{ |
| error(365); |
| } |
| } |
| if(storage_class==0){ |
| if(nesting==0) |
| storage_class=EXTERN; |
| else |
| storage_class=AUTO; |
| } |
| msc=storage_class;mhr=hard_reg; |
| while(notdone){ |
| int oldnesting=nesting; |
| imerk=ident;ident=vident;*vident=0; /* merken von ident hier vermutlich */ |
| storage_class=msc;hard_reg=mhr; |
| if(old) {freetyp(old);old=0;} |
| t=declarator(clone_typ(ts)); |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| #ifdef HAVE_EXT_TYPES |
| conv_typ(t); |
| #endif |
| if(!ISFUNC(t->flags)){ |
| isfunc=0; |
| if(inline_flag) error(301); |
| }else{ |
| isfunc=1; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| if(storage_class!=STATIC&&storage_class!=TYPEDEF) storage_class=EXTERN; |
| } |
| ident=imerk; /* nicht unbedingt noetig ? */ |
| if(!*vident){ |
| free(ts);free(t); |
| error(36);return; |
| } |
| v=find_var(vident,oldnesting); |
| if(!v&&/*oldnesting==0&&*/storage_class==EXTERN&&cross_module&&(v=find_ext_var(vident))){ |
| v->flags&=~NOTINTU; |
| diffunit=1; |
| /*FIXME: check auf doppelte Def. */ |
| } |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(v){ |
| had_decl=1; |
| if(storage_class==TYPEDEF){ |
| error(226,v->identifier); |
| }else{ |
| if(nesting>0&&(v->flags&DEFINED)&&!extern_flag&&!isfunc){ |
| error(27,vident); |
| }else{ |
| if(t&&v->vtyp&&!compatible_types(v->vtyp,t,NU|CONST|VOLATILE)){ |
| if(ISFUNC(t->flags)&&!ISFUNC(v->vtyp->flags)) |
| error(361,vident); |
| else |
| error(68,vident); |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| } |
| if((storage_class!=v->storage_class&&!extern_flag)||hard_reg!=v->reg) |
| error(28,v->identifier); |
| if(!isfunc&&!extern_flag) v->flags|=TENTATIVE; |
| } |
| #ifdef HAVE_TARGET_ATTRIBUTES |
| { |
| int i; |
| for(i=0;g_attr_name[i];i++){ |
| if((v->tattr&(1L<<i))!=(tattr&(1L<<i))) error(228,vident,g_attr_name[i]); |
| } |
| v->tattr=tattr; |
| } |
| #endif |
| if(vattr){ |
| if(!v->vattr||!strstr(v->vattr,vattr)){ |
| error(370,v->identifier,vattr,v->vattr?v->vattr:empty); |
| add_attr(&v->vattr,vattr); |
| } |
| if(ISFUNC(v->vtyp->flags)) fi_from_attr(v); |
| } |
| if(!isfunc){ |
| if(!ISARRAY(t->flags)||!zmeqto(t->size,l2zm(0L))){ |
| free(v->vtyp); |
| v->vtyp=t; |
| } |
| }else{ |
| om=v->vtyp; |
| if(t->exact->count>0){ |
| old=v->vtyp;v->vtyp=t; |
| } |
| } |
| } |
| #ifdef HAVE_TARGET_VARHOOK_POST |
| add_attr_haddecl=v; |
| add_var_hook_post(v); |
| add_attr_haddecl=0; |
| #endif |
| |
| }else{ |
| had_decl=0; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| if(isfunc&&ctok->type!=COMMA&&ctok->type!=SEMIC&&ctok->type!=RPAR&&ctok->type!=ASGN&&nesting>0) nesting--; |
| if(!zumeqto(mask,ul2zum(0UL))){ |
| sprintf(vident+strlen(vident),".%lu",zum2ul(mask)); |
| } |
| v=add_var(vident,t,storage_class,0); |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| v->reg=hard_reg; |
| if(vattr) |
| add_attr(&v->vattr,vattr); |
| if(ISFUNC(v->vtyp->flags)) |
| fi_from_attr(v); |
| #ifdef HAVE_TARGET_ATTRIBUTES |
| v->tattr=tattr; |
| #endif |
| if(isfunc&&ctok->type!=COMMA&&ctok->type!=SEMIC&&ctok->type!=RPAR&&ctok->type!=ASGN&&nesting>=0) nesting++; |
| if(!v) ierror(0); |
| else{ |
| if(!isfunc&&!extern_flag){ |
| v->flags|=TENTATIVE; |
| if(nesting>0){ |
| v->flags|=DEFINED; |
| v->dfilename=filename; |
| v->dline=line; |
| } |
| } |
| } |
| om=0; |
| } |
| if(isfunc&&inline_flag){ |
| v->flags|=INLINEFUNC; |
| if(extern_flag) v->flags|=INLINEEXT; |
| } |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(disallow_statics&&v->storage_class==STATIC&&*v->identifier&&!is_const(v->vtyp)) |
| error(302,v->identifier); |
| killsp(); |
| /* Inline-Assembler-Code in Funktionsdeklarationen */ |
| if(ctok->type==ASGN&&ISFUNC(v->vtyp->flags)&&(header_cnt>0||!(c_flags[7]&USEDFLAG))){ |
| np tree; |
| next_token();killsp(); |
| if(v->fi){free(v->fi->inline_asm);v->fi->inline_asm=0;} |
| if(!v->fi) v->fi=new_fi(); |
| v->fi->inline_asm=get_string(); |
| /*STRBACK(v->fi->inline_asm);*/ |
| mdef=1; |
| }else{ |
| /*if(v->fi){free(v->fi->inline_asm);v->fi->inline_asm=0;}*/ |
| } |
| /* Initialisierung von Variablen bei Deklaration */ |
| if(ctok->type==ASGN){ |
| |
| next_token();killsp(); |
| if(!had_decl&&v->nesting==0&&v->storage_class==EXTERN&&strcmp("main",v->identifier)) |
| error(168,v->identifier); |
| if(v->flags&DEFINED){ |
| if(nesting==0) error(30,v->identifier); |
| }else{ |
| v->flags|=DEFINED; |
| v->dfilename=filename; |
| v->dline=line; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| } |
| if(v->storage_class==TYPEDEF) error(114,v->identifier); |
| if(extern_flag){ |
| if(nesting==0) |
| error(118,v->identifier); |
| else |
| error(207,v->identifier); |
| if(v->storage_class!=EXTERN){ error(77);v->storage_class=EXTERN;} |
| } |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| #endif |
| init_dyn_sz=l2zm(0L); |
| init_dyn_cnt=0; |
| init_const_sz=l2zm(0L); |
| init_const_cnt=0; |
| v->clist=initialization(v->vtyp,v->storage_class==AUTO||v->storage_class==REGISTER,0,0,0,0); |
| /* MISRA Rule 9.2 violation checking and error reporting */ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| if(v->clist){ |
| if(ISARRAY(v->vtyp->flags)&&zmeqto(v->vtyp->size,l2zm(0L))){ |
| const_list *p=v->clist; |
| while(p){v->vtyp->size=zmadd(p->idx,l2zm(1L));p=p->next;} |
| if(v->storage_class==AUTO||v->storage_class==REGISTER){ |
| local_offset[nesting]=zmadd(local_offset[nesting],szof(v->vtyp)); |
| if(zmleq(max_offset,local_offset[nesting])) max_offset=local_offset[nesting]; |
| } |
| } |
| if(v->storage_class==AUTO||v->storage_class==REGISTER){ |
| |
| init_local_compound(v); |
| |
| }else if(c_flags[19]&USEDFLAG){ |
| /* Ohne Optimierung gleich erzeugen; das ist noch */ |
| /* etwas von der genauen Implementierung der Liste */ |
| /* der Variablen abhaengig. */ |
| Var *merk=v->next; |
| v->next=0; |
| gen_vars(v); |
| v->next=merk; |
| v->clist=0; |
| } |
| } |
| }else{ |
| if((v->flags&DEFINED)&&type_uncomplete(v->vtyp)) error(202,v->identifier); |
| if((v->vtyp->flags&CONST)&&(v->storage_class==AUTO||v->storage_class==REGISTER)) |
| error(119,v->identifier); |
| } |
| if(ctok->type==COMMA) {next_token();killsp();mdef=1;} else notdone=0; |
| } |
| freetyp(ts); |
| |
| if(ISFUNC(t->flags)&&v->reg) |
| t->next->reg=v->reg; |
| |
| if(!mdef&&t&&(t->flags&NQ)==FUNKT&&ctok->type!=SEMIC){ |
| /* Funktionsdefinition*/ |
| int i,oldstyle=0; |
| |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| #endif |
| #ifdef HAVE_REGPARMS |
| treg_handle reg_handle; |
| #endif |
| if(DEBUG&1) printf("Funktionsdefinition! %s %p\n",v->identifier,(void *)v); |
| { |
| int i; |
| for(i=1;i<=MAXR;i++) {regs[i]=regused[i]=regsa[i];regsbuf[i]=0;} |
| } |
| cur_func=v->identifier; |
| cur_funcv=v; |
| if(only_inline==2) only_inline=0; |
| if(nesting<1) enter_block(); |
| if(nesting>1) error(32); |
| if(v->flags&DEFINED){ |
| if(!inline_flag||!cross_module){ |
| error(33,v->identifier); |
| }else{ |
| if(v->fi->first_ic){ |
| free_IC(v->fi->first_ic); |
| v->fi->first_ic=0; |
| } |
| } |
| }else{ |
| v->flags|=DEFINED; |
| v->dfilename=filename; |
| v->dline=line; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| } |
| if(storage_class!=EXTERN&&storage_class!=STATIC) error(34); |
| if(extern_flag&&!inline_flag) error(120); |
| if(storage_class==EXTERN&&!strcmp(v->identifier,"main")&&(!t->next||t->next->flags!=INT)) error(121); |
| if(!had_decl&&v->nesting==0&&v->storage_class==EXTERN&&strcmp("main",v->identifier)) |
| error(168,v->identifier); |
| while(!ecpp&&ctok->type!=LBRA){ |
| /* alter Stil */ |
| type *nt=declaration_specifiers();notdone=1;oldstyle=OLDSTYLE; |
| if(!ts) {error(35);} |
| while(notdone){ |
| int found=0; |
| imerk=ident;ident=vident;*vident=0; |
| ts=declarator(clone_typ(nt)); |
| ident=imerk; |
| if(!ts) {error(36);} |
| else{ |
| for(i=0;i<t->exact->count;i++){ |
| if(!strcmp((*t->exact->sl)[i].identifier,vident)){ |
| found=1; |
| if((*t->exact->sl)[i].styp){ |
| error(69,vident); |
| freetyp((*t->exact->sl)[i].styp); |
| } |
| /* typ[] in *typ */ |
| if(ISARRAY(ts->flags)) ts->flags=POINTER_TYPE(ts); |
| /* typ() in *typ() */ |
| if(ISFUNC(ts->flags)){ |
| type *new=new_typ(); |
| new->flags=POINTER_TYPE(ts); |
| new->next=ts; |
| ts=new; |
| } |
| if(!return_sc) return_sc=AUTO; |
| if(return_sc!=AUTO&&return_sc!=REGISTER) |
| {error(122);return_sc=AUTO;} |
| (*t->exact->sl)[i].storage_class=return_sc; |
| (*t->exact->sl)[i].reg=return_reg; |
| if(return_reg) error(219); |
| (*t->exact->sl)[i].styp=ts; |
| } |
| } |
| } |
| if(!found) {error(37,vident);} |
| killsp(); |
| if(ctok->type==COMMA) {next_token();killsp();} else notdone=0; |
| } |
| if(nt) freetyp(nt); |
| if(ctok->type==SEMIC){ |
| next_token();killsp(); |
| }else{ |
| error(54); |
| while(ctok->type!=LBRA&&ctok->type!=SEMIC){next_token();killsp();} |
| } |
| } |
| if(!ecpp&&t->exact->count==0){ |
| struct_list sl[1]; |
| if(DEBUG&1) printf("prototype converted to (void)\n"); |
| t->exact->count=1; |
| sl[0].identifier=empty; |
| sl[0].storage_class=AUTO; |
| sl[0].styp=new_typ(); |
| sl[0].styp->flags=VOID; |
| sl[0].styp->next=0; |
| sl[0].reg=0; |
| nesting--; |
| add_sl(t->exact,&sl); |
| nesting++; |
| } |
| if(om&&om->exact&&!compare_sd(om->exact,t->exact)) { |
| error(123); |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| } |
| nocode=0;currentpri=1; |
| /* enter_block();*/ |
| local_offset[1]=l2zm(0L); |
| return_var=0; |
| if(!v->vtyp) ierror(0); |
| #ifdef HAVE_REGPARMS |
| reg_handle=empty_reg_handle; |
| #endif |
| if(v->vtyp->next->flags==VOID){ |
| return_typ=0; |
| }else{ |
| return_typ=v->vtyp->next; |
| if(!ffreturn(return_typ)&&(return_typ->flags&NQ)!=VOID){ |
| /* Parameter fuer die Rueckgabe von Werten, die nicht in einem */ |
| /* Register sind. */ |
| type *rt=new_typ();int reg; |
| rt->flags=POINTER_TYPE(return_typ);rt->next=return_typ; |
| #ifdef HAVE_REGPARMS |
| reg=reg_parm(®_handle,rt,0,v->vtyp); |
| if(!reg){ |
| return_var=add_var(empty,clone_typ(rt),AUTO|PARAMETER|oldstyle,0); |
| }else{ |
| return_var=add_var(empty,clone_typ(rt),reg<0?(AUTO|PARAMETER|REGPARM|DBLPUSH|oldstyle):(AUTO|PARAMETER|REGPARM|oldstyle),0); |
| return_var->reg=reg; |
| } |
| #else |
| return_var=add_var(empty,clone_typ(rt),AUTO|PARAMETER|oldstyle,0); |
| #endif |
| return_var->flags|=DEFINED; |
| return_var->dfilename=filename; |
| return_var->dline=line; |
| free(rt); |
| } |
| } |
| first_ic=last_ic=0;ic_count=0;max_offset=l2zm(0L); |
| if(!zmleq(local_offset[1],Z0)) max_offset=local_offset[1]; |
| for(i=0;i<t->exact->count;i++){ |
| /* TODO: missing pointer for struct return */ |
| #ifdef HAVE_REGPARMS |
| int didrp=0; |
| if((*t->exact->sl)[i].styp){ |
| int tr; |
| tr=reg_parm(®_handle,(*t->exact->sl)[i].styp,0,t); |
| didrp=1; |
| if(!(*t->exact->sl)[i].reg) (*t->exact->sl)[i].reg=tr; |
| } |
| #endif |
| if(!(*t->exact->sl)[i].styp&&*(*t->exact->sl)[i].identifier){ |
| type *nt; |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| nt=new_typ(); |
| nt->flags=INT; |
| (*t->exact->sl)[i].styp=nt; |
| (*t->exact->sl)[i].storage_class=AUTO; |
| (*t->exact->sl)[i].reg=0; |
| error(124); |
| } |
| if(*(*t->exact->sl)[i].identifier){ |
| Var *tmp;int sc,tr; |
| sc=((*t->exact->sl)[i].storage_class|PARAMETER|oldstyle); |
| #ifdef HAVE_REGPARMS |
| if(!didrp){ |
| if(!t->exact->sl) ierror(0); |
| if(!(*t->exact->sl)[i].styp) ierror(0); |
| tr=reg_parm(®_handle,(*t->exact->sl)[i].styp,0,t); |
| if(!(*t->exact->sl)[i].reg) (*t->exact->sl)[i].reg=tr; |
| } |
| #endif |
| if((*t->exact->sl)[i].reg>0) sc|=REGPARM; |
| if((*t->exact->sl)[i].reg<0) sc|=(REGPARM|DBLPUSH); |
| tmp=add_var((*t->exact->sl)[i].identifier,clone_typ((*t->exact->sl)[i].styp),sc,0); |
| tmp->reg=(*t->exact->sl)[i].reg; |
| tmp->flags|=DEFINED; |
| tmp->dfilename=filename; |
| tmp->dline=line; |
| if(oldstyle){ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| freetyp((*t->exact->sl)[i].styp); |
| (*t->exact->sl)[i].styp=0; /* Prototype entfernen */ |
| } |
| } |
| } |
| if(oldstyle) t->exact->count=0; /* Prototype entfernen */ |
| /* local_offset[1]=l2zm(0L);*/ |
| return_label=++label; |
| function_calls=0;float_used=0;has_return=0;goto_used=0;vlas=0; |
| did_return_label=0; |
| for(i=1;i<=MAXR;i++) simple_scratch[i]=0; |
| if(v->storage_class==EXTERN&&(v->flags&INLINEFUNC)) |
| disallow_statics=1; |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| #endif |
| |
| if(c99){ |
| /* c99 predefined __func__ */ |
| type *ft=new_typ(); |
| Var *fnc; |
| |
| /* create type */ |
| ft->flags=ARRAY; |
| ft->size=l2zm((long)strlen(cur_func)+1); |
| ft->next=new_typ(); |
| ft->next->flags=CONST|CHAR; |
| |
| /* use string_expression() to create const_list */ |
| fnc=add_var("__func__",ft,STATIC,cl_from_string(cur_func,cur_func+strlen(cur_func))); |
| fnc->flags|=DEFINED; |
| } |
| |
| /* Generate intermediate code for function */ |
| compound_statement(); |
| |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| cur_funcv=0; |
| disallow_statics=0; |
| if(block_vla[nesting]) clearvl(); |
| if((v->vtyp->next->flags&NQ)!=VOID&&!has_return){ |
| if(strcmp(v->identifier,"main")) error(173,v->identifier); |
| else error(174,v->identifier); |
| } |
| #if 0 |
| {int i; |
| for(i=1;i<=MAXR;i++) if(regs[i]!=regsa[i]) {printf("Register %s:\n",regnames[i]);ierror(0);} |
| } |
| #endif |
| if(!did_return_label){ |
| clear_main_ret(); |
| gen_label(return_label); |
| } |
| /* backpatch code for jumps out of vla-scope if necessary */ |
| if(vlas) |
| vla_jump_fix(); |
| if(cross_module){ |
| if(!v->fi) v->fi=new_fi(); |
| v->fi->statics=first_var[0]; |
| }else if(first_ic&&errors==0){ |
| if((c_flags[2]&USEDFLAG)&&ic1){fprintf(ic1,"function %s\n",v->identifier); pric(ic1,first_ic);} |
| vl1=first_var[0]; |
| vl2=first_var[1]; |
| vl3=merk_varf; |
| optimize(optflags,v); |
| if((c_flags[3]&USEDFLAG)&&ic2){fprintf(ic2,"function %s\n",v->identifier); pric(ic2,first_ic);} |
| if(out&&!only_inline&&!(c_flags[5]&USEDFLAG)){ |
| memset(regs_modified,0,RSIZE); |
| gen_code(out,first_ic,v,max_offset); |
| static_stack_check(v); |
| v->flags|=GENERATED; |
| #ifdef HAVE_REGS_MODIFIED |
| if(!v->fi) v->fi=new_fi(); |
| if(v->fi->flags&ALL_REGS) |
| { |
| int i; |
| for(i=1;i<=MAXR;i++){ |
| if(reg_pair(i,&rp)){ |
| if(BTST(regs_modified,i)){ |
| BSET(regs_modified,rp.r1); |
| BSET(regs_modified,rp.r2); |
| }else{ |
| if(BTST(regs_modified,rp.r1)||BTST(regs_modified,rp.r2)) |
| BSET(regs_modified,i); |
| } |
| } |
| } |
| memcpy(v->fi->regs_modified,regs_modified,RSIZE); |
| v->fi->flags|=ALL_REGS; |
| } |
| #endif |
| } |
| /*if(DEBUG&8192){fprintf(ic2,"function %s, after gen_code\n",v->identifier); pric(ic2,first_ic);}*/ |
| free_IC(first_ic); |
| first_ic=last_ic=0; |
| } |
| if(cross_module){ |
| if(!v->fi) v->fi=new_fi(); |
| v->fi->first_ic=first_ic; |
| v->fi->last_ic=last_ic; |
| first_ic=last_ic=0; |
| } |
| if(v->fi&&v->fi->first_ic){ |
| Var *vp; |
| if(DEBUG&1) printf("leave block %d (inline-version)\n",nesting); |
| if(block_vla[nesting]) clearvl(); |
| if(nesting!=1) ierror(0); |
| if(merk_varl) merk_varl->next=first_var[nesting]; else merk_varf=first_var[nesting]; |
| if(last_var[nesting]) merk_varl=last_var[nesting]; |
| if(merk_sil) merk_sil->next=first_si[nesting]; else merk_sif=first_si[nesting]; |
| if(last_si[nesting]) merk_sil=last_si[nesting]; |
| if(merk_sdl) merk_sdl->next=first_sd[nesting]; else merk_sdf=first_sd[nesting]; |
| if(last_sd[nesting]) merk_sdl=last_sd[nesting]; |
| if(merk_ilistl) merk_ilistl->next=first_ilist[nesting]; else merk_ilistf=first_ilist[nesting]; |
| if(last_ilist[nesting]) merk_ilistl=last_ilist[nesting]; |
| |
| if(merk_varf&&!only_inline&&!cross_module) gen_vars(merk_varf); |
| if(first_llist) free_llist(first_llist); |
| first_llist=0; |
| if(first_clist) free_clist(first_clist); |
| first_clist=0; |
| if(merk_sif) free_si(merk_sif); |
| /* struct-declarations erst ganz am Schluss loeschen. Um zu vermeiden, */ |
| /* dass struct-declarations in Prototypen frei werden und dann eine */ |
| /* spaetere struct, dieselbe Adresse bekommt und dadurch gleich wird. */ |
| /* Nicht sehr schoen - wenn moeglich noch mal aendern. */ |
| /* if(merk_sdf) free_sd(merk_sdf);*/ |
| /* hier noch was ueberlegen */ |
| /* if(merk_ilistf) free_ilist(merk_ilistf);*/ |
| nesting--; |
| v->fi->vars=merk_varf; |
| /* v->fi->vars=first_var[1];*/ |
| /* keine echten Parameter=>keine negativen Offsets */ |
| /* vp=first_var[1];*/ |
| if(!cross_module){ |
| vp=merk_varf; |
| while(vp){ |
| if(vp->storage_class==AUTO||vp->storage_class==REGISTER){ |
| /*if(DEBUG&1024) printf("handling variable %s(%ld)/%p\n",vp->identifier,zm2l(vp->offset),(void*)vp);*/ |
| if(!zmleq(l2zm(0L),vp->offset)){ |
| vp->offset=l2zm(0L); |
| if(DEBUG&1024) printf("converted parameter <%s>(%ld) for inlining\n",vp->identifier,(long)zm2l(vp->offset)); |
| }else vp->offset=l2zm(4L); /* Dummy, da recalc_offsets? */ |
| } |
| vp=vp->next; |
| } |
| } |
| }else{ |
| leave_block(); |
| } |
| if(only_inline==2) only_inline=0; |
| cur_func="oops, I forgot it"; |
| }else{ |
| if(makeint) error(125); |
| if(ctok->type==SEMIC) next_token(); else error(54); |
| if(ISFUNC(t->flags)&&t->exact){ |
| struct_declaration *sd=t->exact;int i,f; |
| for(f=0,i=0;i<sd->count;i++) |
| if(!(*sd->sl)[i].styp){error(126);f=1;} |
| if(f){ |
| for(i=0;i<sd->count;i++) if((*sd->sl)[i].styp) freetyp((*sd->sl)[i].styp); |
| sd->count=0; |
| } |
| } |
| } |
| if(old) freetyp(old); |
| } |
| int compatible_types(type *a,type *b,int qual) |
| /* Vergleicht, ob Typ beider Typen gleich ist, const/volatile */ |
| /* werden laut ANSI nicht beruecksichtigt. */ |
| { |
| struct_declaration *sd; |
| int af=a->flags&qual,bf=b->flags&qual; |
| if(af!=bf) return(0); |
| af&=NQ;bf&=NQ; |
| if(ISFUNC(af)){ |
| if(a->exact->count&&!compare_sd(a->exact,b->exact)) return(0); |
| } |
| if(ISSTRUCT(af)||ISUNION(af)){ |
| if(cross_module&&a->exact->tunit!=b->exact->tunit) return 1; |
| if(a->exact!=b->exact) return(0); |
| } |
| if(ISARRAY(af)){ |
| if(!zmeqto(a->size,l2zm(0L))&&!zmeqto(b->size,l2zm(0L))&&!zmeqto(a->size,b->size)) return(0); |
| } |
| if(a->next==0&&b->next!=0) return(0); |
| if(a->next!=0&&b->next==0) return(0); |
| if(a->next==0&&b->next==0) return(1); |
| if(qual!=NQ) qual=(NU|CONST|VOLATILE); |
| return(compatible_types(a->next,b->next,qual)); |
| } |
| int compare_sd(struct_declaration *a,struct_declaration *b) |
| /* Vergleicht, ob zwei struct_declarations identisch sind */ |
| /* Wird nur nur fuer Prototypen benutzt, leere Liste immer gleich. */ |
| { |
| int i; |
| if(!a->count||!b->count) return(1); |
| if(a->count!=b->count) return(0); |
| for(i=0;i<a->count;i++){ |
| if((*a->sl)[i].styp&&(*b->sl)[i].styp&&!compatible_types((*a->sl)[i].styp,(*b->sl)[i].styp,NU)) return(0); |
| if((*a->sl)[i].reg!=(*b->sl)[i].reg) {error(368);return 0;} |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| #endif |
| } |
| return(1); |
| } |
| void free_clist(const_list *p) |
| /* Gibt clist frei. */ |
| { |
| const_list *merk; |
| return; |
| while(p){ |
| merk=p->next; |
| if(p->other) free_clist(p->other); |
| if(p->tree) free_expression(p->tree); |
| free(p); |
| p=merk; |
| } |
| } |
| void gen_clist(FILE *,type *,const_list *); |
| |
| void gen_vars(Var *v) |
| /* Generiert Variablen. */ |
| { |
| int mode,al,first_pass=1;Var *p; |
| if(errors!=0||(c_flags[5]&USEDFLAG)) return; |
| if(optsize) |
| al=zm2l(maxalign); |
| else |
| al=0; |
| for(;al>=0;al--){ |
| for(mode=0;mode<3;mode++){ |
| int i,flag; |
| for(p=v;p;p=p->next){ |
| if(p->flags&NEEDS) continue; |
| if(optsize&&zm2l(falign(p->vtyp))!=al) |
| continue; |
| if(cross_module&&!(p->flags&REFERENCED)) continue; |
| if(DEBUG&2) printf("gen_var(): %s\n",p->identifier); |
| if(p->storage_class==STATIC||p->storage_class==EXTERN){ |
| if(!(p->flags&GENERATED)){ |
| if(p->storage_class==EXTERN&&!(p->flags&(USEDASSOURCE|USEDASDEST))&&!(p->flags&(TENTATIVE|DEFINED))) continue; |
| if(p->storage_class==STATIC&&p->nesting>0&&!(p->flags&(USEDASSOURCE|USEDASDEST))) continue; |
| /* erst konstante initialisierte Daten */ |
| if(mode==0){ |
| if(!p->clist) continue; |
| if(!(p->vtyp->flags&(CONST|STRINGCONST))){ |
| type *t=p->vtyp;int f=0; |
| do{ |
| if(t->flags&(CONST|STRINGCONST)) break; |
| if(!ISARRAY(t->flags)){f=1;break;} |
| t=t->next; |
| }while(1); |
| if(f) continue; |
| } |
| } |
| /* dann initiolisierte */ |
| if(mode==1&&!p->clist) continue; |
| /* und dann der Rest */ |
| |
| if(mode==2&&p->clist) continue; |
| |
| if(!(p->flags&(TENTATIVE|DEFINED))){ |
| if(!((p->vtyp->flags&NQ)==FUNKT)||!p->fi||!p->fi->inline_asm){ |
| if(mask_opt){ |
| if((p->flags&PRINTFLIKE)&&!strstr(p->identifier,".")) needs("vfprintf"); |
| if((p->flags&SCANFLIKE)&&!strstr(p->identifier,".")) needs("vfscanf"); |
| } |
| gen_var_head(out,p); |
| } |
| if(p->storage_class==STATIC&&(!p->fi||!p->fi->inline_asm)) error(127,p->identifier); |
| continue; |
| }else{ |
| /*gen_align(out,falign(p->vtyp));*/ |
| } |
| if(!((p->vtyp->flags&NQ)==FUNKT)||!p->fi||!p->fi->inline_asm){ |
| if(mask_opt){ |
| if((p->flags&PRINTFLIKE)&&!strstr(p->identifier,".")) needs("vfprintf"); |
| if((p->flags&SCANFLIKE)&&!strstr(p->identifier,".")) needs("vfscanf"); |
| } |
| gen_var_head(out,p); |
| } |
| if(!p->clist){ |
| if(type_uncomplete(p->vtyp)) error(202,p->identifier); |
| gen_ds(out,szof(p->vtyp),p->vtyp); |
| }else{ |
| gen_clist(out,p->vtyp,p->clist); |
| } |
| p->flags|=GENERATED; |
| }else if(p->flags&INLINEEXT){ |
| /* a function was declared extern inline and defined; |
| we have to create external linkage */ |
| int m=p->flags; |
| /* pretend, it was only declared, but not defined and remove |
| INLINEEXT */ |
| p->flags&=~(DEFINED|INLINEEXT); |
| gen_var_head(out,p); |
| p->flags|=DEFINED; |
| } |
| } |
| } |
| first_pass=0; |
| } |
| } |
| if(mask_opt){ |
| for(p=v;p;p=p->next) |
| if(p->flags&NEEDS) gen_var_head(out,p); |
| } |
| } |
| |
| /* creates code that dynamically initializes a variable */ |
| void dynamic_init(Var *v,type *t,const_list *cl,zmax of,int noconst) |
| { |
| int f=t->flags; |
| if(ISARRAY(f)){ |
| zmax i; |
| for(i=l2zm(0L);!zmleq(t->size,i);i=zmadd(i,l2zm(1L))){ |
| if(cl&&zmeqto(cl->idx,i)){ |
| dynamic_init(v,t->next,cl->other,of,noconst); |
| cl=cl->next; |
| }else{ |
| dynamic_init(v,t->next,0,of,noconst); |
| } |
| of=zmadd(of,szof(t->next)); |
| } |
| }else if(ISUNION(f)&&(!cl||!cl->tree)){ |
| dynamic_init(v,(*t->exact->sl)[cl?zm2l(cl->idx):0].styp,cl?cl->other:0,of,noconst); |
| }else if(ISSTRUCT(f)&&(!cl||!cl->tree)){ |
| zmax al;int fl;type *st; |
| int bfo,i; |
| for(i=0;i<t->exact->count&&cl;i++){ |
| if(!cl->other){ |
| if(errors==0) |
| ierror(0); |
| return; |
| } |
| st=(*t->exact->sl)[i].styp; |
| al=(*t->exact->sl)[i].align; |
| if(!(*t->exact->sl)[i].identifier) ierror(0); |
| bfo=(*t->exact->sl)[i].bfoffset; |
| if(!zmeqto(zmmod(of,al),l2zm(0L))){ |
| of=zmadd(of,zmsub(al,zmmod(of,al))); |
| } |
| if(bfo>=0){ |
| int bfs=(*t->exact->sl)[i].bfsize; |
| static obj dest = {0}; |
| |
| dest.flags=VAR; |
| dest.v=v; |
| dest.val.vmax=of; |
| |
| if(bfo==0){ |
| /* first clear entire bitfield */ |
| IC *new=new_IC(); |
| new->code=ASSIGN; |
| new->z=dest; |
| new->typf=st->flags; |
| new->q2.val.vmax=sizetab[st->flags&NQ]; |
| new->q1.flags=KONST; |
| new->q1.val.vmax=l2zm(0L); |
| eval_const(&new->q1.val,MAXINT); |
| insert_const(&new->q1.val,st->flags&NU); |
| add_IC(new); |
| } |
| |
| /* bitfield */ |
| if(!zmeqto(cl->idx,l2zm(i))||!cl->other){ |
| /* nothing to do, initialized before */ |
| }else if(cl->other->tree){ |
| obj dummy; |
| gen_IC(cl->other->tree,0,0); |
| convert(cl->other->tree,st->flags); |
| insert_bitfield(&dest,&cl->other->tree->o,&cl->other->tree->o,bfs,bfo,st->flags,1); |
| cl=cl->next; |
| }else{ |
| static obj val = {0}; |
| val.flags=KONST; |
| val.val=cl->other->val; |
| insert_bitfield(&dest,&val,&val,bfs,bfo,st->flags,1); |
| cl=cl->next; |
| } |
| if(i+1>=t->exact->count||(*t->exact->sl)[i+1].bfoffset<=0||!cl){ |
| of=zmadd(of,szof(st)); |
| } |
| }else{ |
| if(zmeqto(l2zm((long)i),cl->idx)){ |
| dynamic_init(v,st,cl->other,of,noconst); |
| cl=cl->next; |
| }else |
| dynamic_init(v,st,0,of,noconst); |
| of=zmadd(of,szof(st)); |
| } |
| } |
| for(;i<t->exact->count;i++){ |
| st=(*t->exact->sl)[i].styp; |
| al=(*t->exact->sl)[i].align; |
| bfo=(*t->exact->sl)[i].bfoffset; |
| if(bfo>0) continue; |
| if(!zmeqto(zmmod(of,al),l2zm(0L))){ |
| of=zmadd(of,zmsub(al,zmmod(of,al))); |
| } |
| dynamic_init(v,st,0,of,noconst); |
| of=zmadd(of,szof(st)); |
| } |
| }else{ |
| IC *new; |
| if(noconst&&(!cl||!cl->tree)) |
| return; |
| new=new_IC(); |
| new->code=ASSIGN; |
| new->z.flags=VAR; |
| new->z.v=v; |
| new->z.val.vmax=of; |
| new->typf=t->flags; |
| new->q2.val.vmax=szof(t); |
| if(!cl){ |
| new->q1.flags=KONST; |
| gval.vmax=l2zm(0L); |
| eval_const(&gval,MAXINT); |
| insert_const(&new->q1.val,t->flags&NU); |
| }else if(cl->tree){ |
| gen_IC(cl->tree,0,0); |
| if(ISSCALAR(t->flags)) |
| convert(cl->tree,t->flags); |
| new->q1=cl->tree->o; |
| }else{ |
| new->q1.flags=KONST; |
| new->q1.val=cl->val; |
| } |
| add_IC(new); |
| } |
| } |
| |
| |
| void gen_clist(FILE *f,type *t,const_list *cl) |
| /* Generiert dc fuer const_list. */ |
| { |
| int i,bfo,bfs;zmax sz;zumax bfval=ul2zum(0UL); |
| |
| #if 0 |
| for(i=0;i<(int)szof(t);i++){ |
| zuchar c;int s; |
| s=get_clist_byte(t,cl,i,&c); |
| printf("%03d: 0x%02x (%d)\n",i,(int)c,s); |
| } |
| #endif |
| |
| |
| if(ISARRAY(t->flags)){ |
| for(sz=l2zm(0L);!zmleq(t->size,sz)&&cl;cl=cl->next){ |
| if(!cl->other){ierror(0);return;} |
| if(!zmeqto(sz,cl->idx)) |
| gen_ds(f,zmmult(zmsub(cl->idx,sz),szof(t->next)),t->next); |
| |
| gen_clist(f,t->next,cl->other); |
| sz=zmadd(cl->idx,l2zm(1L)); |
| } |
| if(!zmleq(t->size,sz)) gen_ds(f,zmmult(zmsub(t->size,sz),szof(t->next)),t->next); |
| return; |
| } |
| if(ISUNION(t->flags)){ |
| int i=zm2l(cl->idx); |
| if(cl&&cl->tree){ |
| /* union initialized by another union */ |
| gen_ds(f,szof(t),t); |
| }else{ |
| gen_clist(f,(*t->exact->sl)[i].styp,cl->other); |
| sz=zmsub(szof(t),szof((*t->exact->sl)[i].styp)); |
| if(!zmeqto(sz,l2zm(0L))) gen_ds(f,sz,0); |
| } |
| return; |
| } |
| if(ISSTRUCT(t->flags)){ |
| zmax al;int fl;type *st; |
| sz=l2zm(0L); |
| if(cl&&cl->tree){ |
| /* initialized by another */ |
| gen_ds(f,szof(t),t); |
| sz=zmadd(sz,szof(t)); |
| }else{ |
| for(i=0;i<t->exact->count&&cl;i++){ |
| if(!cl->other){ierror(0);return;} |
| st=(*t->exact->sl)[i].styp; |
| al=(*t->exact->sl)[i].align; |
| if(!(*t->exact->sl)[i].identifier) ierror(0); |
| bfo=(*t->exact->sl)[i].bfoffset; |
| if(!zmeqto(zmmod(sz,al),l2zm(0L))){ |
| gen_ds(f,zmsub(al,zmmod(sz,al)),0); |
| sz=zmadd(sz,zmsub(al,zmmod(sz,al))); |
| } |
| if(bfo>=0){ |
| /* bitfield */ |
| if((*t->exact->sl)[i].identifier[0]){ |
| bfs=(*t->exact->sl)[i].bfsize; |
| if(zmeqto(l2zm((long)i),cl->idx)){ |
| eval_const(&cl->other->val,st->flags); |
| cl=cl->next; |
| }else{ |
| vumax=ul2zum(0UL); |
| } |
| vumax=zumand(vumax,zumsub(zumlshift(ul2zum(1UL),ul2zum((unsigned long)bfs)),ul2zum(1UL))); |
| bfval=zumor(bfval,zumlshift(vumax,ul2zum((unsigned long)bflayout(bfo,bfs,st->flags)))); |
| } |
| if(i+1>=t->exact->count||(*t->exact->sl)[i+1].bfoffset<=0||!cl){ |
| /* last bitfield in integer */ |
| const_list bfcl; |
| gval.vumax=bfval; |
| eval_const(&gval,UNSIGNED|MAXINT); |
| insert_const(&bfcl.val,st->flags&NU); |
| bfcl.tree=0; |
| gen_dc(f,st->flags&NU,&bfcl); |
| bfval=ul2zum(0L); |
| sz=zmadd(sz,szof(st)); |
| } |
| }else{ |
| if(zmeqto(l2zm((long)i),cl->idx)){ |
| gen_clist(f,st,cl->other); |
| cl=cl->next; |
| }else |
| gen_ds(f,szof(st),st); |
| sz=zmadd(sz,szof(st)); |
| } |
| } |
| for(;i<t->exact->count;i++){ |
| st=(*t->exact->sl)[i].styp; |
| al=(*t->exact->sl)[i].align; |
| bfo=(*t->exact->sl)[i].bfoffset; |
| if(bfo>0) continue; |
| if(!zmeqto(zmmod(sz,al),l2zm(0L))){ |
| gen_ds(f,zmsub(al,zmmod(sz,al)),0); |
| sz=zmadd(sz,zmsub(al,zmmod(sz,al))); |
| } |
| gen_ds(f,szof((*t->exact->sl)[i].styp),(*t->exact->sl)[i].styp); |
| sz=zmadd(sz,szof(st)); |
| } |
| } |
| al=falign(t); |
| if(!zmeqto(zmmod(sz,al),l2zm(0L))) |
| gen_ds(f,zmsub(al,zmmod(sz,al)),0); |
| return; |
| } |
| |
| if(cl->tree) cl->tree->o.am=0; |
| |
| if(zmeqto(cl->idx,l2zm(-1L))) |
| gen_ds(f,szof(t),t); |
| else |
| gen_dc(f,t->flags&NU,cl); |
| } |
| |
| /* finds the correct place in a const list to insert new initializer */ |
| const_list *insert_cl(const_list *old,zmax idx) |
| { |
| const_list *p,*cl=0; |
| if(old&&zmleq(old->idx,idx)){ |
| p=old; |
| do{ |
| if(zmeqto(p->idx,idx)){ |
| /* found existing entry */ |
| cl=p; |
| break; |
| } |
| if(!p->next||!zmleq(p->next->idx,idx)) |
| break; |
| p=p->next; |
| }while(p); |
| }else |
| p=0; |
| /* we need a new entry */ |
| if(!cl){ |
| cl=mymalloc(CLS); |
| cl->tree=0; |
| cl->other=0; |
| cl->idx=idx; |
| if(p){ |
| cl->next=p->next; |
| p->next=cl; |
| }else |
| cl->next=old; |
| } |
| return cl; |
| } |
| |
| const_list *designator(type *t,const_list *cl) |
| { |
| int f=t->flags&NQ; |
| np tree; |
| if(!c99) return 0; |
| if(ISARRAY(f)&&ctok->type==LBRK){ |
| next_token(); |
| killsp(); |
| tree=expression(); |
| if(ctok->type!=RBRK) |
| error(62); |
| else |
| {next_token();killsp();} |
| if(!type_expression(tree,0)){ |
| /* error("incorrect constant expression");*/ |
| }else{ |
| if(tree->sidefx) error(60); |
| if(tree->flags!=CEXPR||!ISINT(tree->ntyp->flags)){ |
| error(19); |
| }else{ |
| /* check index for valid range */ |
| eval_constn(tree); |
| if(!zmleq(l2zm(0L),vmax)) {error(354);vmax=l2zm(0L);} |
| if(!zmeqto(t->size,l2zm(0L))&&zmleq(t->size,vmax)) {error(354);vmax=l2zm(0L);} |
| |
| cl=insert_cl(cl,vmax); |
| |
| return cl; |
| } |
| } |
| }else if((ISSTRUCT(f)||ISUNION(f))&&ctok->type==DOT){ |
| next_token(); |
| killsp(); |
| if(ctok->type!=NAME){ |
| error(53); |
| }else{ |
| int i,n=-1; |
| for(i=0;i<t->exact->count;i++) |
| if(!strcmp((*t->exact->sl)[i].identifier,ctok->name)) n=i; |
| if(n<0){ |
| error(23,ctok->name); |
| return 0; |
| } |
| next_token(); |
| killsp(); |
| |
| if(!ISUNION(f)||!cl) |
| cl=insert_cl(cl,l2zm((long)n)); |
| |
| return cl; |
| } |
| } |
| return 0; |
| } |
| |
| /* declare a builtin function with up to two scalar arguments */ |
| Var *declare_builtin(char *name,int ztyp,int q1typ,int q1reg,int q2typ,int q2reg,int nosidefx,char *asm) |
| { |
| struct_declaration *sd; |
| type *t; |
| Var *v; |
| int args; |
| if(!(v=find_ext_var(name))){ |
| sd=mymalloc(sizeof(*sd)); |
| if(q1typ==0) args=1; |
| else if(q2typ!=0) args=3; |
| else args=2; |
| sd->sl=mymalloc(args*sizeof(struct_list)); |
| memset(sd->sl,0,args*sizeof(struct_list)); |
| sd->count=args; |
| if(q1typ){ |
| (*sd->sl)[0].styp=new_typ(); |
| (*sd->sl)[0].styp->flags=q1typ; |
| (*sd->sl)[0].reg=q1reg; |
| } |
| if(q2typ){ |
| (*sd->sl)[1].styp=new_typ(); |
| (*sd->sl)[1].styp->flags=q2typ; |
| (*sd->sl)[1].reg=q2reg; |
| } |
| (*sd->sl)[args-1].styp=new_typ(); |
| (*sd->sl)[args-1].styp->flags=VOID; |
| (*sd->sl)[args-1].reg=0; |
| t=new_typ(); |
| t->flags=FUNKT; |
| t->exact=add_sd(sd,FUNKT); |
| t->next=new_typ(); |
| t->next->flags=ztyp; |
| v=add_var(name,t,EXTERN,0); |
| v->flags|=BUILTIN; |
| if(asm||nosidefx){ |
| v->fi=new_fi(); |
| if(asm) v->fi->inline_asm=asm; |
| if(nosidefx){ |
| v->fi->call_cnt=v->fi->use_cnt=v->fi->change_cnt=0; |
| v->fi->flags=ALL_CALLS|ALL_USES|ALL_MODS|ALWAYS_RETURNS|NOSIDEFX; |
| } |
| } |
| } |
| return v; |
| } |
| |
| |
| const_list *initialization(type *t,int noconst,int level,int desi,struct_declaration *fstruct,const_list *first) |
| /* Traegt eine Initialisierung in eine const_list ein. */ |
| { |
| const_list *cl,**prev; |
| np tree,tree2; |
| int bracket,desi_follows=0; |
| zmax i; |
| token mtok; |
| |
| int f=t->flags&NQ; |
| if(ISFUNC(f)){error(42);return(0);} |
| if(ctok->type==LBRA){next_token();killsp();bracket=1;} else bracket=0; |
| if(ISARRAY(f)){ |
| #ifdef HAVE_MISRA |
| /* removed */ |
| #endif |
| if(t->dsize){ |
| error(358); |
| }else if(zmeqto(t->size,l2zm(0L))&&level!=0){ |
| error(359); |
| }else if(ctok->type==T_STRING&&t->next&&(t->next->flags&NQ)==CHAR){ |
| killsp(); |
| tree=string_expression(); |
| first=tree->cl; |
| free_expression(tree); |
| }else{ |
| const_list *last=first; |
| if(level==0&&!bracket) error(157); |
| for(i=l2zm(0L);desi_follows||((zmeqto(t->size,l2zm(0L))||!zmleq(t->size,i)||ctok->type==LBRK)&&ctok->type!=RBRA);i=zmadd(i,l2zm(1L))){ |
| if(!zmleq(i,0)){ |
| if(ctok->type==COMMA){next_token();killsp();} else break; |
| if(ctok->type==RBRA) break; |
| } |
| /* check for first designated initializer */ |
| cl=designator(t,first); |
| if(!cl){ |
| /* no designator */ |
| cl=insert_cl(last,i); |
| cl->other=initialization(t->next,c99?noconst:0,level+1,0,fstruct,cl->other); |
| if(cl->other&&zmeqto(cl->other->idx,l2zm(-2L))){ |
| first=cl->other; |
| first->other=0; |
| break; |
| } |
| }else{ |
| /* designator: store current object and handle remaining designators */ |
| i=cl->idx; |
| if(ctok->type!=ASGN){ |
| if(ctok->type!=LBRK&&ctok->type!=DOT) |
| error(355); |
| }else{ |
| cl->other=0; |
| next_token();killsp(); |
| } |
| cl->other=initialization(t->next,c99?noconst:0,level+1,1,fstruct,cl->other); |
| } |
| if(cl->next==first) first=cl; |
| last=cl; |
| killsp(); |
| if(desi&&!bracket) |
| break; |
| desi_follows=0; |
| if(ctok->type==COMMA){ |
| copy_token(&mtok,ctok); |
| next_token();killsp(); |
| if(ctok->type==LBRK) |
| desi_follows=1; |
| push_token(&mtok); |
| } |
| } |
| |
| if(bracket&&zmeqto(i,l2zm(0L))) error(360); |
| |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| } |
| }else if(ISSTRUCT(f)&&(bracket||!noconst||c99)){ |
| if(t->exact->count<=0) |
| {error(43);return(0);} |
| #ifdef HAVE_ECPP |
| /* removed */ |
| #endif |
| prev=0; |
| if(level==0&&!bracket&&!c99) error(157); |
| for(i=l2zm(0L);desi_follows||(!zmleq(t->exact->count,i)&&ctok->type!=RBRA);i=zmadd(i,l2zm(1L))){ |
| if(!desi_follows&&(*t->exact->sl)[zm2l(i)].identifier[0]==0) continue; /* unnamed bitfield */ |
| if(!zmleq(i,0)){ |
| if(ctok->type==COMMA){next_token();killsp();} else break; |
| if(ctok->type==RBRA) break; |
| } |
| cl=designator(t,first); |
| |
| if(!cl){ |
| cl=insert_cl(first,l2zm((long)i)); |
| cl->other=initialization((*t->exact->sl)[zm2l(i)].styp,c99?noconst:0,level+1,0,!fstruct&&!bracket&&zmeqto(i,l2zm(0L))?t->exact:fstruct,cl->other); |
| if(cl->other&&zmeqto(cl->other->idx,l2zm(-2L))){ |
| if(fstruct){ |
| first=cl->other; |
| first->other=0; |
| }else{ |
| *cl=*cl->other; |
| cl->idx=l2zm(-1L); |
| cl->other=0; |
| first=cl; |
| } |
| break; |
| } |
| }else{ |
| i=zm2l(cl->idx); |
| if(ctok->type!=ASGN){ |
| if(ctok->type!=LBRK&&ctok->type!=DOT) |
| error(355); |
| }else{ |
| next_token();killsp(); |
| cl->other=0; |
| } |
| cl->other=initialization((*t->exact->sl)[zm2l(i)].styp,c99?noconst:0,level+1,1,fstruct,cl->other); |
| } |
| if(cl->next==first) first=cl; |
| if(desi&&!bracket) |
| break; |
| desi_follows=0; |
| if(ctok->type==COMMA){ |
| copy_token(&mtok,ctok); |
| next_token();killsp(); |
| if(ctok->type==DOT) |
| desi_follows=1; |
| push_token(&mtok); |
| } |
| } |
| |
| if(bracket&&zmeqto(i,l2zm(0L))) error(360); |
| |
| #ifdef HAVE_MISRA |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |
| |
| }else if(ISUNION(f)&&(c99||bracket||!noconst)){ |
| if(t->exact->count<=0) |
| {error(44);return(0);} |
| |
| if(level==0&&!bracket&&!c99) error(157); |
| desi_follows=1; |
| while(desi_follows){ |
| cl=designator(t,first); |
| |
| if(!cl){ |
| cl=insert_cl(first,l2zm((long)0)); |
| cl->other=initialization((*t->exact->sl)[0].styp,c99?noconst:0,level+1,0,!fstruct&&!bracket?t->exact:fstruct,cl->other); |
| if(cl->other&&zmeqto(cl->other->idx,l2zm(-2L))){ |
| if(fstruct){ |
| first=cl->other; |
| first->other=0; |
| }else{ |
| *cl=*cl->other; |
| cl->other=0; |
| cl->idx=l2zm(-1L); |
| first=cl; |
| } |
| break; |
| } |
| }else{ |
| i=zm2l(cl->idx); |
| if(ctok->type!=ASGN){ |
| if(ctok->type!=LBRK&&ctok->type!=DOT) |
| error(355); |
| }else{ |
| next_token();killsp(); |
| cl->other=0; |
| } |
| cl->other=initialization((*t->exact->sl)[zm2l(i)].styp,c99?noconst:0,level+1,1,fstruct,cl->other); |
| } |
| first=cl; |
| if(desi&&!bracket) |
| break; |
| desi_follows=0; |
| if(ctok->type==COMMA){ |
| copy_token(&mtok,ctok); |
| next_token();killsp(); |
| if(ctok->type==DOT) |
| desi_follows=1; |
| else |
| push_token(&mtok); |
| } |
| } |
| }else{ |
| int oldconst=const_expr; |
| tree2=tree=assignment_expression(); |
| |
| if(!tree){error(45);return(0);} |
| if(!noconst) const_expr=1; |
| if(!type_expression(tree,t)){free_expression(tree); const_expr=oldconst;return 0;} |
| const_expr=oldconst; |
| |
| tree=makepointer(tree); |
| |
| /* check for complete assignment in dynamic initialization */ |
| if(noconst&&(ISSTRUCT(tree->ntyp->flags)||ISUNION(tree->ntyp->flags))&&fstruct==tree->ntyp->exact){ |
| first=mymalloc(CLS); |
| first->tree=tree; |
| first->next=first->other=0; |
| first->idx=l2zm(-2L); |
| return first; |
| } |
| |
| if(!test_assignment(t,tree)){free_expression(tree); return 0;} |
| if(!noconst){ |
| /* nur Konstanten erlaubt (bei Arrays/Strukturen etc. oder static) */ |
| if(tree->flags!=CEXPR){ |
| /*while(tree->flags==CAST) tree=tree->left;*/ |
| if(!tree->sidefx/*tree->flags==ADDRESS||tree->flags==ADDRESSS||tree->flags==ADDRESSA*/){ |
| const_expr=1; |
| gen_IC(tree,0,0); |
| const_expr=oldconst; |
| if(!(tree->o.flags&VARADR)){ |
| /* hier fehlen noch viele Pruefungen */ |
| free_expression(tree);error(46); |
| return(0); |
| } |
| tree->o.v->flags|=USEDASADR; |
| first=mymalloc(CLS); |
| first->next=first->other=0; |
| first->tree=tree; |
| first->idx=l2zm(0L); |
| killsp(); |
| }else{ |
| free_expression(tree);error(46); |
| return(0); |
| } |
| }else{ |
| first=mymalloc(CLS); |
| first->idx=l2zm(0L); |
| first->next=first->other=0; |
| first->tree=0; |
| eval_constn(tree); |
| tree->ntyp->flags=t->flags; |
| insert_constn(tree); |
| first->val=tree->val; |
| free_expression(tree2); |
| killsp(); |
| } |
| }else{ |
| /* auch anderes erlaubt */ |
| first=mymalloc(CLS); |
| first->next=first->other=0; |
| first->tree=tree; |
| killsp(); |
| if(!tree->sidefx){ |
| if(tree->flags==CEXPR){ |
| eval_constn(tree); |
| tree->ntyp->flags=t->flags; |
| insert_constn(tree); |
| first->val=tree->val; |
| first->tree=0; |
| first->idx=l2zm(0L); |
| init_const_sz=zmadd(init_const_sz,szof(tree->ntyp)); |
| init_const_cnt++; |
| free_expression(tree2); |
| }else{ |
| first->idx=l2zm(-1L); |
| init_dyn_sz=zmadd(init_dyn_sz,szof(tree->ntyp)); |
| init_dyn_cnt++; |
| } |
| }else{ |
| first->idx=l2zm(-1L); |
| init_dyn_sz=zmadd(init_dyn_sz,szof(tree->ntyp)); |
| init_dyn_cnt++; |
| } |
| } |
| } |
| if(bracket){ |
| if(ctok->type==COMMA){next_token();killsp();} |
| if(ctok->type==RBRA){next_token();killsp();} else error(128); |
| } |
| return(first); |
| } |
| #ifdef HAVE_ECPP |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| /* removed */ |
| #endif |