]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/configuration.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: configuration.cc,v 1.8 1998/10/22 04:56:45 jgg Exp $
4 /* ######################################################################
8 This class provides a configuration file and command line parser
9 for a tree-oriented configuration environment. All runtime configuration
12 ##################################################################### */
14 // Include files /*{{{*/
16 #pragma implementation "apt-pkg/configuration.h"
18 #include <apt-pkg/configuration.h>
19 #include <apt-pkg/error.h>
26 Configuration
*_config
= new Configuration
;
28 // Configuration::Configuration - Constructor /*{{{*/
29 // ---------------------------------------------------------------------
31 Configuration::Configuration()
36 // Configuration::Lookup - Lookup a single item /*{{{*/
37 // ---------------------------------------------------------------------
38 /* This will lookup a single item by name below another item. It is a
39 helper function for the main lookup function */
40 Configuration::Item
*Configuration::Lookup(Item
*Head
,const char *S
,
41 unsigned long Len
,bool Create
)
44 Item
*I
= Head
->Child
;
45 Item
**Last
= &Head
->Child
;
46 for (; I
!= 0; Last
= &I
->Next
, I
= I
->Next
)
47 if ((Res
= stringcasecmp(I
->Tag
.begin(),I
->Tag
.end(),S
,S
+ Len
)) == 0)
56 I
->Tag
= string(S
,Len
);
63 // Configuration::Lookup - Lookup a fully scoped item /*{{{*/
64 // ---------------------------------------------------------------------
65 /* This performs a fully scoped lookup of a given name, possibly creating
67 Configuration::Item
*Configuration::Lookup(const char *Name
,bool Create
)
72 const char *Start
= Name
;
73 const char *End
= Start
+ strlen(Name
);
74 const char *TagEnd
= Name
;
76 for (; End
- TagEnd
> 2; TagEnd
++)
78 if (TagEnd
[0] == ':' && TagEnd
[1] == ':')
80 Itm
= Lookup(Itm
,Start
,TagEnd
- Start
,Create
);
83 TagEnd
= Start
= TagEnd
+ 2;
87 Itm
= Lookup(Itm
,Start
,End
- Start
,Create
);
91 // Configuration::Find - Find a value /*{{{*/
92 // ---------------------------------------------------------------------
94 string
Configuration::Find(const char *Name
,const char *Default
)
96 Item
*Itm
= Lookup(Name
,false);
97 if (Itm
== 0 || Itm
->Value
.empty() == true)
108 // Configuration::FindFile - Find a Filename /*{{{*/
109 // ---------------------------------------------------------------------
110 /* Directories are stored as the base dir in the Parent node and the
111 sub directory in sub nodes with the final node being the end filename
113 string
Configuration::FindFile(const char *Name
,const char *Default
)
115 Item
*Itm
= Lookup(Name
,false);
116 if (Itm
== 0 || Itm
->Value
.empty() == true)
125 if (Itm
->Value
[0] == '/' || Itm
->Parent
== 0)
128 // ./ is also considered absolute as is anything with ~ in it
129 if (Itm
->Value
[0] != 0 &&
130 ((Itm
->Value
[0] == '.' && Itm
->Value
[1] == '/') ||
131 (Itm
->Value
[0] == '~' && Itm
->Value
[1] == '/')))
134 if (Itm
->Parent
->Value
.end()[-1] == '/')
135 return Itm
->Parent
->Value
+ Itm
->Value
;
137 return Itm
->Parent
->Value
+ '/' + Itm
->Value
;
140 // Configuration::FindDir - Find a directory name /*{{{*/
141 // ---------------------------------------------------------------------
142 /* This is like findfile execept the result is terminated in a / */
143 string
Configuration::FindDir(const char *Name
,const char *Default
)
145 string Res
= FindFile(Name
,Default
);
146 if (Res
.end()[-1] != '/')
151 // Configuration::FindI - Find an integer value /*{{{*/
152 // ---------------------------------------------------------------------
154 int Configuration::FindI(const char *Name
,int Default
)
156 Item
*Itm
= Lookup(Name
,false);
157 if (Itm
== 0 || Itm
->Value
.empty() == true)
161 int Res
= strtol(Itm
->Value
.c_str(),&End
,0);
162 if (End
== Itm
->Value
.c_str())
168 // Configuration::FindB - Find a boolean type /*{{{*/
169 // ---------------------------------------------------------------------
171 bool Configuration::FindB(const char *Name
,bool Default
)
173 Item
*Itm
= Lookup(Name
,false);
174 if (Itm
== 0 || Itm
->Value
.empty() == true)
177 return StringToBool(Itm
->Value
,Default
);
180 // Configuration::Set - Set a value /*{{{*/
181 // ---------------------------------------------------------------------
183 void Configuration::Set(const char *Name
,string Value
)
185 Item
*Itm
= Lookup(Name
,true);
191 // Configuration::Set - Set an integer value /*{{{*/
192 // ---------------------------------------------------------------------
194 void Configuration::Set(const char *Name
,int Value
)
196 Item
*Itm
= Lookup(Name
,true);
200 snprintf(S
,sizeof(S
),"%i",Value
);
204 // Configuration::Exists - Returns true if the Name exists /*{{{*/
205 // ---------------------------------------------------------------------
207 bool Configuration::Exists(const char *Name
)
209 Item
*Itm
= Lookup(Name
,false);
216 // Configuration::Item::FullTag - Return the fully scoped tag /*{{{*/
217 // ---------------------------------------------------------------------
219 string
Configuration::Item::FullTag() const
221 if (Parent
== 0 || Parent
->Parent
== 0)
223 return Parent
->FullTag() + "::" + Tag
;
227 // ReadConfigFile - Read a configuration file /*{{{*/
228 // ---------------------------------------------------------------------
229 /* The configuration format is very much like the named.conf format
230 used in bind8, in fact this routine can parse most named.conf files. */
231 bool ReadConfigFile(Configuration
&Conf
,string FName
)
233 // Open the stream for reading
234 ifstream
F(FName
.c_str(),ios::in
| ios::nocreate
);
236 return _error
->Errno("ifstream::ifstream","Opening configuration file %s",FName
.c_str());
245 bool InComment
= false;
246 while (F
.eof() == false)
248 F
.getline(Buffer
,sizeof(Buffer
));
250 _strtabexpand(Buffer
,sizeof(Buffer
));
253 // Multi line comment
254 if (InComment
== true)
256 for (const char *I
= Buffer
; *I
!= 0; I
++)
258 if (*I
== '*' && I
[1] == '/')
260 memmove(Buffer
,I
+2,strlen(I
+2) + 1);
265 if (InComment
== true)
269 // Discard single line comments
270 for (char *I
= Buffer
; *I
!= 0; I
++)
272 if (*I
== '/' && I
[1] == '/')
279 // Look for multi line comments
280 for (char *I
= Buffer
; *I
!= 0; I
++)
282 if (*I
== '/' && I
[1] == '*')
285 for (char *J
= Buffer
; *J
!= 0; J
++)
287 if (*J
== '*' && J
[1] == '/')
289 memmove(I
,J
+2,strlen(J
+2) + 1);
295 if (InComment
== true)
307 // We now have a valid line fragment
308 for (char *I
= Buffer
; *I
!= 0;)
310 if (*I
== '{' || *I
== ';' || *I
== '}')
312 // Put the last fragement into the buffer
313 char *Start
= Buffer
;
315 for (; Start
!= I
&& isspace(*Start
) != 0; Start
++);
316 for (; Stop
!= Start
&& isspace(Stop
[-1]) != 0; Stop
--);
317 if (LineBuffer
.empty() == false && Stop
- Start
!= 0)
319 LineBuffer
+= string(Start
,Stop
- Start
);
321 // Remove the fragment
323 memmove(Buffer
,I
+ 1,strlen(I
+ 1) + 1);
329 string::size_type Pos
= ParentTag
.rfind("::");
330 if (Pos
== string::npos
)
331 ParentTag
= string();
333 ParentTag
= string(ParentTag
,0,Pos
);
337 if (TermChar
== '{' && LineBuffer
.empty() == true)
338 return _error
->Error("Syntax error %s:%u: Block starts with no name.",FName
.c_str(),CurLine
);
340 if (LineBuffer
.empty() == true)
344 string::size_type Pos
= LineBuffer
.find(' ');
345 if (Pos
== string::npos
)
348 Pos
= LineBuffer
.length();
350 return _error
->Error("Syntax error %s:%u: Tag with no value",FName
.c_str(),CurLine
);
353 string Tag
= string(LineBuffer
,0,Pos
);
358 if (ParentTag
.empty() == true)
361 ParentTag
+= string("::") + Tag
;
365 // We dont have a value to set
366 if (Pos
== LineBuffer
.length())
368 LineBuffer
= string();
372 // Parse off the word
374 if (ParseCWord(LineBuffer
.c_str()+Pos
,Word
) == false)
375 return _error
->Error("Syntax error %s:%u: Malformed value",FName
.c_str(),CurLine
);
377 // Generate the item name
379 if (ParentTag
.empty() == true)
383 if (Tag
.empty() == true)
386 Item
= ParentTag
+ "::" + Tag
;
389 // Set the item in the configuration class
393 LineBuffer
= string();
399 // Store the fragment
400 const char *Stripd
= _strstrip(Buffer
);
401 if (*Stripd
!= 0 && LineBuffer
.empty() == false)
403 LineBuffer
+= Stripd
;