ROOT logo
// @(#)root/base:$Id$
// Author: Fons Rademakers   22/09/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TEnv                                                                 //
//                                                                      //
// The TEnv class reads config files, by default named .rootrc. Three   //
// types of config files are read: global, user and local files. The    //
// global file is $ROOTSYS/etc/system<name> (or ROOTETCDIR/system<name>)//
// the user file is $HOME/<name> and the local file is ./<name>.        //
// By setting the shell variable ROOTENV_NO_HOME=1 the reading of       //
// the $HOME/<name> resource file will be skipped. This might be useful //
// in case the home directory resides on an automounted remote file     //
// system and one wants to avoid this file system from being mounted.   //
//                                                                      //
// The format of the .rootrc file is similar to the .Xdefaults format:  //
//                                                                      //
//   [+]<SystemName>.<RootName|ProgName>.<name>[(type)]:  <value>       //
//                                                                      //
// Where <SystemName> is either Unix, WinNT, MacOS or Vms,              //
// <RootName> the name as given in the TApplication ctor (or "RootApp"  //
// in case no explicit TApplication derived object was created),        //
// <ProgName> the current program name and <name> the resource name,    //
// with optionally a type specification. <value> can be either a        //
// string, an integer, a float/double or a boolean with the values      //
// TRUE, FALSE, ON, OFF, YES, NO, OK, NOT. Booleans will be returned as //
// an integer 0 or 1. The options [+] allows the concatenation of       //
// values to the same resouce name.                                     //
//                                                                      //
// E.g.:                                                                //
//                                                                      //
//   Unix.Rint.Root.DynamicPath: .:$(ROOTSYS)/lib:~/lib                 //
//   myapp.Root.Debug:  FALSE                                           //
//   TH.Root.Debug: YES                                                 //
//   *.Root.MemStat: 1                                                  //
//                                                                      //
// <SystemName> and <ProgName> or <RootName> may be the wildcard "*".   //
// A # in the first column starts comment line.                         //
//                                                                      //
// Note that the environment variables (like $ROOTSYS) need to be       //
// surrounded in parentheses in order to be expanded.                   //
//                                                                      //
// For the currently defined resources (and their default values) see   //
// $ROOTSYS/etc/system.rootrc.                                          //
//                                                                      //
// Note that the .rootrc config files contain the config for all ROOT   //
// based applications.                                                  //
//                                                                      //
// To add new entries to a TEnv:                                        //
// TEnv env(".myfile");                                                 //
// env.SetValue("myname","value");                                      //
// env.SaveLevel(kEnvLocal);                                            //
//                                                                      //
// All new entries will be saved in the file corresponding to the       //
// first SaveLevel() command.  If Save() is used, new entries go        //
// into the local file by default.                                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "RConfigure.h"

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include "TEnv.h"
#include "TROOT.h"
#include "TSystem.h"
#include "THashList.h"
#include "TError.h"


TEnv *gEnv;  // main environment created in TROOT


static struct BoolNameTable_t {
   const char *fName;
   Int_t       fValue;
} gBoolNames[]= {
   { "TRUE",  1 },
   { "FALSE", 0 },
   { "ON",    1 },
   { "OFF",   0 },
   { "YES",   1 },
   { "NO",    0 },
   { "OK",    1 },
   { "NOT",   0 },
   { 0, 0 }
};


//---- TEnvParser --------------------------------------------------------------

class TEnvParser {

private:
   FILE    *fIfp;

protected:
   TEnv    *fEnv;

public:
   TEnvParser(TEnv *e, FILE *f) : fIfp(f), fEnv(e) { }
   virtual ~TEnvParser() { }
   virtual void KeyValue(const TString&, const TString&, const TString&) { }
   virtual void Char(Int_t) { }
   void Parse();
};

//______________________________________________________________________________
void TEnvParser::Parse()
{
   // Parse a line of the env file and create an entry in the resource
   // dictionary (i.e. add a KeyValue pair).

   TString name(1024);
   TString type(1024);
   TString value(1024);
   int c, state = 0;

   while ((c = fgetc(fIfp)) != EOF) {
      if (c == 13)        // ignore CR
         continue;
      if (c == '\n') {
         state = 0;
         if (name.Length() > 0) {
            KeyValue(name, value, type);
            name.Clear();
            value.Clear();
            type.Clear();
         }
         Char(c);
         continue;
      }
      switch (state) {
      case 0:             // start of line
         switch (c) {
         case ' ':
         case '\t':
            break;
         case '#':
            state = 1;
            break;
         default:
            state = 2;
            break;
         }
         break;

      case 1:             // comment
         break;

      case 2:             // name
         switch (c) {
         case ' ':
         case '\t':
         case ':':
            state = 3;
            break;
         case '(':
            state = 7;
            break;
         default:
            break;
         }
         break;

      case 3:             // ws before value
         if (c != ' ' && c != '\t')
            state = 4;
         break;

      case 4:             // value
         break;

      case 5:             // type
         if (c == ')')
            state = 6;
         break;

      case 6:             // optional ':'
         state = (c == ':') ? 3 : 4;
         break;

      case 7:
         state = (c == ')') ? 6 : 5;
         break;

      }
      switch (state) {
      case 2:
         name.Append(c);
         break;
      case 4:
         value.Append(c);
         break;
      case 5:
         type.Append(c);
         break;
      }
      if (state != 4)
         Char(c);
   }
   // In case EOF is reach before '\n'
   if (name.Length() > 0) {
      KeyValue(name, value, type);
      name.Clear();
      value.Clear();
      type.Clear();
   }
}

//---- TReadEnvParser ----------------------------------------------------------

class TReadEnvParser : public TEnvParser {

private:
   EEnvLevel fLevel;

public:
   TReadEnvParser(TEnv *e, FILE *f, EEnvLevel l) : TEnvParser(e, f), fLevel(l) { }
   void KeyValue(const TString &name, const TString &value, const TString &type)
      { fEnv->SetValue(name, value, fLevel, type); }
};

//---- TWriteEnvParser ---------------------------------------------------------

class TWriteEnvParser : public TEnvParser {

private:
   FILE *fOfp;

public:
   TWriteEnvParser(TEnv *e, FILE *f, FILE *of) : TEnvParser(e, f), fOfp(of) { }
   void KeyValue(const TString &name, const TString &value, const TString &type);
   void Char(Int_t c) { fputc(c, fOfp); }
};

//______________________________________________________________________________
void TWriteEnvParser::KeyValue(const TString &name, const TString &value,
                               const TString &)
{
   // Write resources out to a new file.

   TEnvRec *er = fEnv->Lookup(name);
   if (er && er->fModified) {
      er->fModified = kFALSE;
      fprintf(fOfp, "%s", er->fValue.Data());
   } else
      fprintf(fOfp, "%s", value.Data());
}


//---- TEnvRec -----------------------------------------------------------------

//______________________________________________________________________________
TEnvRec::TEnvRec(const char *n, const char *v, const char *t, EEnvLevel l)
   : fName(n), fType(t), fLevel(l)
{
   // Ctor of a single resource.

   fValue = ExpandValue(v);
   fModified = (l == kEnvChange);
}

//______________________________________________________________________________
void TEnvRec::ChangeValue(const char *v, const char *, EEnvLevel l,
                          Bool_t append, Bool_t ignoredup)
{
   // Change the value of a resource.

   if (l != kEnvChange && fLevel == l && !append) {
      // use global Warning() since interpreter might not yet be initialized
      // at this stage (called from TROOT ctor)
      if (fValue != v && !ignoredup)
         ::Warning("TEnvRec::ChangeValue",
           "duplicate entry <%s=%s> for level %d; ignored", fName.Data(), v, l);
      return;
   }
   if (!append) {
      if (fValue != v) {
         if (l == kEnvChange)
            fModified = kTRUE;
         else
            fModified = kFALSE;
         fLevel = l;
         fValue = ExpandValue(v);
      }
   } else {
      if (l == kEnvChange)
         fModified = kTRUE;
      fLevel = l;
      fValue += " ";
      fValue += ExpandValue(v);
   }
}

//______________________________________________________________________________
Int_t TEnvRec::Compare(const TObject *op) const
{
   // Comparison function for resources.

   return fName.CompareTo(((TEnvRec*)op)->fName);
}

//______________________________________________________________________________
TString TEnvRec::ExpandValue(const char *value)
{
   // Replace all $(XXX) strings by the value defined in the shell
   // (obtained via TSystem::Getenv()).

   const char *vv;
   char *v, *vorg = StrDup(value);
   v = vorg;

   char *s1, *s2;
   int len = 0;
   while ((s1 = (char*)strstr(v, "$("))) {
      s1 += 2;
      s2 = (char*)strchr(s1, ')');
      if (!s2) {
         len = 0;
         break;
      }
      *s2 = 0;
      vv = gSystem->Getenv(s1);
      if (vv) len += strlen(vv);
      *s2 = ')';
      v = s2 + 1;
   }

   if (!len) {
      delete [] vorg;
      return TString(value);
   }

   v = vorg;
   int nch = strlen(v) + len;
   char *nv = new char[nch];
   *nv = 0;

   while ((s1 = (char*)strstr(v, "$("))) {
      *s1 = 0;
      strlcat(nv, v,nch);
      *s1 = '$';
      s1 += 2;
      s2 = (char*)strchr(s1, ')');
      *s2 = 0;
      vv = gSystem->Getenv(s1);
      if (vv) strlcat(nv, vv,nch);
      *s2 = ')';
      v = s2 + 1;
   }

   if (*v) strlcat(nv, v,nch);

   TString val = nv;
   delete [] nv;
   delete [] vorg;

   return val;
}


//---- TEnv --------------------------------------------------------------------

ClassImp(TEnv)

//______________________________________________________________________________
TEnv::TEnv(const char *name)
{
   // Create a resource table and read the (possibly) three resource files, i.e
   // $ROOTSYS/etc/system<name> (or ROOTETCDIR/system<name>), $HOME/<name> and
   // ./<name>. ROOT always reads ".rootrc" (in TROOT::InitSystem()). You can
   // read additional user defined resource files by creating addtional TEnv
   // objects. By setting the shell variable ROOTENV_NO_HOME=1 the reading of
   // the $HOME/<name> resource file will be skipped. This might be useful in
   // case the home directory resides on an automounted remote file system
   // and one wants to avoid the file system from being mounted.

   fIgnoreDup = kFALSE;

   if (!name || !strlen(name) || !gSystem)
      fTable = 0;
   else {
      fTable  = new THashList(1000);
      fRcName = name;

      TString sname = "system";
      sname += name;
#ifdef ROOTETCDIR
      char *s = gSystem->ConcatFileName(ROOTETCDIR, sname);
#else
      TString etc = gRootDir;
#ifdef WIN32
      etc += "\\etc";
#else
      etc += "/etc";
#endif
#if defined(R__MACOSX) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
      // on iOS etc does not exist and system<name> resides in $ROOTSYS
      etc = gRootDir;
#endif
      char *s = gSystem->ConcatFileName(etc, sname);
#endif
      ReadFile(s, kEnvGlobal);
      delete [] s;
      if (!gSystem->Getenv("ROOTENV_NO_HOME")) {
         s = gSystem->ConcatFileName(gSystem->HomeDirectory(), name);
         ReadFile(s, kEnvUser);
         delete [] s;
         if (strcmp(gSystem->HomeDirectory(), gSystem->WorkingDirectory()))
            ReadFile(name, kEnvLocal);
      } else
         ReadFile(name, kEnvLocal);
   }
}

//______________________________________________________________________________
TEnv::~TEnv()
{
   // Delete the resource table.

   if (fTable) {
      fTable->Delete();
      SafeDelete(fTable);
   }
}

//______________________________________________________________________________
const char *TEnv::Getvalue(const char *name)
{
   // Returns the character value for a named resouce.

   Bool_t haveProgName = kFALSE;
   if (gProgName && strlen(gProgName) > 0)
      haveProgName = kTRUE;

   TString aname;
   TEnvRec *er = 0;
   if (haveProgName && gSystem && gProgName) {
      aname = gSystem->GetName(); aname += "."; aname += gProgName;
      aname += "."; aname += name;
      er = Lookup(aname);
   }
   if (er == 0 && gSystem && gROOT) {
      aname = gSystem->GetName(); aname += "."; aname += gROOT->GetName();
      aname += "."; aname += name;
      er = Lookup(aname);
   }
   if (er == 0 && gSystem) {
      aname = gSystem->GetName(); aname += ".*."; aname += name;
      er = Lookup(aname);
   }
   if (er == 0 && haveProgName && gProgName) {
      aname = gProgName; aname += "."; aname += name;
      er = Lookup(aname);
   }
   if (er == 0 && gROOT) {
      aname = gROOT->GetName(); aname += "."; aname += name;
      er = Lookup(aname);
   }
   if (er == 0) {
      aname = "*.*."; aname += name;
      er = Lookup(aname);
   }
   if (er == 0) {
      aname = "*."; aname += name;
      er = Lookup(aname);
   }
   if (er == 0) {
      er = Lookup(name);
   }
   if (er == 0)
      return 0;
   return er->fValue;
}

//______________________________________________________________________________
Int_t TEnv::GetValue(const char *name, Int_t dflt)
{
   // Returns the integer value for a resource. If the resource is not found
   // return the dflt value.

   const char *cp = TEnv::Getvalue(name);
   if (cp) {
      char buf2[512], *cp2 = buf2;

      while (isspace((int)*cp))
         cp++;
      if (*cp) {
         BoolNameTable_t *bt;
         if (isdigit((int)*cp) || *cp == '-' || *cp == '+')
            return atoi(cp);
         while (isalpha((int)*cp))
            *cp2++ = toupper((int)*cp++);
         *cp2 = 0;
         for (bt = gBoolNames; bt->fName; bt++)
            if (strcmp(buf2, bt->fName) == 0)
               return bt->fValue;
      }
   }
   return dflt;
}

//______________________________________________________________________________
Double_t TEnv::GetValue(const char *name, Double_t dflt)
{
   // Returns the double value for a resource. If the resource is not found
   // return the dflt value.

   const char *cp = TEnv::Getvalue(name);
   if (cp) {
      char *endptr;
      Double_t val = strtod(cp, &endptr);
      if (val == 0.0 && cp == endptr)
         return dflt;
      return val;
   }
   return dflt;
}

//______________________________________________________________________________
const char *TEnv::GetValue(const char *name, const char *dflt)
{
   // Returns the character value for a named resouce. If the resource is
   // not found the dflt value is returned.

   const char *cp = TEnv::Getvalue(name);
   if (cp)
      return cp;
   return dflt;
}

//______________________________________________________________________________
TEnvRec *TEnv::Lookup(const char *name)
{
   // Loop over all resource records and return the one with name.
   // Return 0 in case name is not in the resoucre table.

   if (!fTable) return 0;
   return (TEnvRec*) fTable->FindObject(name);
}

//______________________________________________________________________________
void TEnv::Print(Option_t *opt) const
{
   // Print all resources or the global, user or local resources separately.

   if (!opt || !strlen(opt)) {
      PrintEnv();
      return;
   }

   if (!strcmp(opt, "global"))
      PrintEnv(kEnvGlobal);
   if (!strcmp(opt, "user"))
      PrintEnv(kEnvUser);
   if (!strcmp(opt, "local"))
      PrintEnv(kEnvLocal);
}

//______________________________________________________________________________
void TEnv::PrintEnv(EEnvLevel level) const
{
   // Print all resources for a certain level (global, user, local, changed).

   if (!fTable) return;

   TIter next(fTable);
   TEnvRec *er;
   static const char *lc[] = { "Global", "User", "Local", "Changed", "All" };

   while ((er = (TEnvRec*) next()))
      if (er->fLevel == level || level == kEnvAll)
         Printf("%-25s %-30s [%s]", Form("%s:", er->fName.Data()),
                er->fValue.Data(), lc[er->fLevel]);
}

//______________________________________________________________________________
Int_t TEnv::ReadFile(const char *fname, EEnvLevel level)
{
   // Read and parse the resource file for a certain level.
   // Returns -1 on case of error, 0 in case of success.

   if (!fname || !strlen(fname)) {
      Error("ReadFile", "no file name specified");
      return -1;
   }

   FILE *ifp;
   if ((ifp = fopen(fname, "r"))) {
      TReadEnvParser rp(this, ifp, level);
      rp.Parse();
      fclose(ifp);
      return 0;
   }

   // no Error() here since we are allowed to try to read from a non-existing
   // file (like ./.rootrc, $HOME/.rootrc, etc.)
   return -1;
}

//______________________________________________________________________________
Int_t TEnv::WriteFile(const char *fname, EEnvLevel level)
{
   // Write resourse records to file fname for a certain level. Use
   // level kEnvAll to write all resources. Returns -1 on case of error,
   // 0 in case of success.

   if (!fname || !strlen(fname)) {
      Error("WriteFile", "no file name specified");
      return -1;
   }

   if (!fTable) {
      Error("WriteFile", "TEnv table is empty");
      return -1;
   }

   FILE *ofp;
   if ((ofp = fopen(fname, "w"))) {
      TIter next(fTable);
      TEnvRec *er;
      while ((er = (TEnvRec*) next()))
         if (er->fLevel == level || level == kEnvAll)
            fprintf(ofp, "%-40s %s\n", Form("%s:", er->fName.Data()),
                    er->fValue.Data());
      fclose(ofp);
      return 0;
   }

   Error("WriteFile", "cannot open %s for writing", fname);
   return -1;
}

//______________________________________________________________________________
void TEnv::Save()
{
   // Write the resource files for each level. The new files have the same
   // name as the original files. The old files are renamed to *.bak.

   if (fRcName == "") {
      Error("Save", "no resource file name specified");
      return;
   }

   SaveLevel(kEnvLocal);  // Be default, new items will be put into Local.
   SaveLevel(kEnvUser);
   SaveLevel(kEnvGlobal);
}

//______________________________________________________________________________
void TEnv::SaveLevel(EEnvLevel level)
{
   // Write the resource file for a certain level.

   if (fRcName == "") {
      Error("SaveLevel", "no resource file name specified");
      return;
   }

   if (!fTable) {
      Error("SaveLevel", "TEnv table is empty");
      return;
   }

   TString   rootrcdir;
   FILE     *ifp, *ofp;

   if (level == kEnvGlobal) {

      TString sname = "system";
      sname += fRcName;
#ifdef ROOTETCDIR
      char *s = gSystem->ConcatFileName(ROOTETCDIR, sname);
#else
      TString etc = gRootDir;
#ifdef WIN32
      etc += "\\etc";
#else
      etc += "/etc";
#endif
      char *s = gSystem->ConcatFileName(etc, sname);
#endif
      rootrcdir = s;
      delete [] s;
   } else if (level == kEnvUser) {
      char *s = gSystem->ConcatFileName(gSystem->HomeDirectory(), fRcName);
      rootrcdir = s;
      delete [] s;
   } else if (level == kEnvLocal)
      rootrcdir = fRcName;
   else
      return;

   if ((ofp = fopen(Form("%s.new", rootrcdir.Data()), "w"))) {
      ifp = fopen(rootrcdir.Data(), "r");
      if (ifp == 0) {     // try to create file
         ifp = fopen(rootrcdir.Data(), "w");
         if (ifp) {
            fclose(ifp);
            ifp = 0;
         }
      }
      if (ifp || (ifp = fopen(rootrcdir.Data(), "r"))) {
         TWriteEnvParser wp(this, ifp, ofp);
         wp.Parse();

         TIter next(fTable);
         TEnvRec *er;
         while ((er = (TEnvRec*) next())) {
            if (er->fModified) {

               // If it doesn't have a level yet, make it this one.
               if (er->fLevel == kEnvChange) er->fLevel = level;
               if (er->fLevel == level) {
                  er->fModified = kFALSE;
                  fprintf(ofp, "%-40s %s\n", Form("%s:", er->fName.Data()),
                          er->fValue.Data());
               }
            }
         }
         fclose(ifp);
         fclose(ofp);
         gSystem->Rename(rootrcdir.Data(), Form("%s.bak", rootrcdir.Data()));
         gSystem->Rename(Form("%s.new", rootrcdir.Data()), rootrcdir.Data());
         return;
      }
      fclose(ofp);
   } else
      Error("SaveLevel", "cannot write to file %s", rootrcdir.Data());
}

//______________________________________________________________________________
void TEnv::SetValue(const char *name, const char *value, EEnvLevel level,
                    const char *type)
{
   // Set the value of a resource or create a new resource.

   if (!fTable)
      fTable  = new THashList(1000);

   const char *nam = name;
   Bool_t append = kFALSE;
   if (name[0] == '+') {
      nam    = &name[1];
      append = kTRUE;
   }

   TEnvRec *er = Lookup(nam);
   if (er)
      er->ChangeValue(value, type, level, append, fIgnoreDup);
   else
      fTable->Add(new TEnvRec(nam, value, type, level));
}

//______________________________________________________________________________
void TEnv::SetValue(const char *name, EEnvLevel level)
{
   // Set the value of a resource or create a new resource.
   // Use this method to set a resource like, "name=val".
   // If just "name" is given it will be interpreted as "name=1".

   TString buf = name;
   int l = buf.Index("=");
   if (l > 0) {
      TString nm  = buf(0, l);
      TString val = buf(l+1, buf.Length());
      SetValue(nm, val, level);
   } else
      SetValue(name, "1", level);
}

//______________________________________________________________________________
void TEnv::SetValue(const char *name, Int_t value)
{
   // Set or create an integer resource value.

   SetValue(name, Form("%d", value));
}

//______________________________________________________________________________
void TEnv::SetValue(const char *name, double value)
{
   // Set or create a double resource value.

   SetValue(name, Form("%g", value));
}

//______________________________________________________________________________
Bool_t TEnv::IgnoreDuplicates(Bool_t ignore)
{
   // If set to true, no warnings in case of duplicates are issued.
   // Returns previous value.

   Bool_t ret = fIgnoreDup;
   fIgnoreDup = ignore;
   return ret;
}
 TEnv.cxx:1
 TEnv.cxx:2
 TEnv.cxx:3
 TEnv.cxx:4
 TEnv.cxx:5
 TEnv.cxx:6
 TEnv.cxx:7
 TEnv.cxx:8
 TEnv.cxx:9
 TEnv.cxx:10
 TEnv.cxx:11
 TEnv.cxx:12
 TEnv.cxx:13
 TEnv.cxx:14
 TEnv.cxx:15
 TEnv.cxx:16
 TEnv.cxx:17
 TEnv.cxx:18
 TEnv.cxx:19
 TEnv.cxx:20
 TEnv.cxx:21
 TEnv.cxx:22
 TEnv.cxx:23
 TEnv.cxx:24
 TEnv.cxx:25
 TEnv.cxx:26
 TEnv.cxx:27
 TEnv.cxx:28
 TEnv.cxx:29
 TEnv.cxx:30
 TEnv.cxx:31
 TEnv.cxx:32
 TEnv.cxx:33
 TEnv.cxx:34
 TEnv.cxx:35
 TEnv.cxx:36
 TEnv.cxx:37
 TEnv.cxx:38
 TEnv.cxx:39
 TEnv.cxx:40
 TEnv.cxx:41
 TEnv.cxx:42
 TEnv.cxx:43
 TEnv.cxx:44
 TEnv.cxx:45
 TEnv.cxx:46
 TEnv.cxx:47
 TEnv.cxx:48
 TEnv.cxx:49
 TEnv.cxx:50
 TEnv.cxx:51
 TEnv.cxx:52
 TEnv.cxx:53
 TEnv.cxx:54
 TEnv.cxx:55
 TEnv.cxx:56
 TEnv.cxx:57
 TEnv.cxx:58
 TEnv.cxx:59
 TEnv.cxx:60
 TEnv.cxx:61
 TEnv.cxx:62
 TEnv.cxx:63
 TEnv.cxx:64
 TEnv.cxx:65
 TEnv.cxx:66
 TEnv.cxx:67
 TEnv.cxx:68
 TEnv.cxx:69
 TEnv.cxx:70
 TEnv.cxx:71
 TEnv.cxx:72
 TEnv.cxx:73
 TEnv.cxx:74
 TEnv.cxx:75
 TEnv.cxx:76
 TEnv.cxx:77
 TEnv.cxx:78
 TEnv.cxx:79
 TEnv.cxx:80
 TEnv.cxx:81
 TEnv.cxx:82
 TEnv.cxx:83
 TEnv.cxx:84
 TEnv.cxx:85
 TEnv.cxx:86
 TEnv.cxx:87
 TEnv.cxx:88
 TEnv.cxx:89
 TEnv.cxx:90
 TEnv.cxx:91
 TEnv.cxx:92
 TEnv.cxx:93
 TEnv.cxx:94
 TEnv.cxx:95
 TEnv.cxx:96
 TEnv.cxx:97
 TEnv.cxx:98
 TEnv.cxx:99
 TEnv.cxx:100
 TEnv.cxx:101
 TEnv.cxx:102
 TEnv.cxx:103
 TEnv.cxx:104
 TEnv.cxx:105
 TEnv.cxx:106
 TEnv.cxx:107
 TEnv.cxx:108
 TEnv.cxx:109
 TEnv.cxx:110
 TEnv.cxx:111
 TEnv.cxx:112
 TEnv.cxx:113
 TEnv.cxx:114
 TEnv.cxx:115
 TEnv.cxx:116
 TEnv.cxx:117
 TEnv.cxx:118
 TEnv.cxx:119
 TEnv.cxx:120
 TEnv.cxx:121
 TEnv.cxx:122
 TEnv.cxx:123
 TEnv.cxx:124
 TEnv.cxx:125
 TEnv.cxx:126
 TEnv.cxx:127
 TEnv.cxx:128
 TEnv.cxx:129
 TEnv.cxx:130
 TEnv.cxx:131
 TEnv.cxx:132
 TEnv.cxx:133
 TEnv.cxx:134
 TEnv.cxx:135
 TEnv.cxx:136
 TEnv.cxx:137
 TEnv.cxx:138
 TEnv.cxx:139
 TEnv.cxx:140
 TEnv.cxx:141
 TEnv.cxx:142
 TEnv.cxx:143
 TEnv.cxx:144
 TEnv.cxx:145
 TEnv.cxx:146
 TEnv.cxx:147
 TEnv.cxx:148
 TEnv.cxx:149
 TEnv.cxx:150
 TEnv.cxx:151
 TEnv.cxx:152
 TEnv.cxx:153
 TEnv.cxx:154
 TEnv.cxx:155
 TEnv.cxx:156
 TEnv.cxx:157
 TEnv.cxx:158
 TEnv.cxx:159
 TEnv.cxx:160
 TEnv.cxx:161
 TEnv.cxx:162
 TEnv.cxx:163
 TEnv.cxx:164
 TEnv.cxx:165
 TEnv.cxx:166
 TEnv.cxx:167
 TEnv.cxx:168
 TEnv.cxx:169
 TEnv.cxx:170
 TEnv.cxx:171
 TEnv.cxx:172
 TEnv.cxx:173
 TEnv.cxx:174
 TEnv.cxx:175
 TEnv.cxx:176
 TEnv.cxx:177
 TEnv.cxx:178
 TEnv.cxx:179
 TEnv.cxx:180
 TEnv.cxx:181
 TEnv.cxx:182
 TEnv.cxx:183
 TEnv.cxx:184
 TEnv.cxx:185
 TEnv.cxx:186
 TEnv.cxx:187
 TEnv.cxx:188
 TEnv.cxx:189
 TEnv.cxx:190
 TEnv.cxx:191
 TEnv.cxx:192
 TEnv.cxx:193
 TEnv.cxx:194
 TEnv.cxx:195
 TEnv.cxx:196
 TEnv.cxx:197
 TEnv.cxx:198
 TEnv.cxx:199
 TEnv.cxx:200
 TEnv.cxx:201
 TEnv.cxx:202
 TEnv.cxx:203
 TEnv.cxx:204
 TEnv.cxx:205
 TEnv.cxx:206
 TEnv.cxx:207
 TEnv.cxx:208
 TEnv.cxx:209
 TEnv.cxx:210
 TEnv.cxx:211
 TEnv.cxx:212
 TEnv.cxx:213
 TEnv.cxx:214
 TEnv.cxx:215
 TEnv.cxx:216
 TEnv.cxx:217
 TEnv.cxx:218
 TEnv.cxx:219
 TEnv.cxx:220
 TEnv.cxx:221
 TEnv.cxx:222
 TEnv.cxx:223
 TEnv.cxx:224
 TEnv.cxx:225
 TEnv.cxx:226
 TEnv.cxx:227
 TEnv.cxx:228
 TEnv.cxx:229
 TEnv.cxx:230
 TEnv.cxx:231
 TEnv.cxx:232
 TEnv.cxx:233
 TEnv.cxx:234
 TEnv.cxx:235
 TEnv.cxx:236
 TEnv.cxx:237
 TEnv.cxx:238
 TEnv.cxx:239
 TEnv.cxx:240
 TEnv.cxx:241
 TEnv.cxx:242
 TEnv.cxx:243
 TEnv.cxx:244
 TEnv.cxx:245
 TEnv.cxx:246
 TEnv.cxx:247
 TEnv.cxx:248
 TEnv.cxx:249
 TEnv.cxx:250
 TEnv.cxx:251
 TEnv.cxx:252
 TEnv.cxx:253
 TEnv.cxx:254
 TEnv.cxx:255
 TEnv.cxx:256
 TEnv.cxx:257
 TEnv.cxx:258
 TEnv.cxx:259
 TEnv.cxx:260
 TEnv.cxx:261
 TEnv.cxx:262
 TEnv.cxx:263
 TEnv.cxx:264
 TEnv.cxx:265
 TEnv.cxx:266
 TEnv.cxx:267
 TEnv.cxx:268
 TEnv.cxx:269
 TEnv.cxx:270
 TEnv.cxx:271
 TEnv.cxx:272
 TEnv.cxx:273
 TEnv.cxx:274
 TEnv.cxx:275
 TEnv.cxx:276
 TEnv.cxx:277
 TEnv.cxx:278
 TEnv.cxx:279
 TEnv.cxx:280
 TEnv.cxx:281
 TEnv.cxx:282
 TEnv.cxx:283
 TEnv.cxx:284
 TEnv.cxx:285
 TEnv.cxx:286
 TEnv.cxx:287
 TEnv.cxx:288
 TEnv.cxx:289
 TEnv.cxx:290
 TEnv.cxx:291
 TEnv.cxx:292
 TEnv.cxx:293
 TEnv.cxx:294
 TEnv.cxx:295
 TEnv.cxx:296
 TEnv.cxx:297
 TEnv.cxx:298
 TEnv.cxx:299
 TEnv.cxx:300
 TEnv.cxx:301
 TEnv.cxx:302
 TEnv.cxx:303
 TEnv.cxx:304
 TEnv.cxx:305
 TEnv.cxx:306
 TEnv.cxx:307
 TEnv.cxx:308
 TEnv.cxx:309
 TEnv.cxx:310
 TEnv.cxx:311
 TEnv.cxx:312
 TEnv.cxx:313
 TEnv.cxx:314
 TEnv.cxx:315
 TEnv.cxx:316
 TEnv.cxx:317
 TEnv.cxx:318
 TEnv.cxx:319
 TEnv.cxx:320
 TEnv.cxx:321
 TEnv.cxx:322
 TEnv.cxx:323
 TEnv.cxx:324
 TEnv.cxx:325
 TEnv.cxx:326
 TEnv.cxx:327
 TEnv.cxx:328
 TEnv.cxx:329
 TEnv.cxx:330
 TEnv.cxx:331
 TEnv.cxx:332
 TEnv.cxx:333
 TEnv.cxx:334
 TEnv.cxx:335
 TEnv.cxx:336
 TEnv.cxx:337
 TEnv.cxx:338
 TEnv.cxx:339
 TEnv.cxx:340
 TEnv.cxx:341
 TEnv.cxx:342
 TEnv.cxx:343
 TEnv.cxx:344
 TEnv.cxx:345
 TEnv.cxx:346
 TEnv.cxx:347
 TEnv.cxx:348
 TEnv.cxx:349
 TEnv.cxx:350
 TEnv.cxx:351
 TEnv.cxx:352
 TEnv.cxx:353
 TEnv.cxx:354
 TEnv.cxx:355
 TEnv.cxx:356
 TEnv.cxx:357
 TEnv.cxx:358
 TEnv.cxx:359
 TEnv.cxx:360
 TEnv.cxx:361
 TEnv.cxx:362
 TEnv.cxx:363
 TEnv.cxx:364
 TEnv.cxx:365
 TEnv.cxx:366
 TEnv.cxx:367
 TEnv.cxx:368
 TEnv.cxx:369
 TEnv.cxx:370
 TEnv.cxx:371
 TEnv.cxx:372
 TEnv.cxx:373
 TEnv.cxx:374
 TEnv.cxx:375
 TEnv.cxx:376
 TEnv.cxx:377
 TEnv.cxx:378
 TEnv.cxx:379
 TEnv.cxx:380
 TEnv.cxx:381
 TEnv.cxx:382
 TEnv.cxx:383
 TEnv.cxx:384
 TEnv.cxx:385
 TEnv.cxx:386
 TEnv.cxx:387
 TEnv.cxx:388
 TEnv.cxx:389
 TEnv.cxx:390
 TEnv.cxx:391
 TEnv.cxx:392
 TEnv.cxx:393
 TEnv.cxx:394
 TEnv.cxx:395
 TEnv.cxx:396
 TEnv.cxx:397
 TEnv.cxx:398
 TEnv.cxx:399
 TEnv.cxx:400
 TEnv.cxx:401
 TEnv.cxx:402
 TEnv.cxx:403
 TEnv.cxx:404
 TEnv.cxx:405
 TEnv.cxx:406
 TEnv.cxx:407
 TEnv.cxx:408
 TEnv.cxx:409
 TEnv.cxx:410
 TEnv.cxx:411
 TEnv.cxx:412
 TEnv.cxx:413
 TEnv.cxx:414
 TEnv.cxx:415
 TEnv.cxx:416
 TEnv.cxx:417
 TEnv.cxx:418
 TEnv.cxx:419
 TEnv.cxx:420
 TEnv.cxx:421
 TEnv.cxx:422
 TEnv.cxx:423
 TEnv.cxx:424
 TEnv.cxx:425
 TEnv.cxx:426
 TEnv.cxx:427
 TEnv.cxx:428
 TEnv.cxx:429
 TEnv.cxx:430
 TEnv.cxx:431
 TEnv.cxx:432
 TEnv.cxx:433
 TEnv.cxx:434
 TEnv.cxx:435
 TEnv.cxx:436
 TEnv.cxx:437
 TEnv.cxx:438
 TEnv.cxx:439
 TEnv.cxx:440
 TEnv.cxx:441
 TEnv.cxx:442
 TEnv.cxx:443
 TEnv.cxx:444
 TEnv.cxx:445
 TEnv.cxx:446
 TEnv.cxx:447
 TEnv.cxx:448
 TEnv.cxx:449
 TEnv.cxx:450
 TEnv.cxx:451
 TEnv.cxx:452
 TEnv.cxx:453
 TEnv.cxx:454
 TEnv.cxx:455
 TEnv.cxx:456
 TEnv.cxx:457
 TEnv.cxx:458
 TEnv.cxx:459
 TEnv.cxx:460
 TEnv.cxx:461
 TEnv.cxx:462
 TEnv.cxx:463
 TEnv.cxx:464
 TEnv.cxx:465
 TEnv.cxx:466
 TEnv.cxx:467
 TEnv.cxx:468
 TEnv.cxx:469
 TEnv.cxx:470
 TEnv.cxx:471
 TEnv.cxx:472
 TEnv.cxx:473
 TEnv.cxx:474
 TEnv.cxx:475
 TEnv.cxx:476
 TEnv.cxx:477
 TEnv.cxx:478
 TEnv.cxx:479
 TEnv.cxx:480
 TEnv.cxx:481
 TEnv.cxx:482
 TEnv.cxx:483
 TEnv.cxx:484
 TEnv.cxx:485
 TEnv.cxx:486
 TEnv.cxx:487
 TEnv.cxx:488
 TEnv.cxx:489
 TEnv.cxx:490
 TEnv.cxx:491
 TEnv.cxx:492
 TEnv.cxx:493
 TEnv.cxx:494
 TEnv.cxx:495
 TEnv.cxx:496
 TEnv.cxx:497
 TEnv.cxx:498
 TEnv.cxx:499
 TEnv.cxx:500
 TEnv.cxx:501
 TEnv.cxx:502
 TEnv.cxx:503
 TEnv.cxx:504
 TEnv.cxx:505
 TEnv.cxx:506
 TEnv.cxx:507
 TEnv.cxx:508
 TEnv.cxx:509
 TEnv.cxx:510
 TEnv.cxx:511
 TEnv.cxx:512
 TEnv.cxx:513
 TEnv.cxx:514
 TEnv.cxx:515
 TEnv.cxx:516
 TEnv.cxx:517
 TEnv.cxx:518
 TEnv.cxx:519
 TEnv.cxx:520
 TEnv.cxx:521
 TEnv.cxx:522
 TEnv.cxx:523
 TEnv.cxx:524
 TEnv.cxx:525
 TEnv.cxx:526
 TEnv.cxx:527
 TEnv.cxx:528
 TEnv.cxx:529
 TEnv.cxx:530
 TEnv.cxx:531
 TEnv.cxx:532
 TEnv.cxx:533
 TEnv.cxx:534
 TEnv.cxx:535
 TEnv.cxx:536
 TEnv.cxx:537
 TEnv.cxx:538
 TEnv.cxx:539
 TEnv.cxx:540
 TEnv.cxx:541
 TEnv.cxx:542
 TEnv.cxx:543
 TEnv.cxx:544
 TEnv.cxx:545
 TEnv.cxx:546
 TEnv.cxx:547
 TEnv.cxx:548
 TEnv.cxx:549
 TEnv.cxx:550
 TEnv.cxx:551
 TEnv.cxx:552
 TEnv.cxx:553
 TEnv.cxx:554
 TEnv.cxx:555
 TEnv.cxx:556
 TEnv.cxx:557
 TEnv.cxx:558
 TEnv.cxx:559
 TEnv.cxx:560
 TEnv.cxx:561
 TEnv.cxx:562
 TEnv.cxx:563
 TEnv.cxx:564
 TEnv.cxx:565
 TEnv.cxx:566
 TEnv.cxx:567
 TEnv.cxx:568
 TEnv.cxx:569
 TEnv.cxx:570
 TEnv.cxx:571
 TEnv.cxx:572
 TEnv.cxx:573
 TEnv.cxx:574
 TEnv.cxx:575
 TEnv.cxx:576
 TEnv.cxx:577
 TEnv.cxx:578
 TEnv.cxx:579
 TEnv.cxx:580
 TEnv.cxx:581
 TEnv.cxx:582
 TEnv.cxx:583
 TEnv.cxx:584
 TEnv.cxx:585
 TEnv.cxx:586
 TEnv.cxx:587
 TEnv.cxx:588
 TEnv.cxx:589
 TEnv.cxx:590
 TEnv.cxx:591
 TEnv.cxx:592
 TEnv.cxx:593
 TEnv.cxx:594
 TEnv.cxx:595
 TEnv.cxx:596
 TEnv.cxx:597
 TEnv.cxx:598
 TEnv.cxx:599
 TEnv.cxx:600
 TEnv.cxx:601
 TEnv.cxx:602
 TEnv.cxx:603
 TEnv.cxx:604
 TEnv.cxx:605
 TEnv.cxx:606
 TEnv.cxx:607
 TEnv.cxx:608
 TEnv.cxx:609
 TEnv.cxx:610
 TEnv.cxx:611
 TEnv.cxx:612
 TEnv.cxx:613
 TEnv.cxx:614
 TEnv.cxx:615
 TEnv.cxx:616
 TEnv.cxx:617
 TEnv.cxx:618
 TEnv.cxx:619
 TEnv.cxx:620
 TEnv.cxx:621
 TEnv.cxx:622
 TEnv.cxx:623
 TEnv.cxx:624
 TEnv.cxx:625
 TEnv.cxx:626
 TEnv.cxx:627
 TEnv.cxx:628
 TEnv.cxx:629
 TEnv.cxx:630
 TEnv.cxx:631
 TEnv.cxx:632
 TEnv.cxx:633
 TEnv.cxx:634
 TEnv.cxx:635
 TEnv.cxx:636
 TEnv.cxx:637
 TEnv.cxx:638
 TEnv.cxx:639
 TEnv.cxx:640
 TEnv.cxx:641
 TEnv.cxx:642
 TEnv.cxx:643
 TEnv.cxx:644
 TEnv.cxx:645
 TEnv.cxx:646
 TEnv.cxx:647
 TEnv.cxx:648
 TEnv.cxx:649
 TEnv.cxx:650
 TEnv.cxx:651
 TEnv.cxx:652
 TEnv.cxx:653
 TEnv.cxx:654
 TEnv.cxx:655
 TEnv.cxx:656
 TEnv.cxx:657
 TEnv.cxx:658
 TEnv.cxx:659
 TEnv.cxx:660
 TEnv.cxx:661
 TEnv.cxx:662
 TEnv.cxx:663
 TEnv.cxx:664
 TEnv.cxx:665
 TEnv.cxx:666
 TEnv.cxx:667
 TEnv.cxx:668
 TEnv.cxx:669
 TEnv.cxx:670
 TEnv.cxx:671
 TEnv.cxx:672
 TEnv.cxx:673
 TEnv.cxx:674
 TEnv.cxx:675
 TEnv.cxx:676
 TEnv.cxx:677
 TEnv.cxx:678
 TEnv.cxx:679
 TEnv.cxx:680
 TEnv.cxx:681
 TEnv.cxx:682
 TEnv.cxx:683
 TEnv.cxx:684
 TEnv.cxx:685
 TEnv.cxx:686
 TEnv.cxx:687
 TEnv.cxx:688
 TEnv.cxx:689
 TEnv.cxx:690
 TEnv.cxx:691
 TEnv.cxx:692
 TEnv.cxx:693
 TEnv.cxx:694
 TEnv.cxx:695
 TEnv.cxx:696
 TEnv.cxx:697
 TEnv.cxx:698
 TEnv.cxx:699
 TEnv.cxx:700
 TEnv.cxx:701
 TEnv.cxx:702
 TEnv.cxx:703
 TEnv.cxx:704
 TEnv.cxx:705
 TEnv.cxx:706
 TEnv.cxx:707
 TEnv.cxx:708
 TEnv.cxx:709
 TEnv.cxx:710
 TEnv.cxx:711
 TEnv.cxx:712
 TEnv.cxx:713
 TEnv.cxx:714
 TEnv.cxx:715
 TEnv.cxx:716
 TEnv.cxx:717
 TEnv.cxx:718
 TEnv.cxx:719
 TEnv.cxx:720
 TEnv.cxx:721
 TEnv.cxx:722
 TEnv.cxx:723
 TEnv.cxx:724
 TEnv.cxx:725
 TEnv.cxx:726
 TEnv.cxx:727
 TEnv.cxx:728
 TEnv.cxx:729
 TEnv.cxx:730
 TEnv.cxx:731
 TEnv.cxx:732
 TEnv.cxx:733
 TEnv.cxx:734
 TEnv.cxx:735
 TEnv.cxx:736
 TEnv.cxx:737
 TEnv.cxx:738
 TEnv.cxx:739
 TEnv.cxx:740
 TEnv.cxx:741
 TEnv.cxx:742
 TEnv.cxx:743
 TEnv.cxx:744
 TEnv.cxx:745
 TEnv.cxx:746
 TEnv.cxx:747
 TEnv.cxx:748
 TEnv.cxx:749
 TEnv.cxx:750
 TEnv.cxx:751
 TEnv.cxx:752
 TEnv.cxx:753
 TEnv.cxx:754
 TEnv.cxx:755
 TEnv.cxx:756
 TEnv.cxx:757
 TEnv.cxx:758
 TEnv.cxx:759
 TEnv.cxx:760
 TEnv.cxx:761
 TEnv.cxx:762
 TEnv.cxx:763
 TEnv.cxx:764
 TEnv.cxx:765
 TEnv.cxx:766
 TEnv.cxx:767
 TEnv.cxx:768
 TEnv.cxx:769
 TEnv.cxx:770
 TEnv.cxx:771
 TEnv.cxx:772
 TEnv.cxx:773
 TEnv.cxx:774
 TEnv.cxx:775
 TEnv.cxx:776
 TEnv.cxx:777
 TEnv.cxx:778
 TEnv.cxx:779
 TEnv.cxx:780
 TEnv.cxx:781
 TEnv.cxx:782
 TEnv.cxx:783
 TEnv.cxx:784
 TEnv.cxx:785
 TEnv.cxx:786
 TEnv.cxx:787
 TEnv.cxx:788
 TEnv.cxx:789
 TEnv.cxx:790
 TEnv.cxx:791
 TEnv.cxx:792
 TEnv.cxx:793
 TEnv.cxx:794
 TEnv.cxx:795
 TEnv.cxx:796
 TEnv.cxx:797
 TEnv.cxx:798
 TEnv.cxx:799
 TEnv.cxx:800
 TEnv.cxx:801
 TEnv.cxx:802
 TEnv.cxx:803
 TEnv.cxx:804
 TEnv.cxx:805
 TEnv.cxx:806
 TEnv.cxx:807
 TEnv.cxx:808
 TEnv.cxx:809
 TEnv.cxx:810