]>
git.saurik.com Git - apt.git/blob - apt-pkg/deb/deblistparser.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: deblistparser.cc,v 1.29.2.5 2004/01/06 01:43:44 mdz 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>
16 #include <apt-pkg/aptconfiguration.h>
17 #include <apt-pkg/strutl.h>
18 #include <apt-pkg/crc-16.h>
19 #include <apt-pkg/md5.h>
20 #include <apt-pkg/macros.h>
26 static debListParser::WordList PrioList
[] = {{"important",pkgCache::State::Important
},
27 {"required",pkgCache::State::Required
},
28 {"standard",pkgCache::State::Standard
},
29 {"optional",pkgCache::State::Optional
},
30 {"extra",pkgCache::State::Extra
},
33 // ListParser::debListParser - Constructor /*{{{*/
34 // ---------------------------------------------------------------------
35 /* Provide an architecture and only this one and "all" will be accepted
36 in Step(), if no Architecture is given we will accept every arch
37 we would accept in general with checkArchitecture() */
38 debListParser::debListParser(FileFd
*File
, string
const &Arch
) : Tags(File
),
41 this->Arch
= _config
->Find("APT::Architecture");
42 Architectures
= APT::Configuration::getArchitectures();
43 MultiArchEnabled
= Architectures
.size() > 1;
46 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
47 // ---------------------------------------------------------------------
49 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
53 if (Section
.Find(Tag
,Start
,Stop
) == false)
55 return WriteUniqString(Start
,Stop
- Start
);
58 // ListParser::Package - Return the package name /*{{{*/
59 // ---------------------------------------------------------------------
60 /* This is to return the name of the package this section describes */
61 string
debListParser::Package() {
62 string
const Result
= Section
.FindS("Package");
63 if(unlikely(Result
.empty() == true))
64 _error
->Error("Encountered a section with no Package: header");
68 // ListParser::Architecture - Return the package arch /*{{{*/
69 // ---------------------------------------------------------------------
70 /* This will return the Architecture of the package this section describes */
71 string
debListParser::Architecture() {
72 std::string
const Arch
= Section
.FindS("Architecture");
73 if (Arch
.empty() == true)
74 return _config
->Find("APT::Architecture");
78 // ListParser::ArchitectureAll /*{{{*/
79 // ---------------------------------------------------------------------
81 bool debListParser::ArchitectureAll() {
82 return Section
.FindS("Architecture") == "all";
85 // ListParser::Version - Return the version string /*{{{*/
86 // ---------------------------------------------------------------------
87 /* This is to return the string describing the version in debian form,
88 epoch:upstream-release. If this returns the blank string then the
89 entry is assumed to only describe package properties */
90 string
debListParser::Version()
92 return Section
.FindS("Version");
95 // ListParser::NewVersion - Fill in the version structure /*{{{*/
96 // ---------------------------------------------------------------------
98 bool debListParser::NewVersion(pkgCache::VerIterator
&Ver
)
101 Ver
->Section
= UniqFindTagWrite("Section");
104 string
const MultiArch
= Section
.FindS("Multi-Arch");
105 if (MultiArch
.empty() == true)
106 Ver
->MultiArch
= pkgCache::Version::None
;
107 else if (MultiArch
== "same") {
109 if (Section
.FindS("Architecture") == "all")
111 /* Arch all packages can't be Multi-Arch: same */
112 _error
->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
113 Section
.FindS("Package").c_str());
114 Ver
->MultiArch
= pkgCache::Version::None
;
117 Ver
->MultiArch
= pkgCache::Version::Same
;
119 else if (MultiArch
== "foreign")
120 Ver
->MultiArch
= pkgCache::Version::Foreign
;
121 else if (MultiArch
== "allowed")
122 Ver
->MultiArch
= pkgCache::Version::Allowed
;
125 _error
->Warning("Unknown Multi-Arch type '%s' for package '%s'",
126 MultiArch
.c_str(), Section
.FindS("Package").c_str());
127 Ver
->MultiArch
= pkgCache::Version::None
;
131 Ver
->Size
= Section
.FindULL("Size");
132 // Unpacked Size (in K)
133 Ver
->InstalledSize
= Section
.FindULL("Installed-Size");
134 Ver
->InstalledSize
*= 1024;
139 if (Section
.Find("Priority",Start
,Stop
) == true)
141 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,Ver
->Priority
) == false)
142 Ver
->Priority
= pkgCache::State::Extra
;
145 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
147 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
149 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
151 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
153 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
155 if (ParseDepends(Ver
,"Breaks",pkgCache::Dep::DpkgBreaks
) == false)
157 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
159 if (ParseDepends(Ver
,"Enhances",pkgCache::Dep::Enhances
) == false)
163 if (ParseDepends(Ver
,"Optional",pkgCache::Dep::Suggests
) == false)
166 if (ParseProvides(Ver
) == false)
172 // ListParser::Description - Return the description string /*{{{*/
173 // ---------------------------------------------------------------------
174 /* This is to return the string describing the package in debian
175 form. If this returns the blank string then the entry is assumed to
176 only describe package properties */
177 string
debListParser::Description()
179 string
const lang
= DescriptionLanguage();
181 return Section
.FindS("Description");
183 return Section
.FindS(string("Description-").append(lang
).c_str());
186 // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
187 // ---------------------------------------------------------------------
188 /* This is to return the string describing the language of
189 description. If this returns the blank string then the entry is
190 assumed to describe original description. */
191 string
debListParser::DescriptionLanguage()
193 if (Section
.FindS("Description").empty() == false)
196 std::vector
<string
> const lang
= APT::Configuration::getLanguages();
197 for (std::vector
<string
>::const_iterator l
= lang
.begin();
198 l
!= lang
.end(); l
++)
199 if (Section
.FindS(string("Description-").append(*l
).c_str()).empty() == false)
205 // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
206 // ---------------------------------------------------------------------
207 /* This is to return the md5 string to allow the check if it is the right
208 description. If no Description-md5 is found in the section it will be
211 MD5SumValue
debListParser::Description_md5()
213 string value
= Section
.FindS("Description-md5");
218 md5
.Add((Description() + "\n").c_str());
221 return MD5SumValue(value
);
224 // ListParser::UsePackage - Update a package structure /*{{{*/
225 // ---------------------------------------------------------------------
226 /* This is called to update the package with any new information
227 that might be found in the section */
228 bool debListParser::UsePackage(pkgCache::PkgIterator
&Pkg
,
229 pkgCache::VerIterator
&Ver
)
231 if (Pkg
->Section
== 0)
232 Pkg
->Section
= UniqFindTagWrite("Section");
234 // Packages which are not from the "native" arch doesn't get the essential flag
235 // in the default "native" mode - it is also possible to mark "all" or "none".
236 // The "installed" mode is handled by ParseStatus(), See #544481 and friends.
237 string
const static myArch
= _config
->Find("APT::Architecture");
238 string
const static essential
= _config
->Find("pkgCacheGen::Essential", "native");
239 if ((essential
== "native" && Pkg
->Arch
!= 0 && myArch
== Pkg
.Arch()) ||
241 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
243 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
246 if (strcmp(Pkg
.Name(),"apt") == 0)
247 Pkg
->Flags
|= pkgCache::Flag::Important
;
249 if (ParseStatus(Pkg
,Ver
) == false)
254 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
255 // ---------------------------------------------------------------------
257 unsigned short debListParser::VersionHash()
259 const char *Sections
[] ={"Installed-Size",
267 unsigned long Result
= INIT_FCS
;
269 for (const char **I
= Sections
; *I
!= 0; I
++)
273 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
276 /* Strip out any spaces from the text, this undoes dpkgs reformatting
277 of certain fields. dpkg also has the rather interesting notion of
278 reformatting depends operators < -> <= */
280 for (; Start
!= End
; Start
++)
282 if (isspace(*Start
) == 0)
283 *I
++ = tolower_ascii(*Start
);
284 if (*Start
== '<' && Start
[1] != '<' && Start
[1] != '=')
286 if (*Start
== '>' && Start
[1] != '>' && Start
[1] != '=')
290 Result
= AddCRC16(Result
,S
,I
- S
);
296 // ListParser::ParseStatus - Parse the status field /*{{{*/
297 // ---------------------------------------------------------------------
298 /* Status lines are of the form,
299 Status: want flag status
300 want = unknown, install, hold, deinstall, purge
301 flag = ok, reinstreq, hold, hold-reinstreq
302 status = not-installed, unpacked, half-configured,
303 half-installed, config-files, post-inst-failed,
304 removal-failed, installed
306 Some of the above are obsolete (I think?) flag = hold-* and
307 status = post-inst-failed, removal-failed at least.
309 bool debListParser::ParseStatus(pkgCache::PkgIterator
&Pkg
,
310 pkgCache::VerIterator
&Ver
)
314 if (Section
.Find("Status",Start
,Stop
) == false)
317 // UsePackage() is responsible for setting the flag in the default case
318 bool const static essential
= _config
->Find("pkgCacheGen::Essential", "") == "installed";
319 if (essential
== true &&
320 Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
323 // Isolate the first word
324 const char *I
= Start
;
325 for(; I
< Stop
&& *I
!= ' '; I
++);
326 if (I
>= Stop
|| *I
!= ' ')
327 return _error
->Error("Malformed Status line");
329 // Process the want field
330 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
331 {"install",pkgCache::State::Install
},
332 {"hold",pkgCache::State::Hold
},
333 {"deinstall",pkgCache::State::DeInstall
},
334 {"purge",pkgCache::State::Purge
},
336 if (GrabWord(string(Start
,I
-Start
),WantList
,Pkg
->SelectedState
) == false)
337 return _error
->Error("Malformed 1st word in the Status line");
339 // Isloate the next word
342 for(; I
< Stop
&& *I
!= ' '; I
++);
343 if (I
>= Stop
|| *I
!= ' ')
344 return _error
->Error("Malformed status line, no 2nd word");
346 // Process the flag field
347 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
348 {"reinstreq",pkgCache::State::ReInstReq
},
349 {"hold",pkgCache::State::HoldInst
},
350 {"hold-reinstreq",pkgCache::State::HoldReInstReq
},
352 if (GrabWord(string(Start
,I
-Start
),FlagList
,Pkg
->InstState
) == false)
353 return _error
->Error("Malformed 2nd word in the Status line");
355 // Isloate the last word
358 for(; I
< Stop
&& *I
!= ' '; I
++);
360 return _error
->Error("Malformed Status line, no 3rd word");
362 // Process the flag field
363 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
364 {"unpacked",pkgCache::State::UnPacked
},
365 {"half-configured",pkgCache::State::HalfConfigured
},
366 {"installed",pkgCache::State::Installed
},
367 {"half-installed",pkgCache::State::HalfInstalled
},
368 {"config-files",pkgCache::State::ConfigFiles
},
369 {"triggers-awaited",pkgCache::State::TriggersAwaited
},
370 {"triggers-pending",pkgCache::State::TriggersPending
},
371 {"post-inst-failed",pkgCache::State::HalfConfigured
},
372 {"removal-failed",pkgCache::State::HalfInstalled
},
374 if (GrabWord(string(Start
,I
-Start
),StatusList
,Pkg
->CurrentState
) == false)
375 return _error
->Error("Malformed 3rd word in the Status line");
377 /* A Status line marks the package as indicating the current
378 version as well. Only if it is actually installed.. Otherwise
379 the interesting dpkg handling of the status file creates bogus
381 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
382 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
384 if (Ver
.end() == true)
385 _error
->Warning("Encountered status field in a non-version description");
387 Pkg
->CurrentVer
= Ver
.Index();
393 const char *debListParser::ConvertRelation(const char *I
,unsigned int &Op
)
395 // Determine the operator
403 Op
= pkgCache::Dep::LessEq
;
410 Op
= pkgCache::Dep::Less
;
414 // < is the same as <= and << is really Cs < for some reason
415 Op
= pkgCache::Dep::LessEq
;
423 Op
= pkgCache::Dep::GreaterEq
;
430 Op
= pkgCache::Dep::Greater
;
434 // > is the same as >= and >> is really Cs > for some reason
435 Op
= pkgCache::Dep::GreaterEq
;
439 Op
= pkgCache::Dep::Equals
;
443 // HACK around bad package definitions
445 Op
= pkgCache::Dep::Equals
;
454 * The complete architecture, consisting of <kernel>-<cpu>.
456 static string
CompleteArch(std::string
& arch
) {
457 if (arch
== "armel") return "linux-arm";
458 if (arch
== "armhf") return "linux-arm";
459 if (arch
== "lpia") return "linux-i386";
460 if (arch
== "powerpcspe") return "linux-powerpc";
461 if (arch
== "uclibc-linux-armel") return "linux-arm";
462 if (arch
== "uclinux-armel") return "uclinux-arm";
464 return (arch
.find("-") != string::npos
) ? arch
: "linux-" + arch
;
467 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
468 // ---------------------------------------------------------------------
469 /* This parses the dependency elements out of a standard string in place,
471 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
472 string
&Package
,string
&Ver
,
473 unsigned int &Op
, bool const &ParseArchFlags
,
474 bool const &StripMultiArch
)
476 // Strip off leading space
477 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
479 // Parse off the package name
480 const char *I
= Start
;
481 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
482 *I
!= ',' && *I
!= '|'; I
++);
485 if (I
!= Stop
&& *I
== ')')
491 // Stash the package name
492 Package
.assign(Start
,I
- Start
);
494 // We don't want to confuse library users which can't handle MultiArch
495 if (StripMultiArch
== true) {
496 size_t const found
= Package
.rfind(':');
497 if (found
!= string::npos
)
498 Package
= Package
.substr(0,found
);
501 // Skip white space to the '('
502 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
505 if (I
!= Stop
&& *I
== '(')
508 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
511 I
= ConvertRelation(I
,Op
);
514 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
516 for (;I
!= Stop
&& *I
!= ')'; I
++);
517 if (I
== Stop
|| Start
== I
)
520 // Skip trailing whitespace
522 for (; End
> Start
&& isspace(End
[-1]); End
--);
524 Ver
.assign(Start
,End
-Start
);
530 Op
= pkgCache::Dep::NoOp
;
534 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
536 if (ParseArchFlags
== true)
538 string arch
= _config
->Find("APT::Architecture");
539 string completeArch
= CompleteArch(arch
);
541 // Parse an architecture
542 if (I
!= Stop
&& *I
== '[')
551 bool NegArch
= false;
554 // look for whitespace or ending ']'
555 while (End
!= Stop
&& !isspace(*End
) && *End
!= ']')
567 if (stringcmp(arch
,I
,End
) == 0) {
570 std::string wildcard
= SubstVar(string(I
, End
), "any", "*");
571 if (fnmatch(wildcard
.c_str(), completeArch
.c_str(), 0) == 0)
581 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
588 Package
= ""; /* not for this arch */
592 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
595 if (I
!= Stop
&& *I
== '|')
596 Op
|= pkgCache::Dep::Or
;
598 if (I
== Stop
|| *I
== ',' || *I
== '|')
601 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
608 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
609 // ---------------------------------------------------------------------
610 /* This is the higher level depends parser. It takes a tag and generates
611 a complete depends tree for the given version. */
612 bool debListParser::ParseDepends(pkgCache::VerIterator
&Ver
,
613 const char *Tag
,unsigned int Type
)
617 if (Section
.Find(Tag
,Start
,Stop
) == false)
621 string
const pkgArch
= Ver
.Arch();
627 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
629 return _error
->Error("Problem parsing dependency %s",Tag
);
631 if (MultiArchEnabled
== true &&
632 (Type
== pkgCache::Dep::Conflicts
||
633 Type
== pkgCache::Dep::DpkgBreaks
||
634 Type
== pkgCache::Dep::Replaces
))
636 for (std::vector
<std::string
>::const_iterator a
= Architectures
.begin();
637 a
!= Architectures
.end(); ++a
)
638 if (NewDepends(Ver
,Package
,*a
,Version
,Op
,Type
) == false)
641 else if (NewDepends(Ver
,Package
,pkgArch
,Version
,Op
,Type
) == false)
649 // ListParser::ParseProvides - Parse the provides list /*{{{*/
650 // ---------------------------------------------------------------------
652 bool debListParser::ParseProvides(pkgCache::VerIterator
&Ver
)
656 if (Section
.Find("Provides",Start
,Stop
) == true)
660 string
const Arch
= Ver
.Arch();
665 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
667 return _error
->Error("Problem parsing Provides line");
668 if (Op
!= pkgCache::Dep::NoOp
) {
669 _error
->Warning("Ignoring Provides line with DepCompareOp for package %s", Package
.c_str());
671 if (NewProvides(Ver
, Package
, Arch
, Version
) == false)
680 if (Ver
->MultiArch
== pkgCache::Version::Allowed
)
682 string
const Package
= string(Ver
.ParentPkg().Name()).append(":").append("any");
683 NewProvides(Ver
, Package
, "any", Ver
.VerStr());
686 if (Ver
->MultiArch
!= pkgCache::Version::Foreign
)
689 if (MultiArchEnabled
== false)
692 string
const Package
= Ver
.ParentPkg().Name();
693 string
const Version
= Ver
.VerStr();
694 for (std::vector
<string
>::const_iterator a
= Architectures
.begin();
695 a
!= Architectures
.end(); ++a
)
697 if (NewProvides(Ver
, Package
, *a
, Version
) == false)
704 // ListParser::GrabWord - Matches a word and returns /*{{{*/
705 // ---------------------------------------------------------------------
706 /* Looks for a word in a list of words - for ParseStatus */
707 bool debListParser::GrabWord(string Word
,WordList
*List
,unsigned char &Out
)
709 for (unsigned int C
= 0; List
[C
].Str
!= 0; C
++)
711 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
720 // ListParser::Step - Move to the next section in the file /*{{{*/
721 // ---------------------------------------------------------------------
722 /* This has to be carefull to only process the correct architecture */
723 bool debListParser::Step()
725 iOffset
= Tags
.Offset();
726 while (Tags
.Step(Section
) == true)
728 /* See if this is the correct Architecture, if it isn't then we
729 drop the whole section. A missing arch tag only happens (in theory)
730 inside the Status file, so that is a positive return */
731 string
const Architecture
= Section
.FindS("Architecture");
732 if (Architecture
.empty() == true)
735 if (Arch
.empty() == true || Arch
== "any" || MultiArchEnabled
== false)
737 if (APT::Configuration::checkArchitecture(Architecture
) == true)
742 if (Architecture
== Arch
)
745 if (Architecture
== "all" && Arch
== _config
->Find("APT::Architecture"))
749 iOffset
= Tags
.Offset();
754 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
755 // ---------------------------------------------------------------------
757 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator
&FileI
,
758 FileFd
&File
, string component
)
760 // apt-secure does no longer download individual (per-section) Release
761 // file. to provide Component pinning we use the section name now
762 FileI
->Component
= WriteUniqString(component
);
764 FILE* release
= fdopen(dup(File
.Fd()), "r");
769 bool gpgClose
= false;
770 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
775 for (; buffer
[len
] == '\r' && buffer
[len
] == '\n'; ++len
);
776 if (buffer
[len
] == '\0')
779 // only evalute the first GPG section
780 if (strncmp("-----", buffer
, 5) == 0)
782 if (gpgClose
== true)
788 // seperate the tag from the data
789 for (; buffer
[len
] != ':' && buffer
[len
] != '\0'; ++len
);
790 if (buffer
[len
] == '\0')
792 char* dataStart
= buffer
+ len
;
793 for (++dataStart
; *dataStart
== ' '; ++dataStart
);
794 char* dataEnd
= dataStart
;
795 for (++dataEnd
; *dataEnd
!= '\0'; ++dataEnd
);
797 // which datastorage need to be updated
798 map_ptrloc
* writeTo
= NULL
;
799 if (buffer
[0] == ' ')
801 #define APT_PARSER_WRITETO(X, Y) else if (strncmp(Y, buffer, len) == 0) writeTo = &X;
802 APT_PARSER_WRITETO(FileI
->Archive
, "Suite")
803 APT_PARSER_WRITETO(FileI
->Component
, "Component")
804 APT_PARSER_WRITETO(FileI
->Version
, "Version")
805 APT_PARSER_WRITETO(FileI
->Origin
, "Origin")
806 APT_PARSER_WRITETO(FileI
->Codename
, "Codename")
807 APT_PARSER_WRITETO(FileI
->Label
, "Label")
808 #undef APT_PARSER_WRITETO
809 #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
810 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, dataEnd-1);
811 APT_PARSER_FLAGIT(NotAutomatic
)
812 APT_PARSER_FLAGIT(ButAutomaticUpgrades
)
813 #undef APT_PARSER_FLAGIT
815 // load all data from the line and save it
818 data
.append(dataStart
, dataEnd
);
819 if (sizeof(buffer
) - 1 == (dataEnd
- buffer
))
821 while (fgets(buffer
, sizeof(buffer
), release
) != NULL
)
825 if (strlen(buffer
) != sizeof(buffer
) - 1)
831 // remove spaces and stuff from the end of the data line
832 for (std::string::reverse_iterator s
= data
.rbegin();
833 s
!= data
.rend(); ++s
)
835 if (*s
!= '\r' && *s
!= '\n' && *s
!= ' ')
839 *writeTo
= WriteUniqString(data
);
844 return !_error
->PendingError();
847 // ListParser::GetPrio - Convert the priority from a string /*{{{*/
848 // ---------------------------------------------------------------------
850 unsigned char debListParser::GetPrio(string Str
)
853 if (GrabWord(Str
,PrioList
,Out
) == false)
854 Out
= pkgCache::State::Extra
;