32 void TMakeProject::AddUniqueStatement(FILE *fp,
const char *statement,
char *inclist)
34 if (!strstr(inclist, statement)) {
35 if (strlen(inclist)+strlen(statement) >= 50000) {
36 Fatal(
"AddUniqueStatement",
"inclist too short need %u instead of 500000",UInt_t(strlen(inclist)+strlen(statement)));
38 strcat(inclist, statement);
39 fprintf(fp,
"%s", statement);
46 void TMakeProject::AddInclude(FILE *fp,
const char *header, Bool_t system,
char *inclist)
50 what.Form(
"#include <%s>\n", header);
52 what.Form(
"#include \"%s\"\n", header);
54 AddUniqueStatement(fp, what.Data(), inclist);
61 void TMakeProject::ChopFileName(TString &name, Int_t limit)
63 Ssiz_t len = name.Length();
64 Bool_t has_extension = name.EndsWith(
".h");
69 name.Remove(name.Length()-2);
72 md.Update((
const UChar_t*)name.Data(),name.Length());
74 name.Remove( limit - 32 - 5);
75 name.Append( md.AsString() );
86 TString TMakeProject::GetHeaderName(
const char *in_name,
const TList *extrainfos, Bool_t includeNested)
89 std::string strname( TClassEdit::GetLong64_Name( in_name ) );
90 const char *name = strname.c_str();
91 Int_t len = strlen(name);
93 for (Int_t i = 0; i < len; ++i) {
104 if (nest == 0 && name[i+1] ==
':') {
105 TString nsname(name, i);
106 TClass *cl = gROOT->GetClass(nsname);
107 Bool_t definedInParent = !includeNested && cl && (cl->Size() != 0 || (cl->Size()==0 && !cl->HasInterpreterInfo() ));
108 if (!definedInParent && cl==0 && extrainfos!=0) {
109 TStreamerInfo *clinfo = (TStreamerInfo*)extrainfos->FindObject(nsname);
110 if (clinfo && clinfo->GetClassVersion() == -5) {
111 definedInParent = kTRUE;
114 if (definedInParent) {
119 if (strcmp(name + strlen(name) - 2,
".h") == 0) {
122 ChopFileName(result,127);
130 if (name[i+1] ==
'/') {
133 result.Append(name[i]);
151 result.Append(name[i]);
154 ChopFileName(result,127);
162 UInt_t TMakeProject::GenerateClassPrefix(FILE *fp,
const char *clname, Bool_t top, TString &protoname,
163 UInt_t *numberOfClasses, Int_t implementEmptyClass, Bool_t needGenericTemplate)
166 Int_t numberOfNamespaces = 0;
167 const char *fullname = clname;
169 Bool_t istemplate = kFALSE;
170 if (strchr(clname,
':')) {
172 Int_t len = strlen(clname);
173 const char *name = clname;
175 for (Int_t cur = 0; cur < len; ++cur) {
176 switch (clname[cur]) {
185 if (nest == 0 && clname[cur+1] ==
':') {
187 TString nsname(clname, cur);
188 TClass *cl = gROOT->GetClass(nsname);
190 if (cl == 0 || (cl && cl->Size() == 0)) {
191 TString last(name, cur - (name - clname));
192 if ((numberOfClasses == 0 || *numberOfClasses == 0) && strchr(last.Data(),
'<') == 0) {
193 fprintf(fp,
"namespace %s {\n", last.Data());
194 ++numberOfNamespaces;
196 TString headername(GetHeaderName(last,0));
197 fprintf(fp,
"#ifndef %s_h\n", headername.Data());
198 fprintf(fp,
"#define %s_h\n", headername.Data());
199 GenerateClassPrefix(fp, last.Data(), top, protoname, 0);
201 fprintf(fp,
"public:\n");
202 if (numberOfClasses) ++(*numberOfClasses);
205 name = clname + cur + 2;
209 name = clname + cur + 2;
218 istemplate = strstr(clname,
"<") != 0;
223 if (implementEmptyClass==1) {
224 TString headername(GetHeaderName(fullname,0));
225 fprintf(fp,
"#ifndef %s_h\n", headername.Data());
226 fprintf(fp,
"#define %s_h\n", headername.Data());
229 std::vector<const char*> argtype;
231 Ssiz_t pos = protoname.First(
'<');
234 if (isdigit(protoname[pos+1])) {
235 argtype.push_back(
"int");
237 argtype.push_back(
"typename");
240 for (Ssiz_t i = pos; i < protoname.Length(); ++i) {
241 switch (protoname[i]) {
250 if (isdigit(protoname[i+1])) {
251 argtype.push_back(
"int");
253 argtype.push_back(
"typename");
260 protoname.Remove(pos);
264 fprintf(fp,
"template <");
265 for (UInt_t p = 0; p < nparam; ++p) {
266 if (p >= argtype.size() ) {
267 fprintf(fp,
"/* missing */ T%d", p);
269 fprintf(fp,
"%s T%d", argtype[p], p);
271 if (p != (nparam - 1)) fprintf(fp,
", ");
273 if (needGenericTemplate) {
274 fprintf(fp,
"> class %s", protoname.Data());
276 fprintf(fp,
"> class %s;\n", protoname.Data());
277 fprintf(fp,
"template <> ");
281 if (implementEmptyClass) {
283 if (!needGenericTemplate) {
284 fprintf(fp,
"class %s", clname);
287 if (numberOfClasses) ++(*numberOfClasses);
288 fprintf(fp,
"public:\n");
289 fprintf(fp,
"operator int() { return 0; };\n");
291 fprintf(fp,
"enum %s { kDefault_%s };\n", clname, clname);
294 if (implementEmptyClass==1) {
295 if (strchr(fullname,
':') == 0) {
297 fprintf(fp,
"#ifdef __MAKECINT__\n#pragma link C++ class %s+;\n#endif\n", fullname);
299 fprintf(fp,
"#endif\n");
303 if (!(istemplate && needGenericTemplate)) {
304 fprintf(fp,
"class %s", clname);
307 return numberOfNamespaces;
317 void TMakeProject::GenerateMissingStreamerInfo(TList *extrainfos,
const char *clname, Bool_t iscope)
319 if (!TClassEdit::IsStdClass(clname) && !TClass::GetClass(clname) && gROOT->GetType(clname) == 0) {
321 TStreamerInfo *info = (TStreamerInfo*)extrainfos->FindObject(clname);
324 TStreamerInfo *newinfo =
new TStreamerInfo();
325 newinfo->SetName(clname);
326 if (clname[strlen(clname)-1]==
'>') {
327 newinfo->SetTitle(
"Generated by MakeProject as an empty class template instantiation");
328 newinfo->SetClassVersion(1);
330 newinfo->SetTitle(
"Generated by MakeProject as a namespace");
331 newinfo->SetClassVersion(-4 );
333 newinfo->SetTitle(
"Generated by MakeProject as an enum");
334 newinfo->SetClassVersion(-3 );
336 extrainfos->Add(newinfo);
339 if (info->GetClassVersion() == -3) {
342 info->SetTitle(
"Generated by MakeProject as an empty class");
343 info->SetClassVersion(-5 );
346 if (info->GetClassVersion() == -4) {
349 info->SetTitle(
"Generated by MakeProject as an empty class");
350 info->SetClassVersion(-5 );
364 void TMakeProject::GenerateMissingStreamerInfos(TList *extrainfos,
const char *clname)
366 UInt_t len = strlen(clname);
371 for (UInt_t i = 0; i < len; ++i) {
374 if (nest == 0 && clname[i+1] ==
':') {
375 TString incName(clname, i);
376 GenerateMissingStreamerInfo(extrainfos, incName.Data(), kTRUE);
382 if (nest == 1) last = i + 1;
385 if (nest == 0)
return;
388 if ((clname[i] ==
',' && nest == 1) || (clname[i] ==
'>' && nest == 0)) {
389 TString incName(clname + last, i - last);
390 incName = TClassEdit::ShortType(incName.Data(), TClassEdit::kDropTrailStar | TClassEdit::kLong64);
391 if (clname[i] ==
'>' && nest == 1) incName.Append(
">");
393 if (isdigit(incName[0])) {
396 GenerateMissingStreamerInfos(extrainfos,incName.Data());
402 GenerateMissingStreamerInfo(extrainfos,TClassEdit::ShortType(clname, TClassEdit::kDropTrailStar | TClassEdit::kLong64).c_str(),kFALSE);
412 void TMakeProject::GenerateMissingStreamerInfos(TList *extrainfos, TStreamerElement *element)
414 if (element->IsBase()) {
415 TClass *elemCl = element->GetClassPointer();
416 if (elemCl) GenerateMissingStreamerInfos(extrainfos,elemCl->GetName());
417 else GenerateMissingStreamerInfos(extrainfos,element->GetTypeName());
419 GenerateMissingStreamerInfos(extrainfos,element->GetTypeName());
427 UInt_t TMakeProject::GenerateForwardDeclaration(FILE *fp,
const char *clname,
char *inclist, Bool_t implementEmptyClass, Bool_t needGenericTemplate,
const TList *extrainfos)
431 if (strchr(clname,
'<')) {
432 ninc += GenerateIncludeForTemplate(fp, clname, inclist, kTRUE, extrainfos);
435 UInt_t numberOfClasses = 0;
436 UInt_t numberOfNamespaces = GenerateClassPrefix(fp, clname, kTRUE, protoname, &numberOfClasses, implementEmptyClass, needGenericTemplate);
438 if (!implementEmptyClass) fprintf(fp,
";\n");
439 for (UInt_t i = 0;i < numberOfClasses;++i) {
440 fprintf(fp,
"}; // end of class.\n");
441 fprintf(fp,
"#endif\n");
443 for (UInt_t i = 0;i < numberOfNamespaces;++i) {
444 fprintf(fp,
"} // end of namespace.\n");
454 UInt_t TMakeProject::GenerateIncludeForTemplate(FILE *fp,
const char *clname,
char *inclist, Bool_t forward,
const TList *extrainfos)
457 UInt_t len = strlen(clname);
462 for (UInt_t i = 0; i < len; ++i) {
466 if (nest == 1) last = i + 1;
469 if (nest==0)
return ninc;
472 if ((clname[i] ==
',' && nest == 1) || (clname[i] ==
'>' && nest == 0)) {
473 TString incName(clname + last, i - last);
474 incName = TClassEdit::ShortType(incName.Data(), TClassEdit::kDropTrailStar | TClassEdit::kLong64);
475 if (clname[i] ==
'>' && nest == 1) incName.Append(
">");
477 if (isdigit(incName[0])) {
479 }
else if ((stlType = TClassEdit::IsSTLCont(incName))) {
480 const char *what =
"";
481 switch (TMath::Abs(stlType)) {
482 case ROOT::kSTLvector:
488 case ROOT::kSTLforwardlist:
489 what =
"forward_list";
491 case ROOT::kSTLdeque:
495 case ROOT::kSTLmultimap:
498 case ROOT::kSTLunorderedmap:
499 case ROOT::kSTLunorderedmultimap:
500 what =
"unordered_map";
503 case ROOT::kSTLmultiset:
506 case ROOT::kSTLunorderedset:
507 case ROOT::kSTLunorderedmultiset:
508 what =
"unordered_set";
510 case ROOT::kSTLbitset:
514 what =
"undetermined_stl_container";
517 AddInclude(fp, what, kTRUE, inclist);
518 fprintf(fp,
"namespace std {} using namespace std;\n");
519 ninc += GenerateIncludeForTemplate(fp, incName, inclist, forward, extrainfos);
520 }
else if (strncmp(incName.Data(),
"pair<", strlen(
"pair<")) == 0) {
521 AddInclude(fp,
"utility", kTRUE, inclist);
522 ninc += GenerateIncludeForTemplate(fp, incName, inclist, forward, extrainfos);
523 }
else if (strncmp(incName.Data(),
"auto_ptr<", strlen(
"auto_ptr<")) == 0) {
524 AddInclude(fp,
"memory", kTRUE, inclist);
525 ninc += GenerateIncludeForTemplate(fp, incName, inclist, forward, extrainfos);
526 }
else if (TClassEdit::IsStdClass(incName)) {
529 TClass *cl = gROOT->GetClass(incName);
530 if (!forward && cl) {
531 if (cl->HasInterpreterInfo()) {
534 const char *include = cl->GetDeclFileName();
535 if (include && include[0]) {
537 if (strncmp(include,
"include/", 8) == 0) {
540 if (strncmp(include,
"include\\", 9) == 0) {
543 TMakeProject::AddInclude(fp, include, kFALSE, inclist);
545 GenerateIncludeForTemplate(fp, incName, inclist, forward, extrainfos);
547 incName = GetHeaderName(incName,extrainfos);
548 incName.Append(
".h");
549 AddInclude(fp, incName, kFALSE, inclist);
551 }
else if (incName.Length() && incName[0] !=
' ' && gROOT->GetType(incName) == 0) {
552 Bool_t emptyclass = !cl;
553 if (emptyclass && extrainfos) {
554 TStreamerInfo *info = (TStreamerInfo*)extrainfos->FindObject(incName);
555 if (info && info->GetClassVersion() == -5) {
559 GenerateForwardDeclaration(fp, incName, inclist, emptyclass, kFALSE, extrainfos);
567 Int_t stlType = TClassEdit::IsSTLCont(clname);
569 std::vector<std::string> inside;
571 TClassEdit::GetSplit( clname, inside, nestedLoc, TClassEdit::kLong64 );
572 Int_t stlkind = TClassEdit::STLKind(inside[0]);
573 TClass *key = TClass::GetClass(inside[1].c_str());
578 case ROOT::kSTLmultimap: {
580 what += UpdateAssociativeToVector( inside[1].c_str() );
582 what += UpdateAssociativeToVector( inside[2].c_str() );
584 what.ReplaceAll(
"std::",
"");
586 TClass *paircl = TClass::GetClass(what.Data());
587 if (paircl == 0 || !paircl->HasInterpreterInfo()) {
588 AddUniqueStatement(fp, TString::Format(
"#ifdef __MAKECINT__\n#pragma link C++ class %s+;\n#endif\n", what.Data()), inclist);
604 void TMakeProject::GeneratePostDeclaration(FILE *fp,
const TVirtualStreamerInfo *info,
char *inclist)
606 TIter next(info->GetElements());
607 TStreamerElement *element;
608 while( (element = (TStreamerElement*)next()) ) {
609 Int_t stlType = TClassEdit::IsSTLCont(element->GetTypeName());
611 std::vector<std::string> inside;
613 TClassEdit::GetSplit( element->GetTypeName(), inside, nestedLoc, TClassEdit::kLong64 );
614 Int_t stlkind = TClassEdit::STLKind(inside[0]);
615 TClass *key = TClass::GetClass(inside[1].c_str());
617 if (strncmp(inside[1].c_str(),
"pair<",strlen(
"pair<"))==0) {
618 what = inside[1].c_str();
622 case ROOT::kSTLmultimap:
633 TClass *paircl = TClass::GetClass(what.Data());
634 if (paircl == 0 || !paircl->HasInterpreterInfo()) {
635 AddUniqueStatement(fp, TString::Format(
"#ifdef __MAKECINT__\n#pragma link C++ class %s+;\n#endif\n",what.Data()), inclist);
650 static constexpr
int str_length(
const char* str)
652 return *str ? 1 + str_length(str + 1) : 0;
655 TString TMakeProject::UpdateAssociativeToVector(
const char *name)
657 TString newname( name );
659 constexpr
auto auto_ptr_len = str_length(
"auto_ptr<");
660 if (strncmp(name,
"auto_ptr<", auto_ptr_len) == 0) {
661 newname =
"unique_ptr<";
662 newname += (name + auto_ptr_len);
663 }
else if (strchr(name,
'<')!=0) {
664 std::vector<std::string> inside;
666 unsigned int narg = TClassEdit::GetSplit( name, inside, nestedLoc, TClassEdit::kLong64 );
668 Int_t stlkind = TMath::Abs(TClassEdit::STLKind(inside[0]));
670 for(
unsigned int i = 1; i<narg; ++i) {
671 inside[i] = UpdateAssociativeToVector( inside[i].c_str() );
674 if (nestedLoc) narg = nestedLoc;
677 static const char* allocPrefix =
"std::allocator<";
678 static const unsigned int allocPrefixLen (strlen(allocPrefix));
680 case ROOT::kSTLvector:
682 case ROOT::kSTLforwardlist:
683 case ROOT::kSTLdeque:
684 if (narg>2 && strncmp(inside[2].c_str(),allocPrefix,allocPrefixLen)==0) {
689 case ROOT::kSTLmultiset:
691 case ROOT::kSTLmultimap:
692 if (narg>4 && strncmp(inside[4].c_str(),allocPrefix,allocPrefixLen)==0) {
696 case ROOT::kSTLunorderedset:
697 case ROOT::kSTLunorderedmultiset:
698 if (narg>5 && strncmp(inside[5].c_str(),allocPrefix,allocPrefixLen)==0) {
702 case ROOT::kSTLunorderedmap:
703 case ROOT::kSTLunorderedmultimap:
704 if (narg>6 && strncmp(inside[6].c_str(),allocPrefix,allocPrefixLen)==0) {
710 TClass *key = TClass::GetClass(inside[1].c_str());
718 case ROOT::kSTLunorderedmap:
719 case ROOT::kSTLmultimap:
720 case ROOT::kSTLunorderedmultimap: {
725 if (what[what.size()-1]==
'>') {
731 inside.push_back(
"std::vector");
732 inside.push_back(what);
737 case ROOT::kSTLunorderedset:
738 case ROOT::kSTLmultiset:
739 case ROOT::kSTLunorderedmultiset:
740 inside[0] =
"std::vector";
744 if (strncmp(inside[0].c_str(),
"std::",5) != 0) {
745 inside[0] =
"std::" + inside[0];
748 static const char *stlnames[] = {
"pair",
"greater",
"less",
"allocator" };
749 for(
unsigned int in = 0; in <
sizeof(stlnames)/
sizeof(stlnames[0]); ++in) {
750 if (strncmp( inside[0].c_str(), stlnames[in], strlen(stlnames[in])) == 0 ) {
751 inside[0] =
"std::" + inside[0];
758 newname.Append(inside[1]);
759 for(
unsigned int j=2; j<narg; ++j) {
760 if (!inside[j].empty()) {
762 newname.Append(inside[j]);
765 if (newname[newname.Length()-1]==
'>') {
766 newname.Append(
" >");
770 if (nestedLoc) newname.Append(inside[nestedLoc]);
771 }
else if ( newname ==
"string" ) {
772 newname =
"std::string";