Checkpoint
[ntk/apt.git] / apt-pkg / deb / deblistparser.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: deblistparser.cc,v 1.1 1998/07/04 05:58:08 jgg Exp $
4 /* ######################################################################
5
6 Package Cache Generator - Generator for the cache structure.
7
8 This builds the cache structure from the abstract package list parser.
9
10 ##################################################################### */
11 /*}}}*/
12 // Include Files /*{{{*/
13 #include <pkglib/deblistparser.h>
14 #include <pkglib/error.h>
15 #include <system.h>
16 /*}}}*/
17
18 // ListParser::debListParser - Constructor /*{{{*/
19 // ---------------------------------------------------------------------
20 /* */
21 debListParser::debListParser(File &File) : Tags(File)
22 {
23 Step();
24 }
25 /*}}}*/
26 // ListParser::FindTag - Find the tag and return a string /*{{{*/
27 // ---------------------------------------------------------------------
28 /* */
29 string debListParser::FindTag(const char *Tag)
30 {
31 const char *Start;
32 const char *Stop;
33 if (Section.Find(Tag,Start,Stop) == false)
34 return string();
35 return string(Start,Stop - Start);
36 }
37 /*}}}*/
38 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
39 // ---------------------------------------------------------------------
40 /* */
41 unsigned long debListParser::UniqFindTagWrite(const char *Tag)
42 {
43 const char *Start;
44 const char *Stop;
45 if (Section.Find(Tag,Start,Stop) == false)
46 return 0;
47 return WriteUniqString(Start,Stop - Start);
48 }
49 /*}}}*/
50 // ListParser::HandleFlag - Sets a flag variable based on a tag /*{{{*/
51 // ---------------------------------------------------------------------
52 /* This checks the tag for true/false yes/no etc */
53 bool debListParser::HandleFlag(const char *Tag,unsigned long &Flags,
54 unsigned long Flag)
55 {
56 const char *Start;
57 const char *Stop;
58 if (Section.Find(Tag,Start,Stop) == false)
59 return true;
60
61 int Set = 2;
62 if (strncasecmp(Start,"yes",Stop - Start) == 0)
63 Set = 1;
64 if (strncasecmp(Start,"true",Stop - Start) == 0)
65 Set = 1;
66 if (strncasecmp(Start,"no",Stop - Start) == 0)
67 Set = 0;
68 if (strncasecmp(Start,"false",Stop - Start) == 0)
69 Set = 0;
70 if (Set == 2)
71 {
72 _error->Warning("Unknown flag value");
73 return true;
74 }
75
76 if (Set == 0)
77 Flags &= ~Flag;
78 if (Set == 1)
79 Flags |= Flag;
80 return true;
81 }
82 /*}}}*/
83 // ListParser::Package - Return the package name /*{{{*/
84 // ---------------------------------------------------------------------
85 /* This is to return the name of the package this section describes */
86 string debListParser::Package()
87 {
88 string Result = FindTag("Package");
89 if (Result.empty() == true)
90 _error->Error("Encoutered a section with no Package: header");
91 return Result;
92 }
93 /*}}}*/
94 // ListParser::Version - Return the version string /*{{{*/
95 // ---------------------------------------------------------------------
96 /* This is to return the string describing the version in debian form,
97 epoch:upstream-release. If this returns the blank string then the
98 entry is assumed to only describe package properties */
99 string debListParser::Version()
100 {
101 return FindTag("Version");
102 }
103 /*}}}*/
104 // ListParser::NewPackage - Fill in the package structure /*{{{*/
105 // ---------------------------------------------------------------------
106 /* This is called when a new package structure is created. It must fill
107 in the static package information. */
108 bool debListParser::NewPackage(pkgCache::PkgIterator Pkg)
109 {
110 // Debian doesnt have anything, everything is condionally megered
111 return true;
112 }
113 /*}}}*/
114 // ListParser::NewVersion - Fill in the version structure /*{{{*/
115 // ---------------------------------------------------------------------
116 /* */
117 bool debListParser::NewVersion(pkgCache::VerIterator Ver)
118 {
119 return true;
120 }
121 /*}}}*/
122 // ListParser::UsePackage - Update a package structure /*{{{*/
123 // ---------------------------------------------------------------------
124 /* This is called to update the package with any new information
125 that might be found in the section */
126 bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
127 pkgCache::VerIterator Ver)
128 {
129 if (Pkg->Section == 0)
130 if ((Pkg->Section = UniqFindTagWrite("Section")) == 0)
131 return false;
132 if (HandleFlag("Essential",Pkg->Flags,pkgCache::Essential) == false)
133 return false;
134 if (HandleFlag("Immediate-Configure",Pkg->Flags,pkgCache::ImmediateConf) == false)
135 return false;
136 if (ParseStatus(Pkg,Ver) == false)
137 return false;
138 return true;
139 }
140 /*}}}*/
141 // ListParser::ParseStatus - Parse the status feild /*{{{*/
142 // ---------------------------------------------------------------------
143 /* Status lines are of the form,
144 Status: want flag status
145 want = unknown, install, hold, deinstall, purge
146 flag = ok, reinstreq, hold, hold-reinstreq
147 status = not-installed, unpacked, half-configured, uninstalled,
148 half-installed, config-files, post-inst-failed,
149 removal-failed, installed
150
151 Some of the above are obsolete (I think?) flag = hold-* and
152 status = post-inst-failed, removal-failed at least.
153 */
154 bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
155 pkgCache::VerIterator Ver)
156 {
157 const char *Start;
158 const char *Stop;
159 if (Section.Find("Status",Start,Stop) == false)
160 return true;
161
162 // Isolate the first word
163 const char *I = Start;
164 for(; I < Stop && *I != ' '; I++);
165 if (I >= Stop || *I != ' ')
166 return _error->Error("Malformed Status line");
167
168 // Process the want field
169 WordList WantList[] = {{"unknown",pkgCache::Unknown},
170 {"install",pkgCache::Install},
171 {"hold",pkgCache::Hold},
172 {"deinstall",pkgCache::DeInstall},
173 {"purge",pkgCache::Purge}};
174 if (GrabWord(string(Start,I-Start),WantList,
175 _count(WantList),Pkg->SelectedState) == false)
176 return _error->Error("Malformed 1st word in the Status line");
177
178 // Isloate the next word
179 I++;
180 Start = I;
181 for(; I < Stop && *I != ' '; I++);
182 if (I >= Stop || *I != ' ')
183 return _error->Error("Malformed status line, no 2nd word");
184
185 // Process the flag field
186 WordList FlagList[] = {{"ok",pkgCache::Ok},
187 {"reinstreq",pkgCache::ReInstReq},
188 {"hold",pkgCache::HoldInst},
189 {"hold-reinstreq",pkgCache::HoldReInstReq}};
190 if (GrabWord(string(Start,I-Start),FlagList,
191 _count(FlagList),Pkg->InstState) == false)
192 return _error->Error("Malformed 2nd word in the Status line");
193
194 // Isloate the last word
195 I++;
196 Start = I;
197 for(; I < Stop && *I != ' '; I++);
198 if (I != Stop)
199 return _error->Error("Malformed Status line, no 3rd word");
200
201 // Process the flag field
202 WordList StatusList[] = {{"not-installed",pkgCache::NotInstalled},
203 {"unpacked",pkgCache::UnPacked},
204 {"half-configured",pkgCache::HalfConfigured},
205 {"installed",pkgCache::Installed},
206 {"uninstalled",pkgCache::UnInstalled},
207 {"half-installed",pkgCache::HalfInstalled},
208 {"config-files",pkgCache::ConfigFiles},
209 {"post-inst-failed",pkgCache::HalfConfigured},
210 {"removal-failed",pkgCache::HalfInstalled}};
211 if (GrabWord(string(Start,I-Start),StatusList,
212 _count(StatusList),Pkg->CurrentState) == false)
213 return _error->Error("Malformed 3rd word in the Status line");
214
215 /* A Status line marks the package as indicating the current
216 version as well. Only if it is actually installed.. Otherwise
217 the interesting dpkg handling of the status file creates bogus
218 entries. */
219 if (!(Pkg->CurrentState == pkgCache::NotInstalled ||
220 Pkg->CurrentState == pkgCache::ConfigFiles))
221 {
222 if (Ver.end() == true)
223 _error->Warning("Encountered status field in a non-version description");
224 else
225 Pkg->CurrentVer = Ver.Index();
226 }
227
228 return true;
229 }
230 /*}}}*/
231 // ListParser::GrabWord - Matches a word and returns /*{{{*/
232 // ---------------------------------------------------------------------
233 /* Looks for a word in a list of words - for ParseStatus */
234 bool debListParser::GrabWord(string Word,WordList *List,int Count,
235 unsigned char &Out)
236 {
237 for (int C = 0; C != Count; C++)
238 {
239 if (strcasecmp(Word.c_str(),List[C].Str) == 0)
240 {
241 Out = List[C].Val;
242 return true;
243 }
244 }
245 return false;
246 }
247 /*}}}*/
248 // ListParser::Step - Move to the next section in the file /*{{{*/
249 // ---------------------------------------------------------------------
250 /* */
251 bool debListParser::Step()
252 {
253 return Tags.Step(Section);
254 }
255 /*}}}*/