/* $Id: gen.cc,v 1.3 1997/08/02 08:42:05 isis Exp $ */ // $Log: gen.cc,v $ // Revision 1.3 1997/08/02 08:42:05 isis // Generator now prints "char*" as strings as well // // Revision 1.2 1997/07/30 17:46:14 isis // Some minor new features and bug fixes // This seems to work fine // // Revision 1.1 1997/06/22 14:48:44 isis // This is the initial version for // the generating functions module // #include #include #include #include #include #include #include "Cname.h" #include "symbol.h" #include "gc_stl.h" #include "h-fun.h" void generate_clean_argument(ostream &out,Ctype *ct,Cname *cn); bool argument_is_ellipsis(Ctype *ct,Cname *); void gen_warning(char *str) { cerr << "Generator: " << str << endl; } void generate_clean_argument_list(ostream &out,Cname *cn) { gc_type_id_list::iterator i; if(cn->parameters) { i=cn->parameters->begin(); if(i!=cn->parameters->end()) { if(!argument_is_ellipsis((*i)->first,(*i)->second)) generate_clean_argument( out,(*i)->first,(*i)->second ); else out << "valist"; i++; } while(i!=cn->parameters->end()) { if(!argument_is_ellipsis((*i)->first,(*i)->second)) { out << ','; generate_clean_argument( out,(*i)->first,(*i)->second ); }else out << ",valist"; //Ellipsis is handled i++; } } } bool is_function_with_ellipsis(Cname *cn) { gc_type_id_list::iterator i; bool ret=false; if(cn->parameters) { for(i=cn->parameters->begin();i!=cn->parameters->end();i++) { if(argument_is_ellipsis( (*i)->first, (*i)->second )) { ret=true; break; } } } return ret; } void get_clean_last_arg_no_ellipsis(Cname *cn,char *buf) { gc_type_id_list::iterator i,last; buf[0]='\0'; if(cn->parameters) { last=cn->parameters->end(); for(i=cn->parameters->begin();i!=cn->parameters->end();i++) { if(argument_is_ellipsis( (*i)->first, (*i)->second )) break; last=i; } if(last!=cn->parameters->end()) strcpy(buf,clean_Cname( (*last)->second )); } } //Cname may be null, Ctype cannot! char* get_printf_specifier(Ctype *ct,Cname *cn) { Cname *cur=cn; //Check if it is a pointer while(cur!=NULL) { if(cur->star_list!=NULL) return "%X"; cur=cur->next; } //if it is built-in type if(ct->style_attr==Ctype::SIMPLEDEF) { if(ct->type_attr==CharType) return "%c"; if(ct->type_attr==FloatType) return "%f"; if(ct->type_attr==DoubleType) return "%f"; if(ct->type_attr==VoidType) assert(0==1); if(ct->type_attr==IntType) { if(ct->sign_attr==Ctype::SIGNED || ct->sign_attr==Ctype::DEFSIGN) { switch(ct->mod_attr) { case Ctype::SHORT: return "%hd"; case Ctype::LONG: return "%ld"; case Ctype::LONGLONG: return "%ld"; case Ctype::DEFMOD: return "%d"; default: assert(0==1); } }else { switch(ct->mod_attr) { case Ctype::SHORT: return "%hu"; case Ctype::LONG: return "%lu"; case Ctype::LONGLONG: return "%lu"; case Ctype::DEFMOD: return "%u"; default: assert(0==1); } } } if(ct->type_attr==EllipsisType) return ""; } //If it is a typedef if(ct->style_attr==Ctype::DEFTYPED) return get_printf_specifier(ct->type_attr->GetCtype(),ct->type_attr->GetCname()); //If it is a struct/union definition.. if(ct->style_attr==Ctype::STRUCTDEF || ct->style_attr==Ctype::UNIONDEF) { return ""; //struct/union not supported } if(ct->style_attr==Ctype::ENUMDEF) { return ""; //enum not supported } assert(0==1); } void generate_clean_argument(ostream &out,Ctype *ct,Cname *cn) { if(ct->type_attr==EllipsisType) { }else { out << clean_Cname(cn); } } bool argument_is_ellipsis(Ctype *ct,Cname *) { return(ct->type_attr==EllipsisType); } void generate_print_args(ostream &out,Cname *nam) { gc_type_id_list::iterator i; if(nam->parameters) { for(i=nam->parameters->begin();i!=nam->parameters->end();i++) { if(!argument_is_ellipsis( (*i)->first, (*i)->second )) { Cname tmp( *(*i)->second ); tmp.ReplaceName(""); tmp.RemoveArgNames(); out << "\t\tfprintf(stderr,\"(" ; print_ctype_cname(out, (*i)->first, &tmp); out << ")" << get_printf_specifier((*i)->first,&tmp) << " \","; generate_clean_argument(out,(*i)->first,(*i)->second); out << ");" << endl; #ifdef GEN_CHARPTR // In case of "char *" we print the string as well... if(IsCharPtr( (*i)->first, (*i)->second )) { out << "\t\tfprintf(stderr,\"\\\"%s\\\" \",(("; generate_clean_argument(out,(*i)->first,(*i)->second); out << ")==NULL) ? ( \"NULL\" ) : ("; generate_clean_argument(out,(*i)->first,(*i)->second); out << ") );" << endl; } #endif } } } } ostream& generate_functions(ostream &out,Scope*sc) { //Some initialisation out << "static int __J_102_inside_counter=0;" << endl; 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) { out << "#ifdef " << clean_Cname(var->GetCname()) << endl; out << " #undef " << clean_Cname(var->GetCname()) << endl; out << "#endif" << endl; print_ctype_cname(out,var->GetCtype(),var->GetCname()); out << " {" << endl; // BEGIN write(out,code2generate) { // write va_list definition (if needed) // and issue a warning if(is_function_with_ellipsis(var->GetCname())) { out << "\tva_list valist;" << endl; char buf[255]; sprintf(buf,"v%s",clean_Cname(var->GetCname())); char msg[255]; sprintf(msg,"Assuming there is function '%s'",buf); gen_warning(msg); //write "v" fname out << "\tchar fname[]=\"" << buf << "\";" << endl; } else { //char fname[]="...."; out << "\tchar fname[]=\"" << clean_Cname(var->GetCname()) << "\";" << endl; } // write "ret" definition // ... ret; if(!IsVoid(var->GetCtype(),var->GetCname())) { out << "\t"; Cname temp(*(var->GetCname())); temp.ReplaceName("ret"); temp.RemoveArgs(); print_ctype_cname(out,var->GetCtype(),&temp); out << ';' << endl; } } { // write "call" definition Cname call_fun( *(var->GetCname()) ); call_fun.ReplaceName(""); call_fun.RemoveArgNames(); gc_Cstar_list stars; stars.push_back(new Cstar); Cname ptr_fun(&stars,"call",0,NULL,NULL,false); Cname *cur=&call_fun; while(cur->next!=NULL) cur=cur->next; cur->next = &ptr_fun; out << '\t'; print_ctype_cname(out,var->GetCtype(),&call_fun); out << ';' << endl; } //Write initialization of va_list (if needed) { if(is_function_with_ellipsis(var->GetCname())) { char buf[255]; get_clean_last_arg_no_ellipsis(var->GetCname(),buf); out << "\tva_start(valist," << buf << ");" << endl; } } //Write argument information { out << "\t__J_102_inside_counter++;" << endl; out << "\tif(__J_102_inside_counter==1) {" << endl; out << "\t\tfprintf(stderr,\"" << clean_Cname(var->GetCname()) << "(\");" << endl; generate_print_args(out,var->GetCname()); out << "\t\tfprintf(stderr,\")\\n\");" << endl; out << "\t\tfflush(stderr);\n" << endl; out << "\t}" << endl; } { // initialize "call" Cname call_fun( *(var->GetCname()) ); call_fun.ReplaceName(""); call_fun.RemoveArgNames(); gc_Cstar_list stars; stars.push_back(new Cstar); Cname ptr_fun(&stars,"",0,NULL,NULL,false); Cname *cur=&call_fun; while(cur->next!=NULL) cur=cur->next; cur->next = &ptr_fun; out << '\t';out << "call = ("; print_ctype_cname(out,var->GetCtype(),&call_fun); out << ") dlget(fname);" << endl; } { // do "call" out << '\t'; if(!IsVoid(var->GetCtype(),var->GetCname())) out << "ret = "; out << "(*call)("; generate_clean_argument_list(out,var->GetCname()); out << ");" << endl; } // write return information and return value { if(!IsVoid(var->GetCtype(),var->GetCname())) { Cname tmp(*(var->GetCname())); tmp.ReplaceName(""); tmp.RemoveArgs(); out << "\tif(__J_102_inside_counter==1) {" << endl; out << "\t\tfprintf(stderr,\"Returns: ("; print_ctype_cname(out,var->GetCtype(),&tmp); out << ")" << get_printf_specifier(var->GetCtype(),&tmp); out << "\\n\",ret);" << endl; out << "\t}" << endl; out << "\t__J_102_inside_counter--;" << endl; out << "\treturn ret;" << endl; } } // END write(out,code2generate) out << "}" << endl << endl; } break; } case TypeEnt: case EnumEnt: continue; default: assert(0==1); } } return out; }