// @(#)root/core:$Id$ // author: Lukasz Janyst #include "RConversionRuleParser.h" #include "TSchemaRuleProcessor.h" #include #include #include #include #include namespace ROOT { typedef std::list > SourceTypeList_t; //-------------------------------------------------------------------------- // Allocate global variables //-------------------------------------------------------------------------- SchemaRuleClassMap_t G__ReadRules; SchemaRuleClassMap_t G__ReadRawRules; static Bool_t ValidateRule( const std::map& rule, std::string &error_string ); static std::string::size_type FindEndSymbol(std::string &command) { // Find the end of a symbol. if (command.length() == 0) return std::string::npos; std::string::size_type cursor; unsigned int level = 0; for (cursor = 0 ; cursor < command.length(); ++cursor) { switch( command[cursor] ) { case ' ': case '\t': case '\r': case '=': if (level==0) { std::string::size_type sub_cursor = cursor; while( isspace(command[sub_cursor]) ) { ++sub_cursor; } if ( command[sub_cursor] == '=' ) { return sub_cursor; } else { return cursor; } } else { break; } case '<': ++level; break; case '>': if (level==0) { return std::string::npos; } --level; break; default: { // nothing to do } }; } return cursor; } //-------------------------------------------------------------------------- Bool_t ParseRule( std::string command, std::map &result, std::string &error_string ) { // Parse the schema rule as specified in the LinkDef file std::string::size_type l; command = TSchemaRuleProcessor::Trim( command ); //----------------------------------------------------------------------- // Remove the semicolon from the end if declared //----------------------------------------------------------------------- if( command[command.size()-1] == ';' ) command = command.substr( 0, command.size()-1 ); //----------------------------------------------------------------------- // If the first symbol does not end is not followed by equal then it // defaults to being the sourceClass. //----------------------------------------------------------------------- { std::string::size_type endsymbol = FindEndSymbol( command ); if ( endsymbol == command.length() || command[endsymbol] == ' ' || command[endsymbol] == '\t' ) { // std::string::size_type space_pos = command.find( ' ' ); // std::string::size_type equal_pos = command.find( '=' ); // if ( space_pos < equal_pos) { std::string value = TSchemaRuleProcessor::Trim( command.substr( 0, endsymbol ) ); result["sourceClass"] = value; result["targetClass"] = value; if (endsymbol < command.length()) { command = TSchemaRuleProcessor::Trim( command.substr( endsymbol+1 ) ); } else { command.clear(); } //----------------------------------------------------------------------- // If the first symbol is the targetClass then the 2nd symbol can be // the source data member name. //----------------------------------------------------------------------- // space_pos = command.find( ' ' ); // equal_pos = command.find( '=' ); // if ( space_pos < equal_pos ) { endsymbol = FindEndSymbol( command ); if ( endsymbol == command.length() || command[endsymbol] == ' ' || command[endsymbol] == '\t' ) { std::string membervalue = TSchemaRuleProcessor::Trim( command.substr( 0, endsymbol ) ); result["source"] = membervalue; result["target"] = membervalue; command = TSchemaRuleProcessor::Trim( command.substr( endsymbol+1 ) ); } } } //----------------------------------------------------------------------- // Process the input until there are no characters left //----------------------------------------------------------------------- while( !command.empty() ) { //-------------------------------------------------------------------- // Find key token //-------------------------------------------------------------------- std::string::size_type pos = command.find( '=' ); //-------------------------------------------------------------------- // No equality sign found - no keys left //-------------------------------------------------------------------- if( pos == std::string::npos ) { error_string = "Parsing error, no key found!"; return false; } //-------------------------------------------------------------------- // The key was found - process the arguments //-------------------------------------------------------------------- std::string key = TSchemaRuleProcessor::Trim( command.substr( 0, pos ) ); command = TSchemaRuleProcessor::Trim( command.substr( pos+1 ) ); //-------------------------------------------------------------------- // Nothing left to be processed //-------------------------------------------------------------------- if( command.size() < 1 ) { error_string = "Parsing error, wrond or no value specified for key: " + key; return false; } Bool_t hasquote = command[0] == '"'; //-------------------------------------------------------------------- // Processing code tag: "{ code }" //-------------------------------------------------------------------- if( key == "code" ) { if( command[1] != '{' ) { error_string = "Parsing error while processing key: code\n"; error_string += "Expected \"{ at the beginning of the value."; return false; } l = command.find( "}\"" ); if( l == std::string::npos ) { error_string = "Parsing error while processing key: \"" + key + "\"\n"; error_string += "Expected }\" at the end of the value."; return false; } result[key] = command.substr( 2, l-2 ); ++l; } //-------------------------------------------------------------------- // Processing normal tag: "value" //-------------------------------------------------------------------- else { if( hasquote) { l = command.find( '"', 1 ); if (l == std::string::npos ) { error_string = "\nParsing error while processing key: \"" + key + "\"\n"; error_string += "Expected \" at the end of the value."; return false; } result[key] = command.substr( 1, l-1 ); } else { l = command.find(' ', 1); if (l == std::string::npos) l = command.size(); result[key] = command.substr( 0, l ); } } //-------------------------------------------------------------------- // Everything went ok //-------------------------------------------------------------------- if( l == command.size() ) break; command = command.substr( l+1 ); } std::map::const_iterator it1; it1 = result.find("oldtype"); if ( it1 != result.end() ) { std::map::const_iterator it2; it2 = result.find("source"); if ( it2 != result.end() ) { result["source"] = it1->second + " " + it2->second; } } if ( result.find("version") == result.end() && result.find("checksum") == result.end() ) { result["version"] = "[1-]"; } return ValidateRule( result, error_string); } //-------------------------------------------------------------------------- static Bool_t ValidateRule( const std::map& rule, std::string &error_string ) { // Validate if the user specified rules are correct //----------------------------------------------------------------------- // Check if we have target class name //----------------------------------------------------------------------- std::map::const_iterator it1, it2; std::list lst; std::list::iterator lsIt; it1 = rule.find( "targetClass" ); if( it1 == rule.end() ) { error_string = "WARNING: You always have to specify the targetClass "; error_string += "when specyfying an IO rule"; return false; } std::string className = TSchemaRuleProcessor::Trim( it1->second ); std::string warning = "WARNING: IO rule for class " + className; //----------------------------------------------------------------------- // Check if we have the source tag //----------------------------------------------------------------------- it1 = rule.find( "sourceClass" ); if( it1 == rule.end()) { error_string = warning + " - sourceClass parameter is missing"; return false; } //----------------------------------------------------------------------- // Check if we have either version or checksum specified //----------------------------------------------------------------------- it1 = rule.find( "version" ); it2 = rule.find( "checksum" ); if( it1 == rule.end() && it2 == rule.end() ) { error_string = warning + " - you need to specify either version or "; error_string += "checksum"; return false; } //----------------------------------------------------------------------- // Check if the checksum has been set to right value //----------------------------------------------------------------------- if( it2 != rule.end() ) { if( it2->second.size() < 2 || it2->second[0] != '[' || it2->second[it2->second.size()-1] != ']' ) { error_string = warning + " - a comma separated list of ints "; error_string += "enclosed in square brackets expected"; error_string += "as a value of checksum parameter"; return false; } TSchemaRuleProcessor::SplitList( it2->second.substr( 1, it2->second.size()-2 ), lst ); if( lst.empty() ) { std::cout << warning << " - the list of checksums is empty"; std::cout << std::endl; } for( lsIt = lst.begin(); lsIt != lst.end(); ++lsIt ) if( !TSchemaRuleProcessor::IsANumber( *lsIt ) ) { error_string = warning + " - " + *lsIt + " is not a valid value"; error_string += " of checksum parameter - an integer expected"; return false; } } //----------------------------------------------------------------------- // Check if the version is correct //----------------------------------------------------------------------- std::pair ver; if( it1 != rule.end() ) { if( it1->second.size() < 2 || it1->second[0] != '[' || it1->second[it1->second.size()-1] != ']' ) { error_string = warning + " - a comma separated list of version specifiers "; error_string += "enclosed in square brackets expected"; error_string += "as a value of version parameter"; return false; } TSchemaRuleProcessor::SplitList( it1->second.substr( 1, it1->second.size()-2 ), lst ); if( lst.empty() ) { error_string = warning + " - the list of versions is empty"; } for( lsIt = lst.begin(); lsIt != lst.end(); ++lsIt ) if( !TSchemaRuleProcessor::ProcessVersion( *lsIt, ver ) ) { error_string = warning + " - " + *lsIt + " is not a valid value"; error_string += " of version parameter"; return false; } } //----------------------------------------------------------------------- // Check if we're dealing with renameing declaration - sourceClass, // targetClass and either version or checksum required //----------------------------------------------------------------------- if( rule.size() == 3 || (rule.size() == 4 && it1 != rule.end() && it2 != rule.end()) ) return true; //----------------------------------------------------------------------- // Check if we have all the keys we need //----------------------------------------------------------------------- std::string keys[] = {"target", "source"}; for( int i = 0; i < 2; ++i ) { it1 = rule.find( keys[i] ); if( it1 == rule.end() ) { error_string = warning + " - required parameter is missing: "; error_string += keys[i]; return false; } } //----------------------------------------------------------------------- // Check the source contains proper declarations. //----------------------------------------------------------------------- it1 = rule.find("code"); if (it1 != rule.end() && it1->second != "") { SourceTypeList_t source; TSchemaRuleProcessor::SplitDeclaration( rule.find("source")->second, source ); SourceTypeList_t::const_iterator it; for( it = source.begin(); it != source.end(); ++it ) { if ( ( it->first.fType == "" && it->second != "") ) { error_string = warning + " - type required when listing a rule's source: "; error_string += "source=\""+ rule.find("source")->second +"\""; return false; } } } //----------------------------------------------------------------------- // Check if we have an embed parameter and if so if it has been set to // the right value //----------------------------------------------------------------------- it1 = rule.find( "embed" ); if( it1 != rule.end() ) { std::string emValue = TSchemaRuleProcessor::Trim( it1->second ); if( emValue != "true" && emValue != "false" ) { error_string = warning + " - true or false expected as a value "; error_string += "of embed parameter"; return false; } } //----------------------------------------------------------------------- // Check if the include list is not empty //----------------------------------------------------------------------- it1 = rule.find( "include" ); if( it1 != rule.end() ) { if( it1->second.empty() ) { error_string = warning + " - the include list is empty"; return false; } } return true; } //-------------------------------------------------------------------------- void CreateNameTypeMap( G__ClassInfo &cl, MembersTypeMap_t& nameType ) { // Create the data member name-type map for given class G__DataMemberInfo member( cl ); std::string dims; while( member.Next() ) { if (((member.Type()->Property() & G__BIT_ISCONSTANT) && (member.Type()->Property() & G__BIT_ISENUM)) // an enum const || (member.Property() & G__BIT_ISSTATIC)) // a static member continue; if (strcmp("G__virtualinfo", member.Name()) == 0) continue; dims.clear(); for (int dim = 0; dim < member.ArrayDim(); dim++) { char cdim[24]; static const int maxsize = sizeof(cdim)/sizeof(cdim[0]); #ifdef _MSC_VER int result = _snprintf(cdim,maxsize,"[%ld]",member.MaxIndex(dim)); #else int result = snprintf(cdim,maxsize,"[%ld]",member.MaxIndex(dim)); #endif if (result > maxsize) { std::cout << "Error: array size is to large, the size '" << member.MaxIndex(dim) << "' does not fit in " << maxsize << " characters.\n"; } dims += cdim; } nameType[member.Name()] = TSchemaType(member.Type()->Name(),dims.c_str()); } G__BaseClassInfo base( cl ); while( base.Next() ) { nameType[base.Name()] = TSchemaType(base.Name(),""); } } //--------------------------------------------------------------------------- Bool_t HasValidDataMembers( SchemaRuleMap_t& rule, MembersTypeMap_t& members ) { // Check if given rule contains references to valid data members std::list mem; std::list::iterator it; // MembersMap_t::iterator rIt; TSchemaRuleProcessor::SplitList( rule["target"], mem ); //----------------------------------------------------------------------- // Loop over the data members //----------------------------------------------------------------------- for( it = mem.begin(); it != mem.end(); ++it ) { if( members.find( *it ) == members.end() ) { std::cout << "WARNING: IO rule for class " + rule["targetClass"]; std::cout << " data member: " << *it << " was specified as a "; std::cout << "target in the rule but doesn't seem to appear in "; std::cout << "target class" << std::endl; return false; } } return true; } //-------------------------------------------------------------------------- static void WriteAutoVariables( const std::list& target, const SourceTypeList_t& source, MembersTypeMap_t& members, std::string& className, std::string& mappedName, std::ostream& output ) { //----------------------------------------------------------------------- // Write down the sources //----------------------------------------------------------------------- if (!source.empty()) { Bool_t start = true; SourceTypeList_t::const_iterator it; //-------------------------------------------------------------------- // Write IDs and check if we should generate the onfile structure // this is done if the type was declared //-------------------------------------------------------------------- Bool_t generateOnFile = false; output << "#if 0" << std::endl; // this is to be removed later for( it = source.begin(); it != source.end(); ++it ) { output << " "; output << "static Int_t id_" << it->second << " = oldObj->GetId("; output << "\"" << it->second << "\");" << std::endl; if( it->first.fType != "" ) generateOnFile = true; } output << "#endif" << std::endl; // this is to be removed later //-------------------------------------------------------------------- // Declare the on-file structure - if needed //-------------------------------------------------------------------- if( generateOnFile ) { std::string onfileStructName = mappedName + "_Onfile"; output << " "; output << "struct " << onfileStructName << " {\n"; //----------------------------------------------------------------- // List the data members with non-empty type declarations //----------------------------------------------------------------- for( it = source.begin(); it != source.end(); ++it ) { // fprintf(stderr, "Seeing %s %s %s\n", it->first.fType.c_str(), it->second.c_str(), it->first.fDimensions.c_str()); if( it->first.fType.size() ) { if ( it->first.fDimensions.size() ) { output << " typedef " << it->first.fType; output << " onfile_" << it->second << "_t" << it->first.fDimensions << ";\n"; output << " "; output << "onfile_" << it->second << "_t &" << it->second << ";\n"; } else { output << " "; output << it->first.fType << " &" << it->second << ";\n"; } } } //----------------------------------------------------------------- // Generate the constructor //----------------------------------------------------------------- output << " " << onfileStructName << "("; for( start = true, it = source.begin(); it != source.end(); ++it ) { if( it->first.fType.size() == 0) continue; if( !start ) output << ", "; else start = false; if (it->first.fDimensions.size() == 0) { output << it->first.fType << " &onfile_" << it->second; } else { output << " onfile_" << it->second << "_t" << " &onfile_" << it->second; } } output << " ): "; //----------------------------------------------------------------- // Generate the constructor's initializer list //----------------------------------------------------------------- for( start = true, it = source.begin(); it != source.end(); ++it ) { if( it->first.fType == "" ) continue; if( !start ) output << ", "; else start = false; output << it->second << "(onfile_" << it->second << ")"; } output << " {}\n"; output << " " << "};\n"; //----------------------------------------------------------------- // Initialize the structure - to be changed later //----------------------------------------------------------------- for( it = source.begin(); it != source.end(); ++it ) { output << " "; output << "static Long_t offset_Onfile_" << mappedName; output << "_" << it->second << " = oldObj->GetClass()->GetDataMemberOffset(\""; output << it->second << "\");\n"; } output << " " << "char *onfile_add = (char*)oldObj->GetObject();\n"; output << " " << mappedName << "_Onfile onfile(\n"; for( start = true, it = source.begin(); it != source.end(); ++it ) { if( it->first.fType == "" ) continue; if( !start ) output << ",\n"; else start = false; output << " "; output << "*("; if (it->first.fDimensions.size() == 0) { output << it->first.fType; } else { output << mappedName << "_Onfile::onfile_" << it->second << "_t"; } output << "*)(onfile_add+offset_Onfile_"; output << mappedName << "_" << it->second << ")"; } output << " );\n\n"; } } //----------------------------------------------------------------------- // Write down the targets //----------------------------------------------------------------------- if( !target.empty() ) { output << " static TClassRef cls(\""; output << className << "\");" << std::endl; std::list::const_iterator it; for( it = target.begin(); it != target.end(); ++it ) { TSchemaType memData = members[*it]; output << " static Long_t offset_" << *it << " = "; output << "cls->GetDataMemberOffset(\"" << *it << "\");"; output << std::endl; if (memData.fDimensions.size()) { output << " typedef " << memData.fType << " " << *it << "_t" << memData.fDimensions << ";" << std::endl; output << " " << *it << "_t& " << *it << " = "; output << "*(" << *it << "_t *)(target+offset_" << *it; output << ");" << std::endl; } else { output << " " << memData.fType << "& " << *it << " = "; output << "*(" << memData.fType << "*)(target+offset_" << *it; output << ");" << std::endl; } } } } //-------------------------------------------------------------------------- void WriteReadRuleFunc( SchemaRuleMap_t& rule, int index, std::string& mappedName, MembersTypeMap_t& members, std::ostream& output ) { // Write the conversion function for Read rule, the function name // is being written to rule["funcname"] std::string className = rule["targetClass"]; //----------------------------------------------------------------------- // Create the function name //----------------------------------------------------------------------- std::ostringstream func; func << "read_" << mappedName << "_" << index; rule["funcname"] = func.str(); //----------------------------------------------------------------------- // Write the header //----------------------------------------------------------------------- output << " static void " << func.str(); output << "( char* target, TVirtualObject *oldObj )" << std::endl; output << " {" << std::endl; output << " //--- Automatically generated variables ---" << std::endl; //----------------------------------------------------------------------- // Write the automatically generated variables //----------------------------------------------------------------------- std::list > source; std::list target; TSchemaRuleProcessor::SplitDeclaration( rule["source"], source ); TSchemaRuleProcessor::SplitList( rule["target"], target ); WriteAutoVariables( target, source, members, className, mappedName, output ); output << " " << className << "* newObj = (" << className; output << "*)target;" << std::endl; output << " // Supress warning message.\n"; output << " " << "if (oldObj) {}\n\n"; output << " " << "if (newObj) {}\n\n"; //----------------------------------------------------------------------- // Write the user's code //----------------------------------------------------------------------- output << " //--- User's code ---" << std::endl; output << " " << rule["code"] << std::endl; output << " }" << std::endl; } //-------------------------------------------------------------------------- void WriteReadRawRuleFunc( SchemaRuleMap_t& rule, int index, std::string& mappedName, MembersTypeMap_t& members, std::ostream& output ) { // Write the conversion function for ReadRaw rule, the function name // is being written to rule["funcname"] std::string className = rule["targetClass"]; //----------------------------------------------------------------------- // Create the function name //----------------------------------------------------------------------- std::ostringstream func; func << "readraw_" << mappedName << "_" << index; rule["funcname"] = func.str(); //----------------------------------------------------------------------- // Write the header //----------------------------------------------------------------------- output << " static void " << func.str(); output << "( char* target, TBuffer &b )" << std::endl; output << " {" << std::endl; output << "#if 0" << std::endl; output << " //--- Automatically generated variables ---" << std::endl; //----------------------------------------------------------------------- // Write the automatically generated variables //----------------------------------------------------------------------- std::list > source; std::list target; TSchemaRuleProcessor::SplitList( rule["target"], target ); WriteAutoVariables( target, source, members, className, mappedName, output ); output << " " << className << "* newObj = (" << className; output << "*)target;" << std::endl << std::endl; //----------------------------------------------------------------------- // Write the user's code //----------------------------------------------------------------------- output << " //--- User's code ---" << std::endl; output << rule["code"] << std::endl; output << "#endif" << std::endl; output << " }" << std::endl; } //-------------------------------------------------------------------------- static void StrReplace( std::string& proc, const std::string& pat, const std::string& tr ) { // Replace all accurances of given string with other string std::string::size_type it = 0; std::string::size_type s = pat.size(); std::string::size_type tr_len= tr.size(); if( s == 0 ) return; while( 1 ) { it = proc.find( pat, it ); if( it == std::string::npos ) break; proc.replace( it, s, tr ); it += tr_len; } } //-------------------------------------------------------------------------- void WriteSchemaList( std::list& rules, const std::string& listName, std::ostream& output ) { // Write schema rules std::list::iterator it; int i = 0; //----------------------------------------------------------------------- // Loop over the rules //----------------------------------------------------------------------- for( it = rules.begin(); it != rules.end(); ++it ) { output << " rule = &" << listName << "[" << i++; output << "];" << std::endl; //-------------------------------------------------------------------- // Write down the mandatory fields //-------------------------------------------------------------------- output << " rule->fSourceClass = \"" << (*it)["sourceClass"]; output << "\";" << std::endl; if( it->find( "target" ) != it->end() ) { output << " rule->fTarget = \"" << (*it)["target"]; output << "\";" << std::endl; } if( it->find( "source" ) != it->end() ) { output << " rule->fSource = \"" << (*it)["source"]; output << "\";" << std::endl; } //-------------------------------------------------------------------- // Deal with nonmandatory keys //-------------------------------------------------------------------- if( it->find( "funcname" ) != it->end() ) { std::string code = (*it)["code"]; StrReplace( code, "\n", "\\n" ); StrReplace( code, "\"", "\\\""); output << " rule->fFunctionPtr = (void *)G__func2void( "; output << (*it)["funcname"] << ");" << std::endl; output << " rule->fCode = \"" << code; output << "\";" << std::endl; } if( it->find( "version" ) != it->end() ) { output << " rule->fVersion = \"" << (*it)["version"]; output << "\";" << std::endl; } if( it->find( "checksum" ) != it->end() ) { output << " rule->fChecksum = \"" << (*it)["checksum"]; output << "\";" << std::endl; } if( it->find( "embed" ) != it->end() ) { output << " rule->fEmbed = " << (*it)["embed"]; output << ";" << std::endl; } if( it->find( "include" ) != it->end() ) { output << " rule->fInclude = \"" << (*it)["include"]; output << "\";" << std::endl; } if( it->find( "attributes" ) != it->end() ) { output << " rule->fAttributes = \"" << (*it)["attributes"]; output << "\";" << std::endl; } } } //-------------------------------------------------------------------------- void GetRuleIncludes( std::list &result ) { // Get the list of includes specified in the shema rules std::list tmp; std::list::iterator rule; SchemaRuleMap_t::iterator attr; SchemaRuleClassMap_t::iterator it; //----------------------------------------------------------------------- // Processing read rules //----------------------------------------------------------------------- for( it = G__ReadRules.begin(); it != G__ReadRules.end(); ++it ) { for( rule = it->second.begin(); rule != it->second.end(); ++rule ) { attr = rule->find( "include" ); if( attr == rule->end() ) continue; TSchemaRuleProcessor::SplitList( attr->second, tmp ); result.splice( result.begin(), tmp, tmp.begin(), tmp.end() ); } } //----------------------------------------------------------------------- // Processing read raw rules //----------------------------------------------------------------------- for( it = G__ReadRawRules.begin(); it != G__ReadRawRules.end(); ++it ) { for( rule = it->second.begin(); rule != it->second.end(); ++rule ) { attr = rule->find( "include" ); if( attr == rule->end() ) continue; TSchemaRuleProcessor::SplitList( attr->second, tmp ); result.splice( result.begin(), tmp, tmp.begin(), tmp.end() ); } } //----------------------------------------------------------------------- // Removing duplicates //----------------------------------------------------------------------- result.sort(); result.unique(); } //-------------------------------------------------------------------------- void ProcessReadPragma( char* args ) { // I am being called when a read pragma is encountered //----------------------------------------------------------------------- // Parse the rule and check it's validity //----------------------------------------------------------------------- std::map rule; std::string error_string; if( !ParseRule( args, rule, error_string ) ) { std::cout << error_string << '\n'; std::cout << "The following rule has been omited:" << std::endl; std::cout << " read " << args << std::endl; return; } //----------------------------------------------------------------------- // Append the rule to the list //----------------------------------------------------------------------- SchemaRuleClassMap_t::iterator it; std::string targetClass = rule["targetClass"]; it = G__ReadRules.find( targetClass ); if( it == G__ReadRules.end() ) { std::list lst; lst.push_back( rule ); G__ReadRules[targetClass] = lst; } else it->second.push_back( rule ); } //-------------------------------------------------------------------------- void ProcessReadRawPragma( char* args ) { // I am being called then a readraw pragma is encountered //----------------------------------------------------------------------- // Parse the rule and check it's validity //----------------------------------------------------------------------- std::map rule; std::string error_string; if( !ParseRule( args, rule, error_string ) ) { std::cout << error_string << '\n'; std::cout << "The following rule has been omited:" << std::endl; std::cout << " readraw " << args << std::endl; return; } //----------------------------------------------------------------------- // Append the rule to the list //----------------------------------------------------------------------- SchemaRuleClassMap_t::iterator it; std::string targetClass = rule["targetClass"]; it = G__ReadRawRules.find( targetClass ); if( it == G__ReadRawRules.end() ) { std::list lst; lst.push_back( rule ); G__ReadRawRules[targetClass] = lst; } else it->second.push_back( rule ); } }