68 #include "RConfigure.h"
85 static struct BoolNameTable_t {
114 TEnvParser(TEnv *e, FILE *f) : fIfp(f), fEnv(e) { }
115 virtual ~TEnvParser() { }
116 virtual void KeyValue(
const TString&,
const TString&,
const TString&) { }
117 virtual void Char(Int_t) { }
125 void TEnvParser::Parse()
132 while ((c = fgetc(fIfp)) != EOF) {
137 if (name.Length() > 0) {
138 KeyValue(name, value, type);
180 if (c !=
' ' && c !=
'\t')
193 state = (c ==
':') ? 3 : 4;
197 state = (c ==
')') ? 6 : 5;
216 if (name.Length() > 0) {
217 KeyValue(name, value, type);
227 class TReadEnvParser :
public TEnvParser {
233 TReadEnvParser(TEnv *e, FILE *f, EEnvLevel l) : TEnvParser(e, f), fLevel(l) { }
234 void KeyValue(
const TString &name,
const TString &value,
const TString &type)
235 { fEnv->SetValue(name, value, fLevel, type); }
241 class TWriteEnvParser :
public TEnvParser {
247 TWriteEnvParser(TEnv *e, FILE *f, FILE *of) : TEnvParser(e, f), fOfp(of) { }
248 void KeyValue(
const TString &name,
const TString &value,
const TString &type);
249 void Char(Int_t c) { fputc(c, fOfp); }
255 void TWriteEnvParser::KeyValue(
const TString &name,
const TString &value,
258 TEnvRec *er = fEnv->Lookup(name);
259 if (er && er->fModified) {
260 er->fModified = kFALSE;
261 fprintf(fOfp,
"%s", er->fValue.Data());
263 fprintf(fOfp,
"%s", value.Data());
273 TEnvRec::TEnvRec(
const char *n,
const char *v,
const char *t, EEnvLevel l)
274 : fName(n), fType(t), fLevel(l)
276 fValue = ExpandValue(v);
277 fModified = (l == kEnvChange);
286 ROOT::CallRecursiveRemoveIfNeeded(*
this);
292 void TEnvRec::ChangeValue(
const char *v,
const char *, EEnvLevel l,
293 Bool_t append, Bool_t ignoredup)
295 if (l != kEnvChange && fLevel == l && !append) {
298 if (fValue != v && !ignoredup)
299 ::Warning(
"TEnvRec::ChangeValue",
300 "duplicate entry <%s=%s> for level %d; ignored", fName.Data(), v, l);
310 fValue = ExpandValue(v);
317 fValue += ExpandValue(v);
324 Int_t TEnvRec::Compare(
const TObject *op)
const
326 return fName.CompareTo(((TEnvRec*)op)->fName);
333 TString TEnvRec::ExpandValue(
const char *value)
336 char *v, *vorg = StrDup(value);
341 while ((s1 = (
char*)strstr(v,
"$("))) {
343 s2 = (
char*)strchr(s1,
')');
349 vv = gSystem->Getenv(s1);
350 if (vv) len += strlen(vv);
357 return TString(value);
361 int nch = strlen(v) + len;
362 char *nv =
new char[nch];
365 while ((s1 = (
char*)strstr(v,
"$("))) {
370 s2 = (
char*)strchr(s1,
')');
372 vv = gSystem->Getenv(s1);
373 if (vv) strlcat(nv, vv,nch);
378 if (*v) strlcat(nv, v,nch);
401 TEnv::TEnv(
const char *name)
405 if (!name || !name[0] || !gSystem)
408 fTable =
new THashList(1000);
411 TString sname =
"system";
413 char *s = gSystem->ConcatFileName(TROOT::GetEtcDir(), sname);
414 ReadFile(s, kEnvGlobal);
416 if (!gSystem->Getenv(
"ROOTENV_NO_HOME")) {
417 s = gSystem->ConcatFileName(gSystem->HomeDirectory(), name);
418 ReadFile(s, kEnvUser);
420 if (strcmp(gSystem->HomeDirectory(), gSystem->WorkingDirectory()))
421 ReadFile(name, kEnvLocal);
423 ReadFile(name, kEnvLocal);
441 const char *TEnv::Getvalue(
const char *name)
const
443 Bool_t haveProgName = kFALSE;
444 if (gProgName && strlen(gProgName) > 0)
445 haveProgName = kTRUE;
449 if (haveProgName && gSystem && gProgName) {
450 aname = gSystem->GetName(); aname +=
"."; aname += gProgName;
451 aname +=
"."; aname += name;
454 if (er == 0 && gSystem && gROOT) {
455 aname = gSystem->GetName(); aname +=
"."; aname += gROOT->GetName();
456 aname +=
"."; aname += name;
459 if (er == 0 && gSystem) {
460 aname = gSystem->GetName(); aname +=
".*."; aname += name;
463 if (er == 0 && haveProgName && gProgName) {
464 aname = gProgName; aname +=
"."; aname += name;
467 if (er == 0 && gROOT) {
468 aname = gROOT->GetName(); aname +=
"."; aname += name;
472 aname =
"*.*."; aname += name;
476 aname =
"*."; aname += name;
491 Int_t TEnv::GetValue(
const char *name, Int_t dflt)
const
493 const char *cp = TEnv::Getvalue(name);
495 char buf2[512], *cp2 = buf2;
497 while (isspace((
int)*cp))
501 if (isdigit((
int)*cp) || *cp ==
'-' || *cp ==
'+')
503 while (isalpha((
int)*cp))
504 *cp2++ = toupper((
int)*cp++);
506 for (bt = gBoolNames; bt->fName; bt++)
507 if (strcmp(buf2, bt->fName) == 0)
518 Double_t TEnv::GetValue(
const char *name, Double_t dflt)
const
520 const char *cp = TEnv::Getvalue(name);
523 Double_t val = strtod(cp, &endptr);
524 if (val == 0.0 && cp == endptr)
535 const char *TEnv::GetValue(
const char *name,
const char *dflt)
const
537 const char *cp = TEnv::Getvalue(name);
547 TEnvRec *TEnv::Lookup(
const char *name)
const
549 if (!fTable)
return 0;
550 return (TEnvRec*) fTable->FindObject(name);
556 void TEnv::Print(Option_t *opt)
const
558 if (!opt || !opt[0]) {
563 if (!strcmp(opt,
"global"))
564 PrintEnv(kEnvGlobal);
565 if (!strcmp(opt,
"user"))
567 if (!strcmp(opt,
"local"))
574 void TEnv::PrintEnv(EEnvLevel level)
const
580 static const char *lc[] = {
"Global",
"User",
"Local",
"Changed",
"All" };
582 while ((er = (TEnvRec*) next()))
583 if (er->fLevel == level || level == kEnvAll)
584 Printf(
"%-25s %-30s [%s]", Form(
"%s:", er->fName.Data()),
585 er->fValue.Data(), lc[er->fLevel]);
592 Int_t TEnv::ReadFile(
const char *fname, EEnvLevel level)
594 if (!fname || !fname[0]) {
595 Error(
"ReadFile",
"no file name specified");
600 if ((ifp = fopen(fname,
"r"))) {
601 TReadEnvParser rp(
this, ifp, level);
617 Int_t TEnv::WriteFile(
const char *fname, EEnvLevel level)
619 if (!fname || !fname[0]) {
620 Error(
"WriteFile",
"no file name specified");
625 Error(
"WriteFile",
"TEnv table is empty");
630 if ((ofp = fopen(fname,
"w"))) {
633 while ((er = (TEnvRec*) next()))
634 if (er->fLevel == level || level == kEnvAll)
635 fprintf(ofp,
"%-40s %s\n", Form(
"%s:", er->fName.Data()),
641 Error(
"WriteFile",
"cannot open %s for writing", fname);
652 Error(
"Save",
"no resource file name specified");
656 SaveLevel(kEnvLocal);
658 SaveLevel(kEnvGlobal);
664 void TEnv::SaveLevel(EEnvLevel level)
667 Error(
"SaveLevel",
"no resource file name specified");
672 Error(
"SaveLevel",
"TEnv table is empty");
679 if (level == kEnvGlobal) {
681 TString sname =
"system";
683 char *s = gSystem->ConcatFileName(TROOT::GetEtcDir(), sname);
686 }
else if (level == kEnvUser) {
687 char *s = gSystem->ConcatFileName(gSystem->HomeDirectory(), fRcName);
690 }
else if (level == kEnvLocal)
695 if ((ofp = fopen(Form(
"%s.new", rootrcdir.Data()),
"w"))) {
696 ifp = fopen(rootrcdir.Data(),
"r");
698 ifp = fopen(rootrcdir.Data(),
"w");
704 if (ifp || (ifp = fopen(rootrcdir.Data(),
"r"))) {
705 TWriteEnvParser wp(
this, ifp, ofp);
710 while ((er = (TEnvRec*) next())) {
714 if (er->fLevel == kEnvChange) er->fLevel = level;
715 if (er->fLevel == level) {
716 er->fModified = kFALSE;
717 fprintf(ofp,
"%-40s %s\n", Form(
"%s:", er->fName.Data()),
724 gSystem->Rename(rootrcdir.Data(), Form(
"%s.bak", rootrcdir.Data()));
725 gSystem->Rename(Form(
"%s.new", rootrcdir.Data()), rootrcdir.Data());
730 Error(
"SaveLevel",
"cannot write to file %s", rootrcdir.Data());
736 void TEnv::SetValue(
const char *name,
const char *value, EEnvLevel level,
740 fTable =
new THashList(1000);
742 const char *nam = name;
743 Bool_t append = kFALSE;
744 if (name[0] ==
'+') {
749 TEnvRec *er = Lookup(nam);
751 er->ChangeValue(value, type, level, append, fIgnoreDup);
753 fTable->Add(
new TEnvRec(nam, value, type, level));
761 void TEnv::SetValue(
const char *name, EEnvLevel level)
764 int l = buf.Index(
"=");
766 TString nm = buf(0, l);
767 TString val = buf(l+1, buf.Length());
768 SetValue(nm, val, level);
770 SetValue(name,
"1", level);
776 void TEnv::SetValue(
const char *name, Int_t value)
778 SetValue(name, Form(
"%d", value));
784 void TEnv::SetValue(
const char *name,
double value)
786 SetValue(name, Form(
"%g", value));
793 Bool_t TEnv::IgnoreDuplicates(Bool_t ignore)
795 Bool_t ret = fIgnoreDup;