home *** CD-ROM | disk | FTP | other *** search
- /* $VER: vbcc (declaration.c) V0.4 */
-
- #include "vbc.h"
-
- static char FILE_[]=__FILE__;
-
- #define PARAMETER 8
- #define OLDSTYLE 16
-
- struct const_list *initialization(struct Typ *,int,int);
- int test_assignment(struct Typ *,np);
- int return_sc,return_reg,has_return;
-
- extern int float_used;
- extern void optimize(long,struct Var *);
-
- int settyp(int typnew, int typold)
- /* Unterroutine fuer declaration_specifiers(). */
- {
- static int warned_long_double;
- 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){
- if(!warned_long_double){error(204);warned_long_double=1;}
- return(DOUBLE);
- }
- 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) return(typold);
- error(48);
- return(typnew);
- }
-
- #define dsc if(storage_class) error(49); if(typ||type_qualifiers) error(50)
- #define XSIGNED 16384
-
- struct Typ *declaration_specifiers(void)
- /* Erzeugt neuen Typ und gibt Zeiger darauf zurueck, */
- /* parst z.B. unsigned int, struct bla etc. */
- {
- int typ=0,type_qualifiers=0,notdone,storage_class,hard_reg;
- char *merk,*imerk,sident[MAXI],sbuff[MAXI];
- struct Typ *new=mymalloc(TYPS),*t,*ts;
- struct struct_declaration *ssd;
- struct struct_list (*sl)[];
- size_t slsz;
- struct Var *v;
- storage_class=hard_reg=0;
- new->next=0; new->exact=0;
- do{
- killsp();merk=s;cpbez(buff,0);notdone=0;
- if(DEBUG&2) printf("ts: %s\n",buff);
- if(!strcmp("struct",buff)) notdone=STRUCT;
- if(!strcmp("union",buff)) notdone=UNION;
- if(notdone!=0){
- killsp();
- if(*s!='{'){
- cpbez(sident,1);
- killsp();
- ssd=find_struct(sident,0);
- if(ssd&&*s=='{'&&find_struct(sident,nesting)&&ssd->count>0) error(13,sident);
- if(!ssd||((*s=='{'||*s==';')&&!find_struct(sident,nesting))){
- typ=settyp(notdone,typ);
- ssd=mymalloc(sizeof(*ssd));
- ssd->count=0;
- new->exact=ssd=add_sd(ssd);
- add_struct_identifier(sident,ssd);
- }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);
- }
- if(*s=='{'){
- s++;
- killsp();
- slsz=SLSIZE;
- sl=mymalloc(slsz*sizeof(struct struct_list));
- ssd->count=0;
- imerk=ident;
- ts=declaration_specifiers();
- while(*s!='}'&&ts){
- ident=sbuff;
- t=declarator(clone_typ(ts));
- killsp();
- if(*s==':'){
- /* bitfields werden hier noch ignoriert */
- np tree;
- if((ts->flags&NQ)!=INT) error(51);
- s++;killsp();tree=assignment_expression();
- if(type_expression(tree)){
- if(tree->flags!=CEXPR) error(52);
- if((tree->ntyp->flags&NQ)<CHAR||(tree->ntyp->flags&NQ)>LONG) error(52);
- }
- if(tree) free_expression(tree);
- }else{
- if(*ident==0) error(53);
- }
- if(type_uncomplete(t)){
- error(14,sbuff);
- freetyp(t);
- break;
- }
- if((t->flags&NQ)==FUNKT)
- error(15,sbuff);
-
- if(*ident!=0){
- int i=ssd->count;
- while(--i>=0)
- if(!strcmp((*sl)[i].identifier,ident))
- error(16,ident);
- }
- (*sl)[ssd->count].styp=t;
- (*sl)[ssd->count].identifier=add_identifier(ident,strlen(ident));
- ssd->count++;
- if(ssd->count>=slsz-1){
- slsz+=SLSIZE;
- sl=realloc(sl,slsz*sizeof(struct struct_list));
- if(!sl){error(12);raus();}
- }
- killsp();
- if(*s==',') {s++;killsp();continue;}
- if(*s!=';') error(54); else s++;
- killsp();
- if(*s!='}'){
- if(ts) freetyp(ts);
- ts=declaration_specifiers();killsp();
- }
- }
- if(ts) freetyp(ts);
- if(ssd->count==0) error(55);
- ident=imerk;
- add_sl(ssd,sl);
- free(sl);
- if(*s!='}') error(56); else s++;
- new->flags=notdone|type_qualifiers;
- }
- notdone=1;
- }
- if(!strcmp("enum",buff)){
- /* enumerations; die Namen werden leider noch ignoriert */
- killsp();notdone=1;
- if(*s!='{'){cpbez(buff,1);killsp();}
- if(*s=='{'){
- zlong val; struct Var *v; struct Typ *t;
- val=l2zl(0L);
- s++;killsp();
- while(*s!='}'){
- cpbez(sident,1);killsp();
- if(*sident==0) {error(56);break;}
- t=mymalloc(TYPS);
- t->flags=CONST|INT;
- t->next=0;
- if(find_var(sident,nesting)) error(17,sident);
- v=add_var(sident,t,AUTO,0); /* AUTO hier klug? */
- if(*s=='='){
- s++;killsp();
- v->clist=initialization(v->vtyp,0,0);
- val=zi2zl(v->clist->val.vint);killsp();
- }else{
- v->clist=mymalloc(CLS);
- v->clist->val.vint=val;
- v->clist->next=v->clist->other=0;
- v->clist->tree=0;
- }
- vlong=l2zl(1L);val=zladd(val,vlong);
- v->vtyp->flags=CONST|ENUM;
- if(*s!='}'&&*s!=',') {error(56);break;}
- if(*s==',') s++;
- killsp();
- if(*s=='}') {s++; break;}
- }
- }
- killsp();
- typ=settyp(INT,typ);*buff=0;
- }
- if(!strcmp("void",buff)) {typ=settyp(VOID,typ);notdone=1;}
- if(!strcmp("char",buff)) {typ=settyp(CHAR,typ);notdone=1;}
- if(!strcmp("short",buff)) {typ=settyp(SHORT,typ);notdone=1;}
- if(!strcmp("int",buff)) {typ=settyp(INT,typ);notdone=1;}
- if(!strcmp("long",buff)) {typ=settyp(LONG,typ);notdone=1;}
- if(!strcmp("float",buff)) {typ=settyp(FLOAT,typ);notdone=1;}
- if(!strcmp("double",buff)) {typ=settyp(DOUBLE,typ);notdone=1;}
- if(!strcmp("const",buff)){
- if(type_qualifiers&CONST) error(58);
- type_qualifiers|=CONST;notdone=1;
- }
- if(!strcmp("volatile",buff)){
- if(type_qualifiers&VOLATILE) error(58);
- type_qualifiers|=VOLATILE;notdone=1;
- }
- if(!strcmp("unsigned",buff)){
- if(type_qualifiers&(XSIGNED|UNSIGNED)) error(58);
- notdone=1;type_qualifiers|=UNSIGNED;
- }
- if(!strcmp("signed",buff)){
- if(type_qualifiers&(XSIGNED|UNSIGNED)) error(58);
- notdone=1;type_qualifiers|=XSIGNED;
- }
- if(!strcmp("auto",buff)) {dsc;storage_class=AUTO;notdone=1;}
- if(!strcmp("register",buff)){dsc;storage_class=REGISTER;notdone=1;}
- if(!strcmp("static",buff)) {dsc;storage_class=STATIC;notdone=1;}
- if(!strcmp("extern",buff)) {dsc;storage_class=EXTERN;notdone=1;}
- if(!strcmp("typedef",buff)) {dsc;storage_class=TYPEDEF;notdone=1;}
- if(!(c_flags[7]&USEDFLAG)&&!strcmp("__reg",buff)){
- char *d;int f=0;
- killsp(); if(*s=='(') s++; else error(151);
- killsp(); if(*s=='\"') s++; else error(74);
- d=buff;
- while(*s&&*s!='\"'){
- if(d-buff-2>MAXI){
- if(!f){ error(206,MAXI);f=1;}
- }else *d++=*s;
- s++;
- }
- *d=0;
- if(*s=='\"') s++; else error(74);
- killsp(); if(*s==')') s++; else error(59);
- for(hard_reg=1;hard_reg<=MAXR;hard_reg++){
- if(!strcmp(buff,regnames[hard_reg])) break;
- }
- if(hard_reg>MAXR){ hard_reg=0;error(220,buff);}
- notdone=1;
- }
-
- if(!notdone&&*buff&&typ==0&&!(type_qualifiers&(XSIGNED|UNSIGNED))){
- v=find_var(buff,0);
- if(v&&v->storage_class==TYPEDEF){
- free(new);
- new=clone_typ(v->vtyp);
- typ=settyp(new->flags,typ);
- notdone=1;
- }
- }
- if(DEBUG&2) printf("typ:%d\n",typ);
- }while(notdone);
- s=merk;killsp();
- return_sc=storage_class;
- return_reg=hard_reg;
- if(typ==0){
- if(storage_class==0&&type_qualifiers==0) {free(new);return(0);}
- typ=INT;
- }
- if(type_qualifiers&(XSIGNED|UNSIGNED))
- if(typ!=INT&&typ!=CHAR&&typ!=LONG&&typ!=SHORT)
- error(58);
- if(DEBUG&2) printf("ts finish:%s\n",s);
- new->flags=typ|type_qualifiers;
- return(new);
- }
-
- struct Typ *declarator(struct Typ *a)
- /* Erzeugt einen neuen Typ, auf Basis des Typs a. */
- /* a wird hiermit verkettet. */
- {
- struct Typ *t;
- killsp();*ident=0;
- t=direct_declarator(pointer(a));
- if(!a) {if(t) freetyp(t);return(0);} else return(t);
- }
- struct Typ *pointer(struct Typ *a)
- /* Unterroutine fuer declaration(), behandelt Zeiger auf Typ. */
- {
- struct Typ *t;char *merk;int notdone;
- if(!a) return(0);
- killsp();
- while(*s=='*'){
- s++;
- t=mymalloc(TYPS);
- t->flags=POINTER;
- t->next=a;
- a=t;
- do{
- killsp();
- merk=s;cpbez(buff,0);
- notdone=0;
- if(!strcmp("const",buff)) {a->flags|=CONST;notdone=1;}
- if(!strcmp("volatile",buff)) {a->flags|=VOLATILE;notdone=1;}
- }while(notdone);
- s=merk;
- }
- return(a);
- }
-
- struct Typ *direct_declarator(struct Typ *a)
- /* Unterroutine zu declarator() */
- /* behandelt [],(funkt),(dekl). */
- {
- struct Typ *rek=0,*merk,*p,*t,*first,*last=0;
- struct struct_declaration *fsd;
- struct struct_list (*sl)[];
- size_t slsz;
- char *imerk,fbuff[MAXI];
- killsp();
- if(!isalpha((unsigned char)*s)&&*s!='_'&&*s!='('&&*s!='[') return(a);
- if(isalpha((unsigned char)*s)||*s=='_'){
- cpbez(ident,1);
- if(!a) return(0);
- }else if(*s=='('&&a){
- /* Rekursion */
- imerk=s; s++; killsp();
- if(*s!=')'&&*ident==0&&!declaration(0)){
- merk=a;
- rek=declarator(a);
- if(*s!=')') error(59); else s++;
- }else s=imerk;
- }
- if(!a)return(0);
- killsp();
- while(*s=='['||*s=='('){
- if(*s=='['){
- s++;
- killsp();
- p=mymalloc(TYPS);
- p->flags=ARRAY;
- p->next=0;
- if(*s==']'){
- p->size=l2zl(0L);
- }else{
- np tree;
- tree=expression();
- if(!type_expression(tree)){
- /* error("incorrect constant expression");*/
- }else{
- if(tree->sidefx) error(60);
- if(tree->flags!=CEXPR||(tree->ntyp->flags&NQ)<CHAR||(tree->ntyp->flags&NQ)>LONG){
- error(19);
- }else{
- eval_constn(tree);
- p->size=vlong;
- if(zleqto(p->size,l2zl(0L))) {error(61);p->size=l2zl(1L);}
- }
- }
- free_expression(tree);
- }
- if(*s!=']') error(62); else s++;
- if(last){
- last->next=p;
- last=p;
- }else{
- first=last=p;
- }
- }
- if(*s=='('){
- int komma,oldstyle=0;
- #ifdef HAVE_REGPARMS
- struct reg_handle reg_handle=empty_reg_handle;
- struct Typ rpointer={POINTER};
- if(!freturn(a)){
- rpointer.next=a;
- if(!reg_parm(®_handle,&rpointer)) ierror(0);
- }
- #endif
- s++;
- killsp();
- fsd=mymalloc(sizeof(*fsd));
- slsz=SLSIZE;
- sl=mymalloc(sizeof(struct struct_list)*slsz);
- fsd->count=0;
- imerk=ident;komma=0;
- enter_block();
- while(*s!=')'&&*s!='.'){
- int hard_reg;
- ident=fbuff;*fbuff=0;komma=0;
- t=declaration_specifiers();
- hard_reg=return_reg;
- t=declarator(t);
- if(!t){
- oldstyle=1;
- if(*ident==0) {error(20);break;}
- }
- if(fsd->count){
- if((t&&!(*sl)[fsd->count-1].styp)||
- (!t&&(*sl)[fsd->count-1].styp))
- error(63);
- }
- 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;
- if(hard_reg&&!regok(hard_reg,t->flags,0)) error(217,regnames[hard_reg]);
- (*sl)[fsd->count].identifier=add_identifier(ident,strlen(ident));
- if(t){
- if(((*sl)[fsd->count].styp->flags&NQ)==VOID&&fsd->count!=0)
- error(22);
- /* Arrays in Zeiger umwandeln */
- if(((*sl)[fsd->count].styp->flags&NQ)==ARRAY)
- (*sl)[fsd->count].styp->flags=POINTER;
- /* Funktionen in Zeiger auf Funktionen umwandeln */
- if(((*sl)[fsd->count].styp->flags&NQ)==FUNKT){
- struct Typ *new;
- new=mymalloc(TYPS);
- new->flags=POINTER;
- new->next=(*sl)[fsd->count].styp;
- (*sl)[fsd->count].styp=new;
- }
- }
- #ifdef HAVE_REGPARMS
- if(t) (*sl)[fsd->count].reg=reg_parm(®_handle,t);
- 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=realloc(sl,slsz*sizeof(struct struct_list));
- if(!sl){error(12);raus();}
- }
- killsp(); /* Hier Syntaxpruefung strenger machen */
- if(*s==',') {s++;komma=1; killsp();}
- }
- ident=imerk;
- if((*s!='.'||*(s+1)!='.'||*(s+2)!='.')||!komma){
- if(fsd->count>0&&(!(*sl)[fsd->count-1].styp||((*sl)[fsd->count-1].styp->flags&NQ)!=VOID)){
- (*sl)[fsd->count].styp=mymalloc(TYPS);
- (*sl)[fsd->count].styp->flags=VOID;
- (*sl)[fsd->count].styp->next=0;
- (*sl)[fsd->count].identifier=empty;
- fsd->count++;
- }
- }else if(komma){
- s+=3;komma=0;
- if(oldstyle) error(221);
- }
- p=mymalloc(TYPS);
- p->flags=FUNKT;
- p->next=0;
- {
- int m=nesting;
- nesting=0;
- p->exact=add_sd(fsd);
- add_sl(fsd,sl);
- free(sl);
- nesting=m;
- }
- killsp();
- if(komma) error(59);
- if(*s!=')') error(59); else s++;
- killsp();
- if(*s==','||*s==';'||*s==')'||*s=='=') 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. */
- {
- char *merk=s,buff[MAXI];
- struct Var *v;
- if(offset){
- s++;
- read_new_line=0;
- if(DEBUG&1) printf("cleared read_new_line\n");
- killsp();
- if(read_new_line){ /* es kam eine neue Zeile */
- memmove(s+1,s,MAXINPUT);
- *s='(';
- if(DEBUG&1) printf("look-ahead: %s|\n",s);
- merk=s;
- s++;
- cpbez(buff,0);
- }else{
- if(DEBUG&1) printf("read_new_line unchanged\n");
- cpbez(buff,0);
- }
- }else{
- cpbez(buff,0);
- }
- s=merk;
- if(!strcmp("auto",buff)) return(1);
- if(!strcmp("char",buff)) return(1);
- if(!strcmp("const",buff)) return(1);
- if(!strcmp("double",buff)) return(1);
- if(!strcmp("enum",buff)) return(1);
- if(!strcmp("extern",buff)) return(1);
- if(!strcmp("float",buff)) return(1);
- if(!strcmp("int",buff)) return(1);
- if(!strcmp("long",buff)) return(1);
- if(!strcmp("register",buff)) return(1);
- if(!strcmp("short",buff)) return(1);
- if(!strcmp("signed",buff)) return(1);
- if(!strcmp("static",buff)) return(1);
- if(!strcmp("struct",buff)) return(1);
- if(!strcmp("typedef",buff)) return(1);
- if(!strcmp("union",buff)) return(1);
- if(!strcmp("unsigned",buff)) return(1);
- if(!strcmp("void",buff)) return(1);
- if(!strcmp("volatile",buff)) return(1);
- if(!(c_flags[7]&USEDFLAG)&&!strcmp("__reg",buff)) return(1);
- v=find_var(buff,0);
- if(v&&v->storage_class==TYPEDEF) return(1);
- return(0);
- }
- void add_sl(struct struct_declaration *sd,struct 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 struct_list)*sd->count;
- sd->sl=mymalloc(sz);
- memcpy(sd->sl,sl,sz);
- }
- struct struct_declaration *add_sd(struct struct_declaration *new)
- /* Fuegt eine struct Declaration in Liste ein. */
- {
- new->next=0;
- 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 struct_declaration *p)
- /* Gibt eine struct_declaration-List inkl. struct_lists und */
- /* allen Typen jeder struct_list frei, nicht aber identifier. */
- {
- int i;struct struct_declaration *merk;
- while(p){
- merk=p->next;
- for(i=0;i<p->count;i++) if((*p->sl)[i].styp) freetyp((*p->sl)[i].styp);
- if(p->count>0) free(p->sl);
- 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. */
- {
- struct identifier_list *new;
- if((*identifier==0&&length==0)||identifier==empty) return(empty);
- new=mymalloc(sizeof(struct 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(struct identifier_list *p)
- /* Gibt eine verkettete identifier_liste und saemtliche darin */
- /* gespeicherten Identifier frei. */
- {
- struct identifier_list *merk;
- while(p){
- merk=p->next;
- if(p->identifier) free(p->identifier);
- free(p);
- p=merk;
- }
- }
- int type_uncomplete(struct Typ *p)
- /* Testet, ob Typ unvollstaendig ist. Momentan gelten nur */
- /* unvollstaendige Strukturen und Arrays von solchen als */
- /* unvollstaendig, aber keine Zeiger oder Funktionen darauf. */
- {
- struct struct_declaration *sd;
- if(!p){ierror(0);return(0);}
- if((p->flags&NQ)==STRUCT||(p->flags&NQ)==UNION)
- if(p->exact->count<=0) return(1);
- if((p->flags&NQ)==ARRAY){
- if(zlleq(p->size,l2zl(0L))) return(1);
- if(type_uncomplete(p->next)) return(1);
- }
- return(0);
- }
- void add_struct_identifier(char *identifier,struct struct_declaration *sd)
- /* Erzeugt neuen struct_identifier, fuegt ihn in Liste an und */
- /* vervollstaendigt unvollstaendige Typen dieser Struktur. */
- {
- struct struct_identifier *new;
- /* struct Typ *t;*/
- if(DEBUG&1) printf("add_si %s (nesting=%d)->%p\n",identifier,nesting,(void *)sd);
- new=mymalloc(sizeof(struct 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;
- }
- }
- void free_si(struct struct_identifier *p)
- /* Gibt eine struct_identifier-Liste frei, aber nicht die */
- /* identifiers und struct_declarations. */
- {
- struct struct_identifier *merk;
- while(p){
- merk=p->next;
- free(p);
- p=merk;
- }
- }
- struct struct_declaration *find_struct(char *identifier,int endnesting)
- /* Sucht angegebene Strukturdefinition und liefert */
- /* entsprechende struct_declaration. */
- {
- struct struct_identifier *si; int i;
- for(i=nesting;i>=endnesting;i--){
- si=first_si[i];
- while(si){
- if(!strcmp(si->identifier,identifier)){
- if(DEBUG&1) printf("found struct tag <%s> at nesting %d->%p\n",identifier,i,(void *)si->sd);
- return(si->sd);
- }
- si=si->next;
- }
- }
- if(DEBUG&1) printf("didn't find struct tag <%s>\n",identifier);
- return(0);
- }
- struct Var *add_tmp_var(struct Typ *t)
- {
- return add_var(empty,t,AUTO,0);
- }
- struct Var *add_var(char *identifier, struct Typ *t, int storage_class,struct 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. */
- {
- struct Var *new;int f;
- struct struct_declaration *sd;
- static zlong paroffset;
- zlong al;
- /*if(*identifier==0) return;*/ /* sollte woanders bemaekelt werden */
- if(DEBUG&2) printf("add_var(): %s\n",identifier);
- if((t->flags&NQ)==FUNKT&&((t->next->flags&NQ)==ARRAY||(t->next->flags&NQ)==FUNKT))
- error(25);
- new=mymalloc(sizeof(struct Var));
- new->identifier=add_identifier(identifier,strlen(identifier));
- new->clist=clist;
- new->vtyp=t;
- new->storage_class=storage_class&7;
- new->reg=0;
- new->next=0;
- new->flags=0;
- new->fi=0;
- new->nesting=nesting;
- /* if((storage_class&7)==STATIC||(storage_class&7)==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;storage_class&=~PARAMETER;}
- if(DEBUG&2) printf("storage_class=%d\n",storage_class);
- if(DEBUG&2) printf("max_offset=%ld\n",max_offset);
- if((storage_class&7)==REGISTER) new->priority=registerpri; else new->priority=0;
- if(last_var[nesting]){
- new->offset=zladd(last_var[nesting]->offset,szof(last_var[nesting]->vtyp));
- last_var[nesting]->next=new;
- last_var[nesting]=new;
- }else{
- new->offset=l2zl(0L);
- paroffset=l2zl(0L);;
- first_var[nesting]=last_var[nesting]=new;
- }
- f=t->flags&NQ;
- if((storage_class&7)==AUTO||(storage_class&7)==REGISTER){
- if(DEBUG&2) printf("auto\n");
- if(type_uncomplete(t)&&(t->flags&NQ)!=ARRAY) error(202,identifier);
- /* das noch ueberpruefen */
- if((c_flags_val[0].l&2)&&nesting==1&&!(storage_class&PARAMETER)){
- new->offset=max_offset;
- }else{
- if(storage_class&PARAMETER){
- new->offset=paroffset;
- }else{
- new->offset=local_offset[nesting];
- }
- }
- al=falign(t);
- new->offset=zlmult(zldiv(zladd(new->offset,zlsub(al,l2zl(1L))),al),al);
- if(storage_class&PARAMETER){
- new->offset=zlmult(zldiv(zladd(new->offset,zlsub(maxalign,l2zl(1L))),maxalign),maxalign);
- if(f>=CHAR&&f<=SHORT){
- /* Integer-Erweiterungen fuer alle Funktionsparameter */
- paroffset=zladd(new->offset,sizetab[INT]);
- }else{
- if(f==FLOAT&&(storage_class&OLDSTYLE)){
- /* Bei alten Funktionen werden FLOAT als DOUBLE uebergeben */
- new->offset=zlmult(zldiv(zladd(new->offset,zlsub(align[DOUBLE],l2zl(1L))),align[DOUBLE]),align[DOUBLE]);
- paroffset=zladd(new->offset,sizetab[DOUBLE]);
- }else{
- paroffset=zladd(new->offset,szof(new->vtyp));
- }
- }
- }else{
- local_offset[nesting]=zladd(new->offset,szof(new->vtyp));
- }
-
- if(!(storage_class&PARAMETER))
- if(zlleq(max_offset,local_offset[nesting])) max_offset=local_offset[nesting];
- if(DEBUG&2) printf("max_offset=%ld\n",max_offset);
- }
- if((storage_class&7)==STATIC) new->offset=l2zl((long)++label);
- if(storage_class&PARAMETER){
-
- if(DEBUG&2) printf("parameter\n");
-
- if(f>=CHAR&&f<=SHORT&&!zlleq(sizetab[INT],sizetab[f])){
- if(BIGENDIAN){
- new->offset=zladd(new->offset,zlsub(sizetab[INT],sizetab[f]));
- }else{
- if(!LITTLEENDIAN)
- ierror(0);
- }
- }
- if((storage_class&OLDSTYLE)&&f==FLOAT){
- /* Bei alten Funktionen werden DOUBLE nach FLOAT konvertiert */
- struct IC *conv=mymalloc(ICS);
- conv->code=CONVDOUBLE;
- conv->typf=FLOAT;
- conv->q1.flags=VAR|DONTREGISTERIZE;
- conv->z.flags=VAR;
- conv->q2.flags=0;
- conv->q1.v=conv->z.v=new;
- conv->q1.val.vlong=conv->z.val.vlong=l2zl(0);
- add_IC(conv);
- new->flags|=CONVPARAMETER;
- }
- new->offset=zlsub(l2zl(0L),zladd(maxalign,new->offset));
- }
- if((storage_class&7)==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;
- }
- return(new);
- }
- void free_var(struct Var *p)
- /* Gibt Variablenliste inkl. Typ, aber ohne Identifier frei. */
- {
- struct Var *merk;
- while(p){
- merk=p->next;
- if(!(p->flags&USEDASADR)&&(p->storage_class==AUTO||p->storage_class==REGISTER)){
- if(*p->identifier&&!(p->flags&USEDASDEST)&&(p->vtyp->flags&NQ)<=POINTER) error(64,p->identifier);
- if(*p->identifier&&!(p->flags&USEDASSOURCE)&&(p->vtyp->flags&NQ)<=POINTER) 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;
- }
- }
- struct 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;struct Var *v;
- if(*identifier==0||identifier==0) return(0);
- for(i=nesting;i>=endnesting;i--){
- v=first_var[i];
- while(v){
- if(!strcmp(v->identifier,identifier)) return(v);
- v=v->next;
- }
- }
- return(0);
- }
- void var_declaration(void)
- /* Bearbeitet eine Variablendeklaration und erzeugt alle */
- /* noetigen Strukturen. */
- {
- struct Typ *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;
- struct Var *v;
- ts=declaration_specifiers();notdone=1;
- storage_class=return_sc;hard_reg=return_reg;
- if(storage_class==EXTERN) extern_flag=1; else extern_flag=0;
- killsp();
- if(*s==';'){
- if(storage_class||((ts->flags&NQ)!=STRUCT&&(ts->flags&NQ)!=UNION&&(ts->flags&NQ)!=INT))
- error(36);
- freetyp(ts);s++;killsp();
- return;
- }
- if(nesting==0&&(storage_class==AUTO||storage_class==REGISTER))
- {error(66);storage_class=EXTERN;}
- if(!ts){
- if(nesting<=1){
- ts=mymalloc(TYPS);
- ts->flags=INT;ts->next=0;
- makeint=1;
- if(!storage_class) storage_class=EXTERN;
- error(67);
- }else{
- ierror(0);return;
- }
- }
- 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));
- if((t->flags&NQ)!=FUNKT) isfunc=0;
- else {isfunc=1;if(storage_class!=STATIC) storage_class=EXTERN;}
- ident=imerk; /* nicht unbedingt noetig ? */
- if(!*vident){
- free(ts);free(t);
- error(36);return;
- }
- v=find_var(vident,oldnesting);
- 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&&!compare_pointers(v->vtyp,t,255)){
- error(68,vident);
- }
- if((storage_class!=v->storage_class&&!extern_flag)||hard_reg!=v->reg)
- error(28,v->identifier);
- if(!isfunc&&!extern_flag) v->flags|=TENTATIVE;
- }
- if(!isfunc){
- v->vtyp=t;
- }else{
- om=v->vtyp;
- if(t->exact->count>0) {old=v->vtyp;v->vtyp=t;}
- }
- }
- }else{
- had_decl=0;
- if(isfunc&&*s!=','&&*s!=';'&&*s!=')'&&*s!='='&&nesting>0) nesting--;
- v=add_var(vident,t,storage_class,0);
- v->reg=hard_reg;
- if(isfunc&&*s!=','&&*s!=';'&&*s!=')'&&*s!='='&&nesting>=0) nesting++;
- if(!v) ierror(0);
- else{
- if(!isfunc&&!extern_flag){
- v->flags|=TENTATIVE;
- if(nesting>0) v->flags|=DEFINED;
- }
- }
- om=0;
- }
- killsp();
- /* Inline-Assembler-Code in Funktionsdeklarationen */
- if(*s=='='&&(v->vtyp->flags&NQ)==FUNKT&&!(c_flags[7]&USEDFLAG)){
- np tree;
- s++;killsp();
- tree=string_expression();
- if(!tree||tree->flags!=STRING) error(42);
- else{
- int l;struct const_list *cl;
- if(!v->fi) v->fi=new_fi();
- cl=tree->cl;l=0;
- while(cl){
- l++;
- cl=cl->next;
- }
- v->fi->inline_asm=mymalloc(l);
- cl=tree->cl;l=0;
- while(cl){
- v->fi->inline_asm[l]=zl2l(zc2zl(cl->other->val.vchar));
- l++;
- cl=cl->next;
- }
- }
- if(tree) free_expression(tree);
- killsp();
- }
- /* Initialisierung von Variablen bei Deklaration */
- if(*s=='='){
- s++;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;
- 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;}
- }
- v->clist=initialization(v->vtyp,v->storage_class==AUTO||v->storage_class==REGISTER,0);
- if(v->clist){
- if((v->vtyp->flags&NQ)==ARRAY&&zleqto(v->vtyp->size,l2zl(0L))){
- struct const_list *p=v->clist;
- while(p){v->vtyp->size=zladd(v->vtyp->size,l2zl(1L));p=p->next;}
- if(v->storage_class==AUTO||v->storage_class==REGISTER){
- local_offset[nesting]=zladd(local_offset[nesting],szof(v->vtyp));
- if(zlleq(max_offset,local_offset[nesting])) max_offset=local_offset[nesting];
- }
- }
- if(v->storage_class==AUTO||v->storage_class==REGISTER){
- struct IC *new;
- /* Initialisierung von auto-Variablen */
- new=mymalloc(ICS);
- new->code=ASSIGN;
- new->typf=v->vtyp->flags;
- new->q2.flags=0;
- new->q2.val.vlong=szof(v->vtyp);
- new->z.flags=VAR;
- new->z.v=v;
- new->z.val.vlong=l2zl(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;
- /* v->clist=0;*/
- }else{
- /* Array etc. */
- struct Var *nv;
- nv=add_var(empty,clone_typ(v->vtyp),STATIC,v->clist);
- nv->flags|=DEFINED;
- nv->vtyp->flags|=CONST;
- /* v->clist=0;*/
- new->q1.flags=VAR;
- new->q1.v=nv;
- new->q1.val.vlong=l2zl(0L);
- }
- add_IC(new);
- /* if(v->clist&&v->clist->tree){free_expression(v->clist->tree);v->clist->tree=0;}*/
- }else if(c_flags[19]&USEDFLAG){
- /* Ohne Optimierung gleich erzeugen; das ist noch */
- /* etwas von der genauen Implementierung der Liste */
- /* der Variablen abhaengig. */
- struct 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(*s==',') {s++;killsp();mdef=1;} else notdone=0;
- }
- freetyp(ts);
- if(!mdef&&t&&(t->flags&NQ)==FUNKT&&*s!=';'){
- /* Funktionsdefinition */
- int i,oldstyle=0;
- #ifdef HAVE_REGPARMS
- struct reg_handle reg_handle;
- #endif
- fline=line;
- if(DEBUG&1) printf("Funktionsdefinition!\n");
- {int i;
- for(i=1;i<=MAXR;i++) {regs[i]=regused[i]=regsa[i];regsbuf[i]=0;}
- }
- cur_func=v->identifier;
- if(only_inline==2) only_inline=0;
- if(nesting<1) ierror(0);
- if(nesting>1) error(32);
- if(v->flags&DEFINED) error(33,v->identifier);
- else v->flags|=DEFINED;
- if(storage_class!=EXTERN&&storage_class!=STATIC) error(34);
- if(extern_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(*s!='{'){
- /* alter Stil */
- struct Typ *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((ts->flags&NQ)==ARRAY) ts->flags=POINTER;
- /* typ() in *typ() */
- if((ts->flags&NQ)==FUNKT){
- struct Typ *new=mymalloc(TYPS);
- new->flags=POINTER;
- 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(*s==',') {s++;killsp();} else notdone=0;
- }
- if(nt) freetyp(nt);
- if(*s==';'){s++;killsp();
- }else{
- error(54);
- while(*s!='{'&&*s!=';'){s++;killsp();}
- }
- }
- if(t->exact->count==0){
- struct 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=mymalloc(TYPS);
- sl[0].styp->flags=VOID;
- sl[0].styp->next=0;
- nesting--;
- add_sl(t->exact,&sl);
- nesting++;
- }
- if(om&&!compare_sd(om->exact,t->exact))
- error(123);
- nocode=0;currentpri=1;
- /* enter_block();*/
- local_offset[1]=l2zl(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(!freturn(return_typ)){
- /* Parameter fuer die Rueckgabe von Werten, die nicht in einem */
- /* Register sind. */
- struct Typ *rt=mymalloc(TYPS);int reg;
- rt->flags=POINTER;rt->next=return_typ;
- #ifdef HAVE_REGPARMS
- reg=reg_parm(®_handle,rt);
- if(!reg) ierror(0);
- return_var=add_var(empty,clone_typ(rt),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;
- free(rt);
- }
- }
- first_ic=last_ic=0;ic_count=0;max_offset=l2zl(0L);
- for(i=0;i<t->exact->count;i++){
- if(!(*t->exact->sl)[i].styp&&*(*t->exact->sl)[i].identifier){
- struct Typ *nt;
- nt=mymalloc(TYPS);
- nt->flags=INT; nt->next=0;
- (*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){
- struct Var *tmp;int sc;
- sc=((*t->exact->sl)[i].storage_class|PARAMETER|oldstyle);
- #ifdef HAVE_REGPARMS
- if(!t->exact->sl) ierror(0);
- if(!(*t->exact->sl)[i].styp) ierror(0);
- (*t->exact->sl)[i].reg=reg_parm(®_handle,(*t->exact->sl)[i].styp);
- #endif
- if((*t->exact->sl)[i].reg) sc|=REGPARM;
- 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;
- if(oldstyle){
- 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]=l2zl(0L);*/
- return_label=++label;
- v->flags|=GENERATED;
- function_calls=0;float_used=0;has_return=0;goto_used=0;
- compound_statement();
- 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
- gen_label(return_label);
- 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(c_flags_val[0].l,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)){
- gen_code(out,first_ic,v,max_offset);
- }
- /* 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(v->fi&&v->fi->first_ic){
- struct Var *vp;
- if(DEBUG&1) printf("leave block %d (inline-version)\n",nesting);
- 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) gen_vars(merk_varf);
- if(first_llist) free_llist(first_llist);
- if(first_clist) free_clist(first_clist);
- 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];*/
- vp=merk_varf;
- while(vp){
- if(vp->storage_class==AUTO||vp->storage_class==REGISTER){
- if(!zlleq(l2zl(0L),vp->offset)){
- vp->offset=l2zl(0L);
- if(DEBUG&1024) printf("converted parameter <%s>(%ld) for inlining\n",vp->identifier,(long)zl2l(vp->offset));
- }else vp->offset=l2zl(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(*s==';') s++; else error(54);
- if((t->flags&NQ)==FUNKT&&t->exact){
- struct 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 compare_pointers(struct Typ *a,struct Typ *b,int qual)
- /* Vergleicht, ob Typ beider Typen gleich ist, const/volatile */
- /* werden laut ANSI nicht beruecksichtigt. */
- {
- struct struct_declaration *sd;
- int af=a->flags&qual,bf=b->flags&qual;
- if(af!=bf) return(0);
- af&=NQ;bf&=NQ;
- if(af==FUNKT){
- if(a->exact->count&&!compare_sd(a->exact,b->exact)) return(0);
- }
- if(af==STRUCT||af==UNION){
- if(a->exact!=b->exact) return(0);
- }
- if(af==ARRAY){
- if(!zleqto(a->size,l2zl(0L))&&!zleqto(b->size,l2zl(0L))&&!zleqto(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);
- return(compare_pointers(a->next,b->next,qual));
- }
- int compare_sd(struct struct_declaration *a,struct 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&&!compare_pointers((*a->sl)[i].styp,(*b->sl)[i].styp,255)) return(0);
- return(1);
- }
- void free_clist(struct const_list *p)
- /* Gibt clist frei. */
- {
- struct 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 *,struct Typ *,struct const_list *);
-
- void gen_vars(struct Var *v)
- /* Generiert Variablen. */
- {
- int mode,al;struct Var *p;
- if(errors!=0||(c_flags[5]&USEDFLAG)) return;
- for(mode=0;mode<3;mode++){
- int i,flag;
- for(p=v;p;p=p->next){
- 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;
- /* erst konstante initialisierte Daten */
- if(mode==0){
- if(!p->clist) continue;
- if(!(p->vtyp->flags&(CONST|STRINGCONST))){
- struct Typ *t=p->vtyp;int f=0;
- do{
- if(t->flags&(CONST|STRINGCONST)) break;
- if((t->flags&NQ)!=ARRAY){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))){
- gen_var_head(out,p);
- if(p->storage_class==STATIC) error(127,p->identifier);
- continue;
- }else{
- gen_align(out,falign(p->vtyp));
- }
- 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;
- }
- }
- }
- }
- }
- void gen_clist(FILE *f,struct Typ *t,struct const_list *cl)
- /* Generiert dc fuer const_list. */
- {
- int i;zlong sz;
- if((t->flags&NQ)==ARRAY){
- for(sz=l2zl(0L);!zlleq(t->size,sz)&&cl;sz=zladd(sz,l2zl(1L)),cl=cl->next){
- if(!cl->other){ierror(0);return;}
- gen_clist(f,t->next,cl->other);
- }
- if(!zlleq(t->size,sz)) gen_ds(f,zlmult(zlsub(t->size,sz),szof(t->next)),t->next);
- return;
- }
- if((t->flags&NQ)==UNION){
- gen_clist(f,(*t->exact->sl)[0].styp,cl);
- sz=zlsub(szof(t),szof((*t->exact->sl)[0].styp));
- if(!zleqto(sz,l2zl(0L))) gen_ds(f,sz,0);
- return;
- }
- if((t->flags&NQ)==STRUCT){
- zlong al;int fl;struct Typ *st;
- sz=l2zl(0L);
- for(i=0;i<t->exact->count&&cl;i++){
- if(!cl->other){ierror(0);return;}
- st=(*t->exact->sl)[i].styp;
- al=falign(st);
- if(!zleqto(zlmod(sz,al),l2zl(0L))){
- gen_ds(f,zlsub(al,zlmod(sz,al)),0);
- sz=zladd(sz,zlsub(al,zlmod(sz,al)));
- }
- if(!(*t->exact->sl)[i].identifier) ierror(0);
- if((*t->exact->sl)[i].identifier[0]){
- gen_clist(f,st,cl->other);
- cl=cl->next;
- }else{
- gen_ds(f,szof(st),0); /* sollte unnamed bitfield sein */
- }
- sz=zladd(sz,szof(st));
- }
- for(;i<t->exact->count;i++){
- st=(*t->exact->sl)[i].styp;
- al=falign(st);
- if(!zleqto(zlmod(sz,al),l2zl(0L))){
- gen_ds(f,zlsub(al,zlmod(sz,al)),0);
- sz+=zladd(sz,zlsub(al,zlmod(sz,al)));
- }
- gen_ds(f,szof((*t->exact->sl)[i].styp),(*t->exact->sl)[i].styp);
- sz=zladd(sz,szof(st));
- }
- al=falign(t);
- if(!zleqto(zlmod(sz,al),l2zl(0L)))
- gen_ds(f,zlsub(al,zlmod(sz,al)),0);
- return;
- }
- if(cl->tree) cl->tree->o.am=0;
- gen_dc(f,t->flags&NU,cl);
- }
- struct const_list *initialization(struct Typ *t,int noconst,int level)
- /* Traegt eine Initialisierung in eine const_list ein. */
- {
- struct const_list *first,*cl,**prev;np tree,tree2;int bracket;zlong i;
- int f=t->flags&NQ;
- if(f==FUNKT){error(42);return(0);}
- if(*s=='{'){s++;killsp();bracket=1;} else bracket=0;
- if(f==ARRAY){
- if(*s=='\"'&&t->next&&(t->next->flags&NQ)==CHAR){
- killsp();
- tree=string_expression();
- first=tree->cl;
- free_expression(tree);
- }else{
- prev=0;
- if(level==0&&!bracket) error(157);
- for(i=l2zl(0L);(zleqto(t->size,l2zl(0L))||!zlleq(t->size,i))&&*s!='}';i=zladd(i,l2zl(1L))){
- if(!zlleq(i,0)){
- if(*s==','){s++;killsp();} else break;
- if(*s=='}') break;
- }
- cl=mymalloc(CLS);
- cl->next=0;cl->tree=0;
- cl->other=initialization(t->next,0,level+1);
- killsp();
- if(prev) *prev=cl; else first=cl;
- prev=&cl->next;
- }
- }
- }else if(f==STRUCT&&(bracket||!noconst)){
- if(t->exact->count<=0)
- {error(43);return(0);}
- prev=0;
- if(level==0&&!bracket) error(157);
- for(i=l2zl(0L);!zlleq(t->exact->count,i)&&*s!='}';i=zladd(i,l2zl(1L))){
- if((*t->exact->sl)[zl2l(i)].identifier[0]==0) {continue;} /* unnamed bitfield */
- if(!zlleq(i,0)){
- if(*s==','){s++;killsp();} else break;
- if(*s=='}') break;
- }
- cl=mymalloc(CLS);
- cl->next=0;cl->tree=0;
- cl->other=initialization((*t->exact->sl)[zl2l(i)].styp,0,level+1);
- if(prev) *prev=cl; else first=cl;
- prev=&cl->next;
- }
- }else if(f==UNION&&(bracket||!noconst)){
- if(t->exact->count<=0)
- {error(44);return(0);}
- first=initialization((*t->exact->sl)[0].styp,0,level+1);
- }else{
- tree2=tree=assignment_expression();
- if(!tree){error(45);return(0);}
- if(!type_expression(tree)){free_expression(tree); return(0);}
- tree=makepointer(tree);
- test_assignment(t,tree);
- if(!noconst){
- /* nur Konstanten erlaubt (bei Arrays/Strukturen etc. oder static) */
- if(tree->flags!=CEXPR){
- while(tree->flags==CAST) tree=tree->left;
- if(tree->flags==ADDRESS||tree->flags==ADDRESSS||tree->flags==ADDRESSA){
- gen_IC(tree,0,0);
- if(!(tree->o.flags&VARADR)){
- /* hier fehlen noch viele Pruefungen */
- free_expression(tree);error(46);
- return(0);
- }
- first=mymalloc(CLS);
- first->next=first->other=0;
- first->tree=tree;
- killsp();
- }else{
- free_expression(tree);error(46);
- return(0);
- }
- }else{
- first=mymalloc(CLS);
- first->next=first->other=0;
- first->tree=0;
- eval_constn(tree);
- tree->ntyp->flags=t->flags;
- insert_const(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(bracket){
- if(*s==','){s++;killsp();}
- if(*s=='}'){s++;killsp();} else error(128);
- }
- return(first);
- }
-
-
-
-