22 #include "TClingUtils.h"
24 std::map<std::string, XMLReader::ETagNames> XMLReader::fgMapTagNames;
29 void XMLReader::PopulateMap(){
30 if (!(fgMapTagNames.empty()))
return;
32 XMLReader::fgMapTagNames[
"class"] = kClass;
33 XMLReader::fgMapTagNames[
"/class"] = kEndClass;
34 XMLReader::fgMapTagNames[
"struct"] = kClass;
35 XMLReader::fgMapTagNames[
"/struct"] = kEndClass;
36 XMLReader::fgMapTagNames[
"namespace"] = kClass;
37 XMLReader::fgMapTagNames[
"/namespace"] = kEndClass;
38 XMLReader::fgMapTagNames[
"function"] = kFunction;
39 XMLReader::fgMapTagNames[
"variable"] = kVariable;
40 XMLReader::fgMapTagNames[
"enum"] = kEnum;
41 XMLReader::fgMapTagNames[
"method"] = kMethod;
42 XMLReader::fgMapTagNames[
"/method"] = kEndMethod;
43 XMLReader::fgMapTagNames[
"field"] = kField;
44 XMLReader::fgMapTagNames[
"/field"] = kEndField;
45 XMLReader::fgMapTagNames[
"member"] = kField;
46 XMLReader::fgMapTagNames[
"/member"] = kEndField;
47 XMLReader::fgMapTagNames[
"lcgdict"] = kLcgdict;
48 XMLReader::fgMapTagNames[
"/lcgdict"] = kEndLcgdict;
49 XMLReader::fgMapTagNames[
"rootdict"] = kLcgdict;
50 XMLReader::fgMapTagNames[
"/rootdict"] = kEndLcgdict;
51 XMLReader::fgMapTagNames[
"selection"] = kSelection;
52 XMLReader::fgMapTagNames[
"/selection"] = kEndSelection;
53 XMLReader::fgMapTagNames[
"exclusion"] = kExclusion;
54 XMLReader::fgMapTagNames[
"/exclusion"] = kEndExclusion;
55 XMLReader::fgMapTagNames[
"properties"] = kProperties;
56 XMLReader::fgMapTagNames[
"version"] = kVersion;
57 XMLReader::fgMapTagNames[
"ioread"] = kBeginIoread;
58 XMLReader::fgMapTagNames[
"/ioread"] = kEndIoread;
59 XMLReader::fgMapTagNames[
"read"] = kBeginIoread;
60 XMLReader::fgMapTagNames[
"/read"] = kEndIoread;
61 XMLReader::fgMapTagNames[
"readraw"] = kBeginIoreadRaw;
62 XMLReader::fgMapTagNames[
"/readraw"] = kEndIoreadRaw;
63 XMLReader::fgMapTagNames[
"typedef"] = kTypedef;
72 bool XMLReader::GetNextTag(std::ifstream& file, std::string& out,
int& lineCount)
76 bool angleBraceLevel =
false;
79 bool tagIsComment =
false;
81 bool tagIsXMLDecl =
false;
83 bool isInlineComment = false ;
94 for (;i<3 && file.good();++i){
97 if (pattern ==
"lt;"){
100 else if (pattern ==
"gt;"){
104 for (;i!=0 && file.good();--i){
118 case '\n': ++lineCount;
120 case '"': quotes = !quotes;
123 if (!quotes) angleBraceLevel = !angleBraceLevel;
124 if (!angleBraceLevel && !comment)
return false;
127 if (!quotes && !comment) angleBraceLevel = !angleBraceLevel;
128 if (!angleBraceLevel && !comment) br =
true;
129 if (!angleBraceLevel && comment && charMinus2==
'-' && charMinus1==
'-') br =
true;
130 if (charMinus2==
'-' && charMinus1==
'-'){
131 if (comment) { tagIsComment=
true; br=
true; }
132 else {
return false; }
134 if (charMinus1==
'?'){
135 if (xmlDecl) {tagIsXMLDecl=
true;br=
true;}
140 if (charMinus3==
'<' && charMinus2==
'!' && charMinus1==
'-') comment = !comment;
143 if (charMinus1==
'<') xmlDecl=!xmlDecl;
146 if (charMinus1==
'/' && !angleBraceLevel && !comment){
147 isInlineComment=
true;
155 if (isInlineComment){
156 out.erase(out.size()-1,1);
157 while (file.good() && c!=
'\n'){
162 charMinus3=charMinus2;
163 charMinus2=charMinus1;
166 if (comment && !(charMinus3==
'-' && charMinus2==
'-' && charMinus1==
'>')){
177 int startpos = out.find_first_not_of(
" \t\n");
178 int endpos = out.find_last_not_of(
" \t\n");
181 if (((
int) std::string::npos == startpos ) || ((
int) std::string::npos == endpos))
186 out = out.substr( startpos, endpos-startpos+1 );
190 bool isTagOk = CheckIsTagOK(out);
191 if (tagIsComment || tagIsXMLDecl){
193 return GetNextTag(file,out,lineCount);
209 bool XMLReader::CheckIsTagOK(
const std::string& tag)
212 ROOT::TMetaUtils::Error(0,
"This is not a tag!\n");
217 if (tag.at(0) !=
'<'){
218 ROOT::TMetaUtils::Error(0,
"Malformed tag %s (tag doesn't begin with <)!\n", tag.c_str());
223 if (isspace(tag.at(1))){
224 ROOT::TMetaUtils::Error(0,
"Malformed tag %s (there should be no white-spaces between < and name-of-tag)!\n", tag.c_str());
230 for (std::string::size_type i = tag.length()-2;
true ; --i) {
237 if (c ==
'/' && countWSp>0) {
238 ROOT::TMetaUtils::Error(0,
"Malformed tag %s (there should be no white-spaces between / and >)!\n", tag.c_str());
251 int pos1 = tag.find(
">");
253 for (std::string::size_type i = pos1+1, e = tag.length(); i < e; ++i) {
275 bool XMLReader::IsStandaloneTag(
const std::string& tag)
277 std::string tagEnd = tag.substr(tag.length()-2, 2);
278 return (tagEnd ==
"/>");
285 bool XMLReader::IsClosingTag(
const std::string& tag)
287 std::string tagBegin = tag.substr(0, 2);
288 return (tagBegin ==
"</");
296 XMLReader::ETagNames XMLReader::GetNameOfTag(
const std::string& tag, std::string& name)
298 for (std::string::size_type i = 0, e = tag.length(); i < e; ++i) {
300 if (isspace(c))
break;
301 if ((c !=
'<') && (c !=
'>'))
305 std::map<std::string, ETagNames>::iterator it;
306 it = XMLReader::fgMapTagNames.find(name);
307 if (it != XMLReader::fgMapTagNames.end())
308 return XMLReader::fgMapTagNames[name];
321 bool XMLReader::GetAttributes(
const std::string& tag, std::vector<Attributes>& out,
const char* lineNum)
325 GetNameOfTag(tag,name);
327 bool standalone = IsStandaloneTag(tag);
330 std::string::size_type cutend = tag.length() - 1 - name.length();
331 if (standalone) --cutend;
332 std::string attrstr = tag.substr(1 + name.length(), cutend);
334 if (attrstr.length() > 4) {
336 int pos = attrstr.find_last_not_of(
" \t\n");
337 attrstr = attrstr.substr(1, pos+1);
346 std::string attrtemp;
347 bool namefound =
false;
348 bool equalfound =
false;
351 bool inString =
false;
352 std::string attr_name;
353 std::string attr_value;
354 char lastsymbol =
'\0';
356 for (std::string::size_type i = 0, e = attrstr.length()-1; i < e; ++i) {
361 ROOT::TMetaUtils::Error(0,
"At line %s. No name of attribute\n", lineNum);
373 else if (isspace(c) && !inString)
continue;
377 if (namefound && equalfound){
383 if (attr_name.length() == 0) {
384 ROOT::TMetaUtils::Error(0,
"At line %s. Attribute - missing attribute name!\n", lineNum);
402 ROOT::TMetaUtils::Info(0,
"*** Attribute: %s = \"%s\"\n", attr_name.c_str(), attr_value.c_str());
403 if (attr_name==
"pattern" && attr_value.find(
"*") == std::string::npos){
404 ROOT::TMetaUtils::Warning(0,
"At line %s. A pattern, \"%s\", without wildcards is being used. This selection rule would not have any effect. Transforming it to a rule based on name.\n", lineNum, attr_value.c_str());
407 out.emplace_back(attr_name, attr_value);
418 ROOT::TMetaUtils::Error(0,
"At line %s. Attribute - missing attribute name or =\n", lineNum);
422 else if (lastsymbol ==
'=') {
425 ROOT::TMetaUtils::Error(0,
"At line %s. Wrong quotes placement or lack of quotes\n", lineNum);
428 else if ((newattr || namefound) && !value){
439 if (namefound && (!equalfound || !value)) {
440 ROOT::TMetaUtils::Error(0,
"At line %s. Attribute - missing attribute value\n", lineNum);
453 bool XMLReader::Parse(
const std::string &fileName, SelectionRules& out)
456 std::ifstream file(fileName);
461 bool exclusion =
false;
462 bool selection =
false;
465 bool exclEnd =
false;
467 bool inIoread =
false;
468 bool inClass =
false;
469 bool inMethod =
false;
470 bool inField =
false;
472 BaseSelectionRule *bsr = 0;
473 BaseSelectionRule *bsrChild = 0;
474 std::unique_ptr<ClassSelectionRule> csr;
475 std::unique_ptr<FunctionSelectionRule> fsr;
476 std::unique_ptr<VariableSelectionRule> vsr;
477 std::unique_ptr<EnumSelectionRule> esr;
482 bool tagOK = GetNextTag(file, tagStr, lineNum);
484 const char* tagStrCharp = tagStr.c_str();
486 std::ostringstream buf;
488 std::string lineNumStr = buf.str();
489 const char* lineNumCharp = lineNumStr.c_str();
491 ROOT::TMetaUtils::Error(0,
"At line %s. Bad tag: %s\n", lineNumCharp, tagStrCharp);
492 out.ClearSelectionRules();
496 if (!tagStr.empty()){
497 std::vector<Attributes> attrs;
499 ETagNames tagKind = GetNameOfTag(tagStr, name);
500 bool attrError = GetAttributes(tagStr, attrs, lineNumCharp);
502 ROOT::TMetaUtils::Error(0,
"Attribute at line %s. Bad tag: %s\n", lineNumCharp, tagStrCharp);
503 out.ClearSelectionRules();
511 ROOT::TMetaUtils::Error(0,
"At line %s. Unrecognized name of tag %s\n", lineNumCharp, tagStrCharp);
512 out.ClearSelectionRules();
519 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
520 out.ClearSelectionRules();
523 if (!IsStandaloneTag(tagStr)){
526 csr.reset(
new ClassSelectionRule(fCount++, fInterp, fileName.c_str(), lineNum));
527 csr->SetRequestStreamerInfo(
true);
535 out.AddClassSelectionRule(*csr);
539 ROOT::TMetaUtils::Error(0,
"Single </class> tag at line %s",lineNumCharp);
540 out.ClearSelectionRules();
548 ROOT::TMetaUtils::Error(0,
"Version tag not within class element at line %s",lineNumCharp);
549 out.ClearSelectionRules();
555 case kBeginIoreadRaw:
559 std::streampos initialPos(file.tellg());
560 const unsigned int lineCharsSize=1000;
561 char lineChars[lineCharsSize];
562 file.getline(lineChars,lineCharsSize);
563 std::string lineStr(lineChars);
565 while (lineStr ==
"" ||
566 std::count(lineStr.begin(),lineStr.end(),
' ') == (
int)lineStr.size()){
567 file.getline(lineChars,lineCharsSize);
571 size_t dataBeginPos = lineStr.find(
"<![CDATA[");
572 if (dataBeginPos==std::string::npos){
573 file.seekg(initialPos);
578 lineStr = lineStr.substr(dataBeginPos+9);
582 std::string codeAttrVal;
587 size_t dataEndPos = lineStr.find(
"]]>");
588 if (dataEndPos!=std::string::npos) {
590 codeAttrVal+=lineStr.substr(0,dataEndPos);
593 codeAttrVal+=lineStr;
595 file.getline(lineChars,lineCharsSize);
598 attrs.emplace_back(
"code", codeAttrVal);
605 ROOT::TMetaUtils::Error(0,
"Single </ioread> at line %s",lineNumCharp);
606 out.ClearSelectionRules();
616 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
617 out.ClearSelectionRules();
630 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
631 out.ClearSelectionRules();
639 ROOT::TMetaUtils::Error(0,
"At line %s. Missing <selection> tag", lineNumCharp);
640 out.ClearSelectionRules();
649 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
650 out.ClearSelectionRules();
656 ROOT::TMetaUtils::Error(0,
"At line %s. Missing </selection> tag", lineNumCharp);
657 out.ClearSelectionRules();
667 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
668 out.ClearSelectionRules();
676 ROOT::TMetaUtils::Error(0,
"At line %s. Missing <exclusion> tag", lineNumCharp);
677 out.ClearSelectionRules();
686 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s not inside a <class> element\n", lineNumCharp,tagStrCharp);
687 out.ClearSelectionRules();
690 if (!IsStandaloneTag(tagStr)){
693 vsr.reset(
new VariableSelectionRule(fCount++, fInterp,fileName.c_str(), lineNum));
694 bsrChild = vsr.get();
700 ROOT::TMetaUtils::Error(0,
"At line %s. Closing field tag which was not opened\n", lineNumCharp);
701 out.ClearSelectionRules();
705 ROOT::TMetaUtils::Info(0,
"At line %s. A field is not supposed to have an end-tag (this message will become a warning).\n", lineNumCharp);
712 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s not inside a <class> element\n", lineNumCharp,tagStrCharp);
713 out.ClearSelectionRules();
716 if (!IsStandaloneTag(tagStr)){
719 fsr.reset(
new FunctionSelectionRule(fCount++, fInterp,fileName.c_str(), lineNum));
720 bsrChild = fsr.get();
726 ROOT::TMetaUtils::Error(0,
"At line %s. Closing method tag which was not opened\n", lineNumCharp);
727 out.ClearSelectionRules();
731 ROOT::TMetaUtils::Info(0,
"At line %s. A method is not supposed to have an end-tag (this message will become a warning).\n", lineNumCharp);
738 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s not inside a <class> element\n", lineNumCharp,tagStrCharp);
739 out.ClearSelectionRules();
742 if (!IsStandaloneTag(tagStr)) {
743 ROOT::TMetaUtils::Error(0,
"At line %s. Tag should be standalone\n", lineNumCharp);
744 out.ClearSelectionRules();
754 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
755 out.ClearSelectionRules();
758 fsr.reset(
new FunctionSelectionRule(fCount++, fInterp,fileName.c_str(), lineNum));
766 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
767 out.ClearSelectionRules();
770 vsr.reset(
new VariableSelectionRule(fCount++, fInterp,fileName.c_str(), lineNum));
778 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
779 out.ClearSelectionRules();
782 csr.reset(
new ClassSelectionRule(fCount++, fInterp));
783 attrs.emplace_back(
"fromTypedef",
"true");
791 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
792 out.ClearSelectionRules();
795 esr.reset(
new EnumSelectionRule(fCount++, fInterp,fileName.c_str(), lineNum));
805 ROOT::TMetaUtils::Error(0,
"At line %s. Tag %s inside a <class> element\n", lineNumCharp,tagStrCharp);
806 out.ClearSelectionRules();
811 default: ROOT::TMetaUtils::Error(0,
"Unknown tag name: %s \n",tagStrCharp);
816 if (tagKind == kBeginIoread || tagKind == kBeginIoreadRaw){
819 ROOT::TMetaUtils::Error(0,
"At line %s. ioread element has no attributes.\n",lineNumCharp);
824 std::string iAttrName;
825 std::string iAttrValue;
831 std::map<std::string,std::string> pragmaArgs;
832 for (
int i = 0, n = attrs.size(); i < n; ++i) {
833 pragmaArgs[attrs[i].fName]=attrs[i].fValue;
836 std::stringstream pragmaLineStream;
837 const std::string attrs[11] ={
"sourceClass",
849 for (
unsigned int i=0;i<11;++i) {
850 const std::string& attr = attrs[i];
851 if ( pragmaArgs.count(attr) == 1){
852 value = pragmaArgs[attr];
853 if (attr ==
"code") value=
"{"+value+
"}";
854 pragmaLineStream <<
" " << attr <<
"=\""<< value <<
"\"";
860 ROOT::TMetaUtils::Info(0,
"Pragma generated for ioread rule: %s\n", pragmaLineStream.str().c_str());
861 std::string error_string;
862 if (tagKind == kBeginIoread)
863 ROOT::ProcessReadPragma( pragmaLineStream.str().c_str(), error_string );
865 ROOT::ProcessReadRawPragma( pragmaLineStream.str().c_str(), error_string );
866 if (!error_string.empty())
867 ROOT::TMetaUtils::Error(0,
"%s", error_string.c_str());
874 if (!tagStr.empty() && tagKind != kVersion) {
876 if (!exclusion && !IsClosingTag(tagStr)) {
878 if (tagKind == kLcgdict || tagKind == kSelection)
882 if (tagKind == kField || tagKind == kMethod) bsrChild->SetSelected(BaseSelectionRule::kYes);
883 else bsr->SetSelected(BaseSelectionRule::kYes);
887 if (IsStandaloneTag(tagStr)){
889 if (tagKind == kField || tagKind == kMethod) bsrChild->SetSelected(BaseSelectionRule::kNo);
890 else bsr->SetSelected(BaseSelectionRule::kNo);
892 else if (tagKind == kClass) {
897 bsr->SetSelected(BaseSelectionRule::kDontCare);
922 std::string iAttrName;
923 std::string iAttrValue;
924 for (
int i = 0, n = attrs.size(); i < n; ++i) {
925 iAttrName=attrs[i].fName;
926 iAttrValue=attrs[i].fValue;
929 if (tagKind == kClass && csr &&
"noStreamer" == iAttrName){
930 if (iAttrValue ==
"true") {
931 csr->SetRequestNoStreamer(
true);
932 }
else if (iAttrValue !=
"false") {
933 ROOT::TMetaUtils::Error(0,
934 "XML at line %s: class attribute 'noStreamer' must be 'true' or 'false' (it was %s)\n",
935 lineNumCharp, iAttrValue.c_str());
940 if (tagKind == kClass && csr &&
"noInputOperator" == iAttrName){
941 if (iAttrValue ==
"true") {
942 csr->SetRequestNoInputOperator(
true);
943 }
else if (iAttrValue !=
"false") {
944 ROOT::TMetaUtils::Error(0,
945 "XML at line %s: class attribute 'noInputOperator' must be 'true' or 'false' (it was %s)\n",
946 lineNumCharp, iAttrValue.c_str());
951 if (tagKind == kClass &&
953 "ClassVersion" == iAttrName){
954 csr->SetRequestedVersionNumber(atoi(iAttrValue.c_str()));
958 if (tagKind == kClass ||
959 tagKind == kTypedef ||
960 tagKind == kProperties ||
962 tagKind == kFunction ||
963 tagKind == kVariable) {
964 if (bsr->HasAttributeWithName(iAttrName)) {
965 std::string preExistingValue;
966 bsr->GetAttributeValue(iAttrName,preExistingValue);
967 if (preExistingValue!=iAttrValue){
968 ROOT::TMetaUtils::Error(0,
969 "Line %s: assigning new value %s to attribue %s (it was %s)\n",
970 lineNumCharp,iAttrValue.c_str(),iAttrName.c_str(),preExistingValue.c_str());
971 out.ClearSelectionRules();
975 bsr->SetAttributeValue(iAttrName, iAttrValue);
976 if ((iAttrName ==
"file_name" || iAttrName ==
"file_pattern") && tagKind == kClass){
977 bsr->SetAttributeValue(
"pattern",
"*");
978 out.SetHasFileNameRule(
true);
982 if (bsrChild->HasAttributeWithName(iAttrName)) {
983 std::string preExistingValue;
984 bsrChild->GetAttributeValue(iAttrName,preExistingValue);
985 if (preExistingValue!=iAttrValue){
986 ROOT::TMetaUtils::Error(0,
987 "Line %s: assigning new value %s to attribue %s (it was %s)\n",
988 lineNumCharp,iAttrValue.c_str(),iAttrName.c_str(),preExistingValue.c_str());
989 out.ClearSelectionRules();
993 bsrChild->SetAttributeValue(iAttrName, iAttrValue);
1004 if (!inClass) out.AddClassSelectionRule(*csr);
1007 out.AddClassSelectionRule(*csr);
1010 out.AddFunctionSelectionRule(*fsr);
1013 out.AddVariableSelectionRule(*vsr);
1016 out.AddEnumSelectionRule(*esr);
1019 csr->AddFieldSelectionRule(*vsr);
1022 csr->AddMethodSelectionRule(*fsr);
1031 if (sel && !selEnd) {
1032 ROOT::TMetaUtils::Error(0,
"Error - missing </selection> tag\n");
1033 out.ClearSelectionRules();
1036 if (excl && !exclEnd ) {
1038 ROOT::TMetaUtils::Error(0,
"Error - missing </selection> tag\n");
1039 out.ClearSelectionRules();