/* $Id: h-fun.cc,v 1.7 1997/08/02 08:42:05 isis Exp $ */ // $Log: h-fun.cc,v $ // Revision 1.7 1997/08/02 08:42:05 isis // Generator now prints "char*" as strings as well // // Revision 1.6 1997/07/30 17:46:15 isis // Some minor new features and bug fixes // This seems to work fine // // Revision 1.5 1997/06/22 14:48:45 isis // This is the initial version for // the generating functions module // // Revision 1.4 1997/06/01 13:23:11 isis // Parsing of const: // e.g const char const * const a; // Changed the internal represantation of '*' to support const qualifiers // // Revision 1.3 1997/05/25 15:12:25 isis // Bug fixes // mostly with sizeof operator // // Revision 1.2 1997/05/18 17:03:04 isis // Added main.cc to improve // the usage of the symbol table // // Revision 1.1 1997/05/18 16:56:39 isis // Changed the names a bit // to be easier to use // // Revision 1.1 1997/05/18 16:44:08 isis // Break some files to improve re-making // #include #include #include #include #include #include #include "Cname.h" #include "symbol.h" #include "gc_stl.h" #include "h-fun.h" #include "lcm.cc" int yyerror(char *s) { cerr << "At line " << lineno << " : " << s << endl; return 0; } char *clean_Cname(Cname*ptr) { Cname *cur=ptr; while(cur->next!=NULL) cur=cur->next; return cur->name; } type_id_list* create_type_id_list(Ctype *type,gc_pCname_list *nmlist) { //Creates a list of (ctype,cname) with info about a declaration //It DOESNOT check whether current declaration are compatible with //previous ones... //Remember: insert_type_id_list_as_?? MUST check for compatibility with //previous declarations before inserting (and issue errors) //(shouldn't matter since map DOESN'T accept multiple keys anyway!) type_id_list *lst=new type_id_list; if(nmlist==NULL) return NULL; for(gc_pCname_list::iterator i=nmlist->begin();i!=nmlist->end();i++) { gc_type_id *pa=new gc_type_id; pa->first=new Ctype(*type); pa->second=(*i); lst->push_back(pa); } return lst; } void insert_type_id_list_as_var(type_id_list *lst) { //MUST check for compatibility with previous declarations.... type_id_list::iterator i; SymbolTableEntry* ent; if(lst==NULL) return; for(i=lst->begin();i!=lst->end();i++) { ent=SymbolTable.Lookup(clean_Cname( (*i)->second) , SEARCH_CURRENT_SCOPE); if(ent==NULL) { //no previous declaration found VariableEntry *var=new VariableEntry((*i)->second,(*i)->first); SymbolTable.Insert(var); } else { //let's warn for compatibility... char buf[255]; sprintf(buf,"Symbol '%s' has already been declared",clean_Cname( (*i)->second )); ErrorHandler.Warning(buf); } } } /* void insert_enum_id_list(gc_enum_id_list *lst,Ctype *typ) { gc_enum_id_list::iterator i; SymbolTableEntry* ent; if(lst==NULL) return; for(i=lst->begin();i!=lst->end();i++) { ent=SymbolTable.Lookup( (*i)->name ,SEARCH_CURRENT_SCOPE); if(ent==NULL) { EnumEntry *en=new EnumEntry( *i,typ ); SymbolTable.Insert(en); } else { char buf[255]; sprintf(buf,"Symbol '%s' has already been declared",(*i)->name); ErrorHandler.Warning(buf); } } }*/ void insert_type_id_list_as_type(type_id_list *lst) { type_id_list::iterator i; if(lst==NULL) return; for(i=lst->begin();i!=lst->end();i++) { TypeEntry *var=new TypeEntry((*i)->second,(*i)->first); var->SetSize( get_sizeof_ctype_cname( (*i)->first, (*i)->second ) ); var->SetAlignment ( get_alignment_of_ctype_cname( (*i)->first,(*i)->second ) ); SymbolTable.Insert(var); } } void mangle(char *dest,Ctype::DefStyle st,char *id) { sprintf(dest,"%s %s",Ctype::Style2Str(st),id); } Ctype* find_and_check_type(char*str,Ctype::DefStyle st) { SymbolTableEntry *ent; TypeEntry *type; char buf[255]; mangle(buf,st,str); ent=SymbolTable.Lookup(buf,SEARCH_ALL_SCOPES); if(ent==NULL) { // char err[255]; // sprintf(err,"Symbol '%s %s' not defined (assuming forward)",Ctype::Style2Str(st),str); // ErrorHandler.Warning(err); forward_create_complex_type(str,st); ent=SymbolTable.Lookup(buf,SEARCH_ALL_SCOPES); assert(ent!=NULL); } if(ent->WhatIs()!=TypeEnt) { char buf[255]; sprintf(buf,"Symbol %s is NOT defined as a %s",str,Ctype::Style2Str(st)); ErrorHandler.Error(buf); } type=(TypeEntry*)ent; return new Ctype(type,Ctype::DEFMOD,Ctype::DEFSIGN,st,NULL); //Scope is NULL because we want to be able to access the scope ONLY from //the TypeEntry, when the time comes (=when the scope is defined) } /* Ctype* check_type(TypeEntry*typ,Ctype::DefStyle st) { assert(typ!=NULL); assert(typ->GetCtype()!=NULL); Ctype::DefStyle typ_st=typ->GetCtype()->style_attr; if(typ_st!=st) { char buf[255]; sprintf(buf,"Symbol '%s' defined as a '%s' (not as a '%s')",typ->GetName(), Ctype::Style2Str(typ_st),Ctype::Style2Str(st) ); ErrorHandler.Error(buf); } return new Ctype(typ,Ctype::DEFMOD,Ctype::DEFSIGN,st,typ->GetScope()); }*/ void create_complex_type(char*name,Ctype::DefStyle st) { Ctype *typ = new Ctype(NULL,Ctype::DEFMOD,Ctype::DEFSIGN,st,NULL); char buf[255]; mangle(buf,st,name); TypeEntry *ent=new TypeEntry(buf,typ); SymbolTable.Insert(ent); SymbolTable.OpenScope(name); typ->scope = SymbolTable.GetCurrentScope(); } void forward_create_complex_type(char *name,Ctype::DefStyle st) { Ctype *typ = new Ctype(NULL,Ctype::DEFMOD,Ctype::DEFSIGN,st,NULL); char buf[255]; mangle(buf,st,name); TypeEntry *ent=new TypeEntry(buf,typ); SymbolTable.Insert(ent); } bool open_forward_complex_type(char*name,Ctype::DefStyle st) { TypeEntry *ent; Ctype *typ; SymbolTableEntry *symb; char buf[255]; mangle(buf,st,name); symb=SymbolTable.Lookup(buf,SEARCH_CURRENT_SCOPE); if(symb==NULL) return false; assert(symb->WhatIs()==TypeEnt); ent=(TypeEntry*)symb; typ=ent->GetCtype(); assert(typ->scope==NULL); SymbolTable.OpenScope(buf); typ->scope = SymbolTable.GetCurrentScope(); return true; } /* void fix_enum_list(gc_enum_id_list *li) { assert(li!=NULL); gc_enum_id_list::iterator i; int cur_value=0; for(i=li->begin();i!=li->end();i++) { if( (*i)->has_value ) cur_value=(*i)->value; else (*i)->SetValue(cur_value); cur_value++; } }*/ int get_sizeof_id(char *id) { SymbolTableEntry *ent; ent=SymbolTable.Lookup(id,SEARCH_ALL_SCOPES); if(ent==NULL) { char buf[255]; sprintf(buf,"Undefined symbol '%s' in sizeof expression",id); ErrorHandler.Error(buf); } switch(ent->WhatIs()) { case VariableEnt: return ((VariableEntry*)ent)->GetSize(); case TypeEnt: case EnumEnt: return 0; default: assert(0==1); } } //Fixes the number of bytes of a structure to incorporate a bitfield //by adding enough BITFIELD_SIZE bytes void fix_bitfield(int &total,int &bits) { if(bits!=0) { int bytes=0; while(bytes*8WhatIs()) { case EnumEnt: { gc_enum_id *enum_id=((EnumEntry*)ent)->GetEnumID(); if(enum_id->has_value) return enum_id->value; else { char buf[255]; sprintf(buf,"Enumeration '%s' has no value(PANIK)",str); ErrorHandler.Error(buf); } } case VariableEnt: case TypeEnt: { char buf[255]; sprintf(buf,"Symbol '%s' is not an enumeration",str); ErrorHandler.Error(buf); } default: assert(0==1); } } int get_lcm_of_alignments(Scope *sc) { ListType::iterator i; ListType *ll=sc->GetListEntity(); int al=1; for(i=ll->begin();i!=ll->end();i++) { switch((*i)->WhatIs()) { case VariableEnt: { VariableEntry *var=(VariableEntry*) (*i); al=lcm(al,var->GetAlignment()); } case TypeEnt: case EnumEnt: continue; default: assert(0==1); } } return al; } int get_max_sizeof_vars_in_scope(Scope *sc) { ListType::iterator i; ListType *ll=sc->GetListEntity(); int maxsize=0; for(i=ll->begin();i!=ll->end();i++) { switch( (*i)->WhatIs() ) { case VariableEnt: { VariableEntry *var=(VariableEntry*) (*i); int sub=var->GetSize(); if(sub>maxsize) maxsize=sub; break; } case TypeEnt: case EnumEnt: continue; default: assert(0==1); } } return maxsize; } int get_sizeof_vars_in_scope(Scope *sc) { ListType::iterator i; ListType *ll=sc->GetListEntity(); int total=0; int bits=0; for(i=ll->begin();i!=ll->end();i++) { switch( (*i)->WhatIs() ) { case VariableEnt: { //Let's get the VariableEntry... VariableEntry *var=(VariableEntry*) (*i); //There are two choises.... //var->GetSize() returns the bytes of the //type OR //throws an integer which represents the bitfield //member try { //Get the member size int sub=var->GetSize(); //Align the previous size accordingly if(not_aligned(total,sub)) fix_align(total,sub); //Add the member size total+=sub; //In case there where bitfields before this variable //add the bitfield size and zero the bitfield counter fix_bitfield(total,bits); } catch (int *bit_width) { //Just keep a count of the bits... bits+=*bit_width; } break; } case TypeEnt: case EnumEnt: continue; default: assert(0==1); } } return total; } void fix_struct_size_alignment(Ctype *ddd,Ctype::DefStyle st) { //Let's find new struct's scope Scope *sc=ddd->type_attr->GetScope(); //Adjust the alignment of the structure //according to ANSI-C int ali=get_lcm_of_alignments(sc); ddd->type_attr->SetAlignment(ali); int size; if(st==Ctype::STRUCTDEF) { //Adjust the size of the structure //considering the alignments of the members size=get_sizeof_vars_in_scope(sc); }else if (st==Ctype::UNIONDEF) { size=get_max_sizeof_vars_in_scope(sc); }else assert(0==1); if( not_aligned(size,ali) ) fix_align(size,ali); ddd->type_attr->SetSize(size); } int get_sizeof_ctype(Ctype *typ) { //Check the built-in types... int size; if(typ->style_attr==Ctype::SIMPLEDEF) { if(typ->mod_attr==Ctype::DEFMOD) { if(typ->type_attr==CharType) size = sizeof(char); if(typ->type_attr==IntType) size = sizeof(int); if(typ->type_attr==FloatType) size = sizeof(float); if(typ->type_attr==DoubleType) size = sizeof(double); if(typ->type_attr==VoidType) size = sizeof(void); } else if(typ->mod_attr==Ctype::SHORT) { // if(typ->type_attr==CharType) size = sizeof(short char); if(typ->type_attr==IntType) size = sizeof(short int); // if(typ->type_attr==FloatType) size = sizeof(short float); // if(typ->type_attr==DoubleType) size = sizeof(short double); // if(typ->type_attr==VoidType) size = sizeof(short void); } else if(typ->mod_attr==Ctype::LONG) { // if(typ->type_attr==CharType) size = sizeof(long char); if(typ->type_attr==IntType) size = sizeof(long int); // if(typ->type_attr==FloatType) size = sizeof(long float); if(typ->type_attr==DoubleType) size = sizeof(long double); // if(typ->type_attr==VoidType) size = sizeof(long void); } else if(typ->mod_attr==Ctype::LONGLONG) { // if(typ->type_attr==CharType) size = sizeof(long long char); if(typ->type_attr==IntType) size = sizeof(long long int); // if(typ->type_attr==FloatType) size = sizeof(long long float); if(typ->type_attr==DoubleType) size = sizeof(long long double); // if(typ->type_attr==VoidType) size = sizeof(long long void); } else { //No other built-in types... assert(0==1); } } else { //No built-in type... size = typ->type_attr->GetSize(); } return size; } int get_alignment_of_ctype(Ctype *typ) { //Check the built-in types... int size; //The following size = sizeof(...) //MAY BE re-written as eg. FloatType->GetSize() //Still don't know the alignment of e.g long double... if(typ->style_attr==Ctype::SIMPLEDEF) { if(typ->mod_attr==Ctype::DEFMOD) { if(typ->type_attr==CharType) size = sizeof(char); if(typ->type_attr==IntType) size = sizeof(int); if(typ->type_attr==FloatType) size = sizeof(float); if(typ->type_attr==DoubleType) size = sizeof(double); if(typ->type_attr==VoidType) size = sizeof(void); } else if(typ->mod_attr==Ctype::SHORT) { // if(typ->type_attr==CharType) size = sizeof(short char); if(typ->type_attr==IntType) size = sizeof(short int); // if(typ->type_attr==FloatType) size = sizeof(short float); // if(typ->type_attr==DoubleType) size = sizeof(short double); // if(typ->type_attr==VoidType) size = sizeof(short void); } else if(typ->mod_attr==Ctype::LONG) { // if(typ->type_attr==CharType) size = sizeof(long char); if(typ->type_attr==IntType) size = sizeof(long int); // if(typ->type_attr==FloatType) size = sizeof(long float); if(typ->type_attr==DoubleType) size = sizeof(long double); // if(typ->type_attr==VoidType) size = sizeof(long void); } else if(typ->mod_attr==Ctype::LONGLONG) { // if(typ->type_attr==CharType) size = sizeof(long long char); if(typ->type_attr==IntType) size = sizeof(long long int); // if(typ->type_attr==FloatType) size = sizeof(long long float); if(typ->type_attr==DoubleType) size = sizeof(long long double); // if(typ->type_attr==VoidType) size = sizeof(long long void); } else { //No other built-in types... assert(0==1); } } else { //No built-in type... size = typ->type_attr->GetAlignment(); } return size; } int get_alignment_of_ctype_cname(Ctype *typ,Cname *nam) { int ali; if(nam->star_list!=NULL) ali=sizeof(int*); else ali=get_alignment_of_ctype(typ); return ali; } int get_sizeof_ctype_cname(Ctype *typ,Cname *nam) { int size; if(nam->star_list!=NULL) size=sizeof(int*); else size=get_sizeof_ctype(typ); if(nam->array_sizes!=NULL) { gc_int_list::iterator i; for(i=nam->array_sizes->begin();i!=nam->array_sizes->end();i++) size*=(*i); } return size; } ostream& print_ctype(ostream &out,Ctype *typ) { out << Ctype::Duration2Str(typ->duration_attr) << Ctype::Sign2Str(typ->sign_attr) << Ctype::Modifier2Str(typ->mod_attr); if(typ->type_attr!=NULL) out << clean_Cname( typ->type_attr->GetCname() ); return out; } void ctype2str(Ctype *typ,char *buf) { //REMEMBER to allocate enough space for buf before calling sprintf(buf,"%s%s%s", Ctype::Duration2Str(typ->duration_attr), Ctype::Sign2Str(typ->sign_attr), Ctype::Modifier2Str(typ->mod_attr) ); if(typ->type_attr!=NULL) strcat(buf,clean_Cname(typ->type_attr->GetCname())); } ostream& print_cname(ostream&out,Cname *nam) { if(nam->star_list!=NULL) { gc_Cstar_list::iterator i; for(i=nam->star_list->begin();i!=nam->star_list->end();i++) { if( (*i)->const_attr == Cstar::CONSTATTR ) out << " const * "; else out << '*'; } } if(nam->constant) out << "const "; out << nam->name; if(nam->array_sizes!=NULL) { gc_int_list::iterator i; for(i=nam->array_sizes->begin();i!=nam->array_sizes->end();i++) { if( (*i)!=-1 ) out << '[' << (*i) << ']'; else out << "[]"; } } if(nam->width!=0) out << ':' << nam->width; if(nam->next) { out << '('; print_cname(out,nam->next); out << ')'; } if(nam->function) { out << '('; if(nam->parameters) { gc_type_id_list::iterator i; i=nam->parameters->begin(); if(i!=nam->parameters->end()) { do { print_ctype_cname( out, (*i)->first, (*i)->second ); i++; if(i==nam->parameters->end()) break; out << ','; }while(1); } }else out << "void"; out << ")"; } return out; } ostream& print_ctype_cname(ostream&out,Ctype* typ,Cname *nam) { print_ctype(out,typ); out << ' '; print_cname(out,nam); return out; } ostream& print_headers(ostream &out,Scope*sc) { ListType::iterator i; ListType *ll=sc->GetListEntity(); for(i=ll->begin();i!=ll->end();i++) { switch( (*i)->WhatIs() ) { case VariableEnt: { VariableEntry *var=(VariableEntry*)(*i); if(var->GetCname()->function) { print_ctype_cname(out,var->GetCtype(),var->GetCname()); out << ';' << endl; } break; } case TypeEnt: case EnumEnt: continue; default: assert(0==1); } } return out; } char* create_param_name() { sprintf(param_name,"par_%d",param_num); param_num++; return param_name; } void fix_param_name(Cname *cn) { Cname *cur=cn; assert(cur!=NULL); while(cur->next!=NULL) { assert(cur->name[0]=='\0'); cur=cur->next; } strcpy(cur->name,create_param_name()); } bool IsVoid(Ctype *typ,Cname *nam) { return (typ->type_attr==VoidType) && (nam->star_list==NULL) && (nam->next==NULL); } bool IsCharPtr(Ctype *typ,Cname *nam) { if(typ->type_attr==CharType) if(nam->star_list!=NULL) return nam->star_list->size()==1; return false; }