X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/0a8e3465cb644e380ab0fc6d66f6d1f17363b34e..f58a97d3de5b43fd2cf8c0928939241b7b01c67d:/apt-pkg/contrib/configuration.cc?ds=sidebyside diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 433b92244..1c58b9881 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: configuration.cc,v 1.6 1998/10/02 04:39:49 jgg Exp $ +// $Id: configuration.cc,v 1.13 1999/07/02 23:17:00 jgg Exp $ /* ###################################################################### Configuration Class @@ -17,7 +17,7 @@ #endif #include #include -#include +#include #include #include @@ -33,7 +33,7 @@ Configuration::Configuration() Root = new Item; } /*}}}*/ -// Configuration::Lookup - Lookup a single item /*{{{*/ +// Configuration::Lookup - Lookup a single item /*{{{*/ // --------------------------------------------------------------------- /* This will lookup a single item by name below another item. It is a helper function for the main lookup function */ @@ -43,10 +43,17 @@ Configuration::Item *Configuration::Lookup(Item *Head,const char *S, int Res = 1; Item *I = Head->Child; Item **Last = &Head->Child; - for (; I != 0; Last = &I->Next, I = I->Next) - if ((Res = stringcasecmp(I->Tag.begin(),I->Tag.end(),S,S + Len)) == 0) - break; + // Empty strings match nothing. They are used for lists. + if (Len != 0) + { + for (; I != 0; Last = &I->Next, I = I->Next) + if ((Res = stringcasecmp(I->Tag.begin(),I->Tag.end(),S,S + Len)) == 0) + break; + } + else + for (; I != 0; Last = &I->Next, I = I->Next); + if (Res == 0) return I; if (Create == false) @@ -66,11 +73,14 @@ Configuration::Item *Configuration::Lookup(Item *Head,const char *S, new items */ Configuration::Item *Configuration::Lookup(const char *Name,bool Create) { + if (Name == 0) + return Root->Child; + const char *Start = Name; const char *End = Start + strlen(Name); const char *TagEnd = Name; Item *Itm = Root; - for (; End - TagEnd > 2; TagEnd++) + for (; End - TagEnd >= 2; TagEnd++) { if (TagEnd[0] == ':' && TagEnd[1] == ':') { @@ -81,6 +91,13 @@ Configuration::Item *Configuration::Lookup(const char *Name,bool Create) } } + // This must be a trailing ::, we create unique items in a list + if (End - Start == 0) + { + if (Create == false) + return 0; + } + Itm = Lookup(Itm,Start,End - Start,Create); return Itm; } @@ -102,12 +119,12 @@ string Configuration::Find(const char *Name,const char *Default) return Itm->Value; } /*}}}*/ -// Configuration::FindDir - Find a directory /*{{{*/ +// Configuration::FindFile - Find a Filename /*{{{*/ // --------------------------------------------------------------------- /* Directories are stored as the base dir in the Parent node and the - sub directory in sub nodes + sub directory in sub nodes with the final node being the end filename */ -string Configuration::FindDir(const char *Name,const char *Default = 0) +string Configuration::FindFile(const char *Name,const char *Default) { Item *Itm = Lookup(Name,false); if (Itm == 0 || Itm->Value.empty() == true) @@ -134,6 +151,17 @@ string Configuration::FindDir(const char *Name,const char *Default = 0) return Itm->Parent->Value + '/' + Itm->Value; } /*}}}*/ +// Configuration::FindDir - Find a directory name /*{{{*/ +// --------------------------------------------------------------------- +/* This is like findfile execept the result is terminated in a / */ +string Configuration::FindDir(const char *Name,const char *Default) +{ + string Res = FindFile(Name,Default); + if (Res.end()[-1] != '/') + return Res + '/'; + return Res; +} + /*}}}*/ // Configuration::FindI - Find an integer value /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -160,28 +188,7 @@ bool Configuration::FindB(const char *Name,bool Default) if (Itm == 0 || Itm->Value.empty() == true) return Default; - char *End; - int Res = strtol(Itm->Value.c_str(),&End,0); - if (End == Itm->Value.c_str() || Res < 0 || Res > 1) - { - // Check for positives - if (strcasecmp(Itm->Value.c_str(),"no") == 0 || - strcasecmp(Itm->Value.c_str(),"false") == 0 || - strcasecmp(Itm->Value.c_str(),"without") == 0 || - strcasecmp(Itm->Value.c_str(),"disable") == 0) - return false; - - // Check for negatives - if (strcasecmp(Itm->Value.c_str(),"yes") == 0 || - strcasecmp(Itm->Value.c_str(),"true") == 0 || - strcasecmp(Itm->Value.c_str(),"with") == 0 || - strcasecmp(Itm->Value.c_str(),"enable") == 0) - return true; - - return Default; - } - - return Res; + return StringToBool(Itm->Value,Default); } /*}}}*/ // Configuration::Set - Set a value /*{{{*/ @@ -219,6 +226,42 @@ bool Configuration::Exists(const char *Name) return true; } /*}}}*/ +// Configuration::Dump - Dump the config /*{{{*/ +// --------------------------------------------------------------------- +/* Dump the entire configuration space */ +void Configuration::Dump() +{ + /* Write out all of the configuration directives by walking the + configuration tree */ + const Configuration::Item *Top = _config->Tree(0); + for (; Top != 0;) + { + clog << Top->FullTag() << " \"" << Top->Value << "\";" << endl; + + if (Top->Child != 0) + { + Top = Top->Child; + continue; + } + + while (Top != 0 && Top->Next == 0) + Top = Top->Parent; + if (Top != 0) + Top = Top->Next; + } +} + /*}}}*/ + +// Configuration::Item::FullTag - Return the fully scoped tag /*{{{*/ +// --------------------------------------------------------------------- +/* */ +string Configuration::Item::FullTag() const +{ + if (Parent == 0 || Parent->Parent == 0) + return Tag; + return Parent->FullTag() + "::" + Tag; +} + /*}}}*/ // ReadConfigFile - Read a configuration file /*{{{*/ // --------------------------------------------------------------------- @@ -233,6 +276,8 @@ bool ReadConfigFile(Configuration &Conf,string FName) char Buffer[300]; string LineBuffer; + string Stack[100]; + unsigned int StackPos = 0; // Parser state string ParentTag; @@ -263,8 +308,14 @@ bool ReadConfigFile(Configuration &Conf,string FName) } // Discard single line comments + bool InQuote = false; for (char *I = Buffer; *I != 0; I++) { + if (*I == '"') + InQuote = !InQuote; + if (InQuote == true) + continue; + if (*I == '/' && I[1] == '/') { *I = 0; @@ -275,6 +326,11 @@ bool ReadConfigFile(Configuration &Conf,string FName) // Look for multi line comments for (char *I = Buffer; *I != 0; I++) { + if (*I == '"') + InQuote = !InQuote; + if (InQuote == true) + continue; + if (*I == '/' && I[1] == '*') { InComment = true; @@ -322,11 +378,10 @@ bool ReadConfigFile(Configuration &Conf,string FName) // Move up a tag if (TermChar == '}') { - string::size_type Pos = ParentTag.rfind("::"); - if (Pos == string::npos) + if (StackPos == 0) ParentTag = string(); else - ParentTag = string(ParentTag,0,Pos); + ParentTag = Stack[--StackPos]; } // Syntax Error @@ -337,20 +392,16 @@ bool ReadConfigFile(Configuration &Conf,string FName) continue; // Parse off the tag - string::size_type Pos = LineBuffer.find(' '); - if (Pos == string::npos) - { - if (TermChar == '{') - Pos = LineBuffer.length(); - else - return _error->Error("Syntax error %s:%u: Tag with no value",FName.c_str(),CurLine); - } + string Tag; + const char *Pos = LineBuffer.c_str(); + if (ParseQuoteWord(Pos,Tag) == false) + return _error->Error("Syntax error %s:%u: Malformed Tag",FName.c_str(),CurLine); - string Tag = string(LineBuffer,0,Pos); - // Go down a level if (TermChar == '{') { + if (StackPos <= 100) + Stack[StackPos++] = ParentTag; if (ParentTag.empty() == true) ParentTag = Tag; else @@ -358,28 +409,27 @@ bool ReadConfigFile(Configuration &Conf,string FName) Tag = string(); } - // We dont have a value to set - if (Pos == LineBuffer.length()) + // Parse off the word + string Word; + if (ParseCWord(Pos,Word) == false) { - LineBuffer = string(); - continue; + if (TermChar != '{') + { + Word = Tag; + Tag = ""; + } } - // Parse off the word - string Word; - if (ParseCWord(LineBuffer.c_str()+Pos,Word) == false) - return _error->Error("Syntax error %s:%u: Malformed value",FName.c_str(),CurLine); - // Generate the item name string Item; if (ParentTag.empty() == true) Item = Tag; else { - if (Tag.empty() == true) - Item = ParentTag; - else + if (TermChar != '{' || Tag.empty() == false) Item = ParentTag + "::" + Tag; + else + Item = ParentTag; } // Set the item in the configuration class