]>
git.saurik.com Git - apt.git/blob - apt-pkg/deb/deblistparser.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: deblistparser.cc,v 1.13 1998/12/14 08:07:29 jgg Exp $
4 /* ######################################################################
6 Package Cache Generator - Generator for the cache structure.
8 This builds the cache structure from the abstract package list parser.
10 ##################################################################### */
12 // Include Files /*{{{*/
13 #include <apt-pkg/deblistparser.h>
14 #include <apt-pkg/error.h>
15 #include <apt-pkg/configuration.h>
21 // ListParser::debListParser - Constructor /*{{{*/
22 // ---------------------------------------------------------------------
24 debListParser::debListParser(FileFd
&File
) : Tags(File
)
28 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
29 // ---------------------------------------------------------------------
31 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
35 if (Section
.Find(Tag
,Start
,Stop
) == false)
37 return WriteUniqString(Start
,Stop
- Start
);
40 // ListParser::Package - Return the package name /*{{{*/
41 // ---------------------------------------------------------------------
42 /* This is to return the name of the package this section describes */
43 string
debListParser::Package()
45 string Result
= Section
.FindS("Package");
46 if (Result
.empty() == true)
47 _error
->Error("Encoutered a section with no Package: header");
51 // ListParser::Version - Return the version string /*{{{*/
52 // ---------------------------------------------------------------------
53 /* This is to return the string describing the version in debian form,
54 epoch:upstream-release. If this returns the blank string then the
55 entry is assumed to only describe package properties */
56 string
debListParser::Version()
58 return Section
.FindS("Version");
61 // ListParser::NewVersion - Fill in the version structure /*{{{*/
62 // ---------------------------------------------------------------------
64 bool debListParser::NewVersion(pkgCache::VerIterator Ver
)
67 Ver
->Section
= UniqFindTagWrite("Section");
70 Ver
->Size
= (unsigned)Section
.FindI("Size");
72 // Unpacked Size (in K)
73 Ver
->InstalledSize
= (unsigned)Section
.FindI("Installed-Size");
74 Ver
->InstalledSize
*= 1024;
79 if (Section
.Find("Priority",Start
,Stop
) == true)
81 WordList PrioList
[] = {{"important",pkgCache::State::Important
},
82 {"required",pkgCache::State::Required
},
83 {"standard",pkgCache::State::Standard
},
84 {"optional",pkgCache::State::Optional
},
85 {"extra",pkgCache::State::Extra
}};
86 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,
87 _count(PrioList
),Ver
->Priority
) == false)
88 return _error
->Error("Malformed Priority line");
91 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
93 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
95 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
97 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
99 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
101 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
104 if (ParseProvides(Ver
) == false)
110 // ListParser::UsePackage - Update a package structure /*{{{*/
111 // ---------------------------------------------------------------------
112 /* This is called to update the package with any new information
113 that might be found in the section */
114 bool debListParser::UsePackage(pkgCache::PkgIterator Pkg
,
115 pkgCache::VerIterator Ver
)
117 if (Pkg
->Section
== 0)
118 Pkg
->Section
= UniqFindTagWrite("Section");
119 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
121 if (Section
.FindFlag("Immediate-Configure",Pkg
->Flags
,pkgCache::Flag::ImmediateConf
) == false)
123 if (ParseStatus(Pkg
,Ver
) == false)
128 // ListParser::ParseStatus - Parse the status field /*{{{*/
129 // ---------------------------------------------------------------------
130 /* Status lines are of the form,
131 Status: want flag status
132 want = unknown, install, hold, deinstall, purge
133 flag = ok, reinstreq, hold, hold-reinstreq
134 status = not-installed, unpacked, half-configured, uninstalled,
135 half-installed, config-files, post-inst-failed,
136 removal-failed, installed
138 Some of the above are obsolete (I think?) flag = hold-* and
139 status = post-inst-failed, removal-failed at least.
141 bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg
,
142 pkgCache::VerIterator Ver
)
146 if (Section
.Find("Status",Start
,Stop
) == false)
149 // Isolate the first word
150 const char *I
= Start
;
151 for(; I
< Stop
&& *I
!= ' '; I
++);
152 if (I
>= Stop
|| *I
!= ' ')
153 return _error
->Error("Malformed Status line");
155 // Process the want field
156 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
157 {"install",pkgCache::State::Install
},
158 {"hold",pkgCache::State::Hold
},
159 {"deinstall",pkgCache::State::DeInstall
},
160 {"purge",pkgCache::State::Purge
}};
161 if (GrabWord(string(Start
,I
-Start
),WantList
,
162 _count(WantList
),Pkg
->SelectedState
) == false)
163 return _error
->Error("Malformed 1st word in the Status line");
165 // Isloate the next word
168 for(; I
< Stop
&& *I
!= ' '; I
++);
169 if (I
>= Stop
|| *I
!= ' ')
170 return _error
->Error("Malformed status line, no 2nd word");
172 // Process the flag field
173 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
174 {"reinstreq",pkgCache::State::ReInstReq
},
175 {"hold",pkgCache::State::HoldInst
},
176 {"hold-reinstreq",pkgCache::State::HoldReInstReq
}};
177 if (GrabWord(string(Start
,I
-Start
),FlagList
,
178 _count(FlagList
),Pkg
->InstState
) == false)
179 return _error
->Error("Malformed 2nd word in the Status line");
181 // Isloate the last word
184 for(; I
< Stop
&& *I
!= ' '; I
++);
186 return _error
->Error("Malformed Status line, no 3rd word");
188 // Process the flag field
189 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
190 {"unpacked",pkgCache::State::UnPacked
},
191 {"half-configured",pkgCache::State::HalfConfigured
},
192 {"installed",pkgCache::State::Installed
},
193 {"uninstalled",pkgCache::State::UnInstalled
},
194 {"half-installed",pkgCache::State::HalfInstalled
},
195 {"config-files",pkgCache::State::ConfigFiles
},
196 {"post-inst-failed",pkgCache::State::HalfConfigured
},
197 {"removal-failed",pkgCache::State::HalfInstalled
}};
198 if (GrabWord(string(Start
,I
-Start
),StatusList
,
199 _count(StatusList
),Pkg
->CurrentState
) == false)
200 return _error
->Error("Malformed 3rd word in the Status line");
202 /* A Status line marks the package as indicating the current
203 version as well. Only if it is actually installed.. Otherwise
204 the interesting dpkg handling of the status file creates bogus
206 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
207 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
209 if (Ver
.end() == true)
210 _error
->Warning("Encountered status field in a non-version description");
212 Pkg
->CurrentVer
= Ver
.Index();
218 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
219 // ---------------------------------------------------------------------
220 /* This parses the dependency elements out of a standard string in place,
222 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
223 string
&Package
,string
&Ver
,
226 // Strip off leading space
227 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
229 // Parse off the package name
230 const char *I
= Start
;
231 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
232 *I
!= ',' && *I
!= '|'; I
++);
235 if (I
!= Stop
&& *I
== ')')
241 // Stash the package name
242 Package
.assign(Start
,I
- Start
);
244 // Skip white space to the '('
245 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
248 if (I
!= Stop
&& *I
== '(')
251 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
255 // Determine the operator
263 Op
= pkgCache::Dep::LessEq
;
270 Op
= pkgCache::Dep::Less
;
274 // < is the same as <= and << is really Cs < for some reason
275 Op
= pkgCache::Dep::LessEq
;
283 Op
= pkgCache::Dep::GreaterEq
;
290 Op
= pkgCache::Dep::Greater
;
294 // > is the same as >= and >> is really Cs > for some reason
295 Op
= pkgCache::Dep::GreaterEq
;
299 Op
= pkgCache::Dep::Equals
;
303 // HACK around bad package definitions
305 Op
= pkgCache::Dep::Equals
;
310 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
312 for (;I
!= Stop
&& *I
!= ')'; I
++);
313 if (I
== Stop
|| Start
== I
)
316 Ver
= string(Start
,I
-Start
);
322 Op
= pkgCache::Dep::NoOp
;
326 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
327 if (I
!= Stop
&& *I
== '|')
328 Op
|= pkgCache::Dep::Or
;
330 if (I
== Stop
|| *I
== ',' || *I
== '|')
333 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
340 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
341 // ---------------------------------------------------------------------
342 /* This is the higher level depends parser. It takes a tag and generates
343 a complete depends tree for the given version. */
344 bool debListParser::ParseDepends(pkgCache::VerIterator Ver
,
345 const char *Tag
,unsigned int Type
)
349 if (Section
.Find(Tag
,Start
,Stop
) == false)
358 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
360 return _error
->Error("Problem parsing dependency %s",Tag
);
362 if (NewDepends(Ver
,Package
,Version
,Op
,Type
) == false)
370 // ListParser::ParseProvides - Parse the provides list /*{{{*/
371 // ---------------------------------------------------------------------
373 bool debListParser::ParseProvides(pkgCache::VerIterator Ver
)
377 if (Section
.Find("Provides",Start
,Stop
) == false)
386 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
388 return _error
->Error("Problem parsing Provides line");
389 if (Op
!= pkgCache::Dep::NoOp
)
390 return _error
->Error("Malformed provides line");
392 if (NewProvides(Ver
,Package
,Version
) == false)
402 // ListParser::GrabWord - Matches a word and returns /*{{{*/
403 // ---------------------------------------------------------------------
404 /* Looks for a word in a list of words - for ParseStatus */
405 bool debListParser::GrabWord(string Word
,WordList
*List
,int Count
,
408 for (int C
= 0; C
!= Count
; C
++)
410 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
419 // ListParser::Step - Move to the next section in the file /*{{{*/
420 // ---------------------------------------------------------------------
421 /* This has to be carefull to only process the correct architecture */
422 bool debListParser::Step()
424 iOffset
= Tags
.Offset();
425 string Arch
= _config
->Find("APT::architecture");
426 while (Tags
.Step(Section
) == true)
428 /* See if this is the correct Architecture, if it isnt then we
429 drop the whole section */
432 if (Section
.Find("Architecture",Start
,Stop
) == false)
435 if (stringcmp(Start
,Stop
,Arch
.begin(),Arch
.end()) == 0)
438 if (stringcmp(Start
,Stop
,"all") == 0)
441 iOffset
= Tags
.Offset();
446 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
447 // ---------------------------------------------------------------------
449 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI
,
452 pkgTagFile
Tags(File
);
453 pkgTagSection Section
;
454 if (Tags
.Step(Section
) == false)
459 if (Section
.Find("Archive",Start
,Stop
) == true)
460 FileI
->Archive
= WriteUniqString(Start
,Stop
- Start
);
461 if (Section
.Find("Component",Start
,Stop
) == true)
462 FileI
->Component
= WriteUniqString(Start
,Stop
- Start
);
463 if (Section
.Find("Version",Start
,Stop
) == true)
464 FileI
->Version
= WriteUniqString(Start
,Stop
- Start
);
465 if (Section
.Find("Origin",Start
,Stop
) == true)
466 FileI
->Origin
= WriteUniqString(Start
,Stop
- Start
);
467 if (Section
.Find("Label",Start
,Stop
) == true)
468 FileI
->Label
= WriteUniqString(Start
,Stop
- Start
);
469 if (Section
.Find("Architecture",Start
,Stop
) == true)
470 FileI
->Architecture
= WriteUniqString(Start
,Stop
- Start
);
472 if (Section
.FindFlag("NotAutomatic",FileI
->Flags
,
473 pkgCache::Flag::NotAutomatic
) == false)
474 _error
->Warning("Bad NotAutomatic flag");
476 return !_error
->PendingError();