#include "Col.ph" #ifdef __GNUG__ #pragma implementation #endif #include "Env.h" #include "Class.h" #include "String.h" #include "System.h" #include "OrdColl.h" #include "StreamBuf.h" #include "ET_stdio.h" #include "ET_stdlib.h" //---- EnvParser --------------------------------------------------------------- class EnvParser { FILE *ifp; public: EnvParser(FILE *f) { ifp= f; } virtual void KeyValue(char*, char*, char*) { } virtual void Char(int) { } void Parse(); }; void EnvParser::Parse() { char name[200], type[200], value[200]; int c, state= 0, ni, ti, vi; ni= ti= vi= 0; while ((c= fgetc(ifp)) != EOF) { if (c == '\n') { state= 0; if (ni > 0) { name[ni++]= 0; type[ti++]= 0; value[vi++]= 0; ni= ti= vi= 0; KeyValue(name, value, type); } 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[ni++]= c; break; case 4: value[vi++]= c; break; case 5: type[ti++]= c; break; } if (state != 4) Char(c); } } //---- ReadEnvParser ----------------------------------------------------------- class ReadEnvParser: public EnvParser { EnvLevel level; public: ReadEnvParser(FILE *f, EnvLevel l) : EnvParser(f) { level= l; } void KeyValue(char *name, char *value, char *type) { Env::SetValue(name, value, level, type); } }; //---- WriteEnvParser ---------------------------------------------------------- class WriteEnvParser: public EnvParser { FILE *ofp; public: WriteEnvParser(FILE *f, FILE *of) : EnvParser(f) { ofp= of; } void KeyValue(char *name, char *value, char *type); void Char(int c) { fputc(c, ofp); } }; void WriteEnvParser::KeyValue(char *name, char *value, char*) { EnvRec *er= Env::Lookup(name); if (er && er->changed) { er->changed= FALSE; if (er->op) er->Write(er->op); fprintf(ofp, "%s", er->value); } else fprintf(ofp, "%s", value); } //---- EnvRec ------------------------------------------------------------------ NewMetaImpl(EnvRec,Object, (T(name), TS(value), TS(type), TE(level), TB(changed))); EnvRec::EnvRec(const Symbol &n, const char *v, const char *t, EnvLevel l) { name= n; value= strsave(v); level= l; type= strsave(t); changed= (l == eEnvChange); op= 0; } EnvRec::~EnvRec() { SafeDelete(value); SafeDelete(type); } void EnvRec::Read(Object *op) { IStream is(value, strlen(value)); op->ReadFrom(is); } /* Object *EnvRec::Read2() { Object *op= 0; IStream is(value, strlen(value)); is >> op; return op; } */ void EnvRec::Write(Object *op) { char *cp= new char[1000]; OStream os(1000, cp); op->PrintOn(os); ChangeValue(cp, 0, eEnvChange); delete cp; } /* void EnvRec::Write2(Object*) { } */ void EnvRec::ChangeValue(const char *v, const char*, EnvLevel l) { if (l != eEnvChange && level == l) { fprintf(stderr, "EnvRec::ChangeValue: duplicate entry <%s=%s> for level %d; ignored\n", name.AsString(), v, l); return; } if (strcmp(value, v) != 0) { if (l == eEnvChange) changed= TRUE; else { changed= FALSE; level= l; } strreplace(&value, v); if (changed && op) Read(op); } } void EnvRec::InspectorId(char *buf, int bufSize) { strn0cpy(buf, name.AsString(), bufSize); } int EnvRec::Compare(Object *op) { return StrCmp(name.AsString(), Guard(op,EnvRec)->name.AsString(), -1, gStdEncoding->SortMap()); } //---- EnvRec ------------------------------------------------------------------ NewMetaImpl(Env,Object, (TP(table), TB(terminated))); static Env gEnv; OrdCollection *Env::table; bool Env::terminated; Env::Env() { } Env::~Env() { terminated= TRUE; if (table) { table->FreeAll(); SafeDelete(table); } } void Env::Init() { if (table) return; table= new OrdCollection; InitSystem(); ReadFile(form("%s/ETRC", gEtDir), eEnvGlobal); ReadFile(form("%s/ETRC", gSystem->HomeDirectory()), eEnvUser); ReadFile("ETRC", eEnvLocal); const char *e; for (int i= 0; e= gSystem->GetEnvAt(i); i++) SetValue(e, eEnvEnvironment); } EnvRec *Env::Lookup(const char *n) { if (table == 0) Env::Init(); u_int name; if (name= (u_int) Symbol::Lookup(n)) { Iter next(table); EnvRec *er; while (er= (EnvRec*) next()) if (er->name.Id() == name) return er; } return 0; } //---- Loading/Storing --------------------------------------------------------- void Env::ReadFile(const char *fname, EnvLevel level) { FILE *ifp; if (ifp= fopen(fname, "r")) { ReadEnvParser rp(ifp, level); rp.Parse(); fclose(ifp); } } void Env::Save() { FILE *ifp, *ofp; if (ofp= fopen(form("%s/ETRC.new", gSystem->HomeDirectory()), "w")) { ifp= fopen(form("%s/ETRC", gSystem->HomeDirectory()), "r"); if (ifp == 0) { // try to create file ifp= fopen(form("%s/ETRC", gSystem->HomeDirectory()), "w"); if (ifp) fclose(ifp); } if (ifp= fopen(form("%s/ETRC", gSystem->HomeDirectory()), "r")) { WriteEnvParser wp(ifp, ofp); wp.Parse(); Iter next(table); EnvRec *er; while (er= (EnvRec*) next()) if (er->changed) { er->changed= FALSE; fprintf(ofp, "%s %s\n", er->name.AsString(), er->value); } fclose(ifp); fclose(ofp); gSystem->Rename(form("%s/ETRC", gSystem->HomeDirectory()), form("%s/ETRC.BAK", gSystem->HomeDirectory())); gSystem->Rename(form("%s/ETRC.new", gSystem->HomeDirectory()), form("%s/ETRC", gSystem->HomeDirectory())); return; } fclose(ofp); } } //---- GetValue ---------------------------------------------------------------- const char *Env::getvalue(const char *name) { if (terminated) return 0; EnvRec *er= Lookup(form("%s.%s", gProgname, name)); if (er == 0) er= Lookup(form("*.%s", name)); if (er == 0) er= Lookup(name); if (er == 0) return 0; return er->value; } static struct BoolNameTable { const char *name; int value; } boolNames[]= { { "TRUE", 1 }, { "FALSE", 0 }, { "ON", 1 }, { "OFF", 0 }, { "YES", 1 }, { "NO", 0 }, { "OK", 1 }, { "NOT", 0 }, { 0, 0 } }; int Env::GetValue(const char *name, int dflt) { const char *cp= Env::getvalue(name); if (cp) { char buf2[100], *cp2= buf2; while (Isspace(*cp)) cp++; if (*cp) { register BoolNameTable *bt; if (Isdigit(*cp)) return atoi(cp); while (Isalpha(*cp)) *cp2++= gStdEncoding->UpperCaseMap()[*cp++]; *cp2= 0; for (bt= boolNames; bt->name; bt++) if (strcmp(buf2, bt->name) == 0) return bt->value; } } return dflt; } const char *Env::GetValue(const char *name, const char *dflt) { const char *cp= Env::getvalue(name); if (cp) return cp; return dflt; } Point Env::GetValue(const char *name, const Point &dflt) { const char *cp= Env::getvalue(name); if (cp) { Point p; IStream is(cp, strlen(cp)); is >> p; return p; } return dflt; } Object *Env::GetValue(const char *name, Object *op) { EnvRec *er= Lookup(form("%s.%s", gProgname, name)); if (er == 0) er= Lookup(form("*.%s", name)); if (er == 0) er= Lookup(name); if (er) { er->op= op; er->Read(op); } return op; } //---- SetValue ---------------------------------------------------------------- void Env::SetValue(const char *name, const char *value, EnvLevel level, const char *type) { if (table == 0) Env::Init(); EnvRec *er= Lookup(name); if (er) er->ChangeValue(value, type, level); else table->Add(new EnvRec(name, value, type, level)); } void Env::SetValue(const char *name, EnvLevel level) { char *buf= strsave(name), *cp; if (cp= strchr(buf, '=')) { *cp++= 0; SetValue(buf, cp, level); } else SetValue(name, "1", level); delete buf; } void Env::SetValue(const char *name, int value) { SetValue(name, form("%d", value)); } void Env::SetValue(const char *name, double value) { SetValue(name, form("%f", value)); } void Env::SetBoolValue(const char *name, bool value) { SetValue(name, value ? "TRUE" : "FALSE"); }