* merged from sha256 branch
[ntk/apt.git] / apt-pkg / deb / deblistparser.cc
CommitLineData
f55a958f
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
b3d44315 3// $Id: deblistparser.cc,v 1.29.2.5 2004/01/06 01:43:44 mdz Exp $
f55a958f
AL
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 /*{{{*/
094a497d
AL
13#include <apt-pkg/deblistparser.h>
14#include <apt-pkg/error.h>
15#include <apt-pkg/configuration.h>
cdcc6d34 16#include <apt-pkg/strutl.h>
204fbdcc 17#include <apt-pkg/crc-16.h>
a52f938b 18#include <apt-pkg/md5.h>
9c14e3d6 19
e7b470ee
AL
20#include <ctype.h>
21
f55a958f
AL
22#include <system.h>
23 /*}}}*/
24
b2e465d6
AL
25static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Important},
26 {"required",pkgCache::State::Required},
27 {"standard",pkgCache::State::Standard},
28 {"optional",pkgCache::State::Optional},
29 {"extra",pkgCache::State::Extra},
30 {}};
31
f55a958f
AL
32// ListParser::debListParser - Constructor /*{{{*/
33// ---------------------------------------------------------------------
34/* */
b2e465d6 35debListParser::debListParser(FileFd *File) : Tags(File)
f55a958f 36{
ddc1d8d0 37 Arch = _config->Find("APT::architecture");
0149949b
AL
38}
39 /*}}}*/
f55a958f
AL
40// ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
41// ---------------------------------------------------------------------
42/* */
43unsigned long debListParser::UniqFindTagWrite(const char *Tag)
44{
45 const char *Start;
46 const char *Stop;
47 if (Section.Find(Tag,Start,Stop) == false)
48 return 0;
49 return WriteUniqString(Start,Stop - Start);
50}
51 /*}}}*/
f55a958f
AL
52// ListParser::Package - Return the package name /*{{{*/
53// ---------------------------------------------------------------------
54/* This is to return the name of the package this section describes */
55string debListParser::Package()
56{
b0b4efb9 57 string Result = Section.FindS("Package");
f55a958f 58 if (Result.empty() == true)
65a1e968 59 _error->Error("Encountered a section with no Package: header");
f55a958f
AL
60 return Result;
61}
62 /*}}}*/
63// ListParser::Version - Return the version string /*{{{*/
64// ---------------------------------------------------------------------
65/* This is to return the string describing the version in debian form,
66 epoch:upstream-release. If this returns the blank string then the
67 entry is assumed to only describe package properties */
68string debListParser::Version()
69{
b0b4efb9 70 return Section.FindS("Version");
f55a958f
AL
71}
72 /*}}}*/
f55a958f
AL
73// ListParser::NewVersion - Fill in the version structure /*{{{*/
74// ---------------------------------------------------------------------
75/* */
76bool debListParser::NewVersion(pkgCache::VerIterator Ver)
0149949b
AL
77{
78 // Parse the section
b35d2f5f 79 Ver->Section = UniqFindTagWrite("Section");
17caf1b1 80 Ver->Arch = UniqFindTagWrite("Architecture");
0149949b
AL
81
82 // Archive Size
b0b4efb9 83 Ver->Size = (unsigned)Section.FindI("Size");
0149949b
AL
84
85 // Unpacked Size (in K)
b0b4efb9 86 Ver->InstalledSize = (unsigned)Section.FindI("Installed-Size");
0149949b
AL
87 Ver->InstalledSize *= 1024;
88
89 // Priority
90 const char *Start;
91 const char *Stop;
92 if (Section.Find("Priority",Start,Stop) == true)
b2e465d6
AL
93 {
94 if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
421c8d10 95 Ver->Priority = pkgCache::State::Extra;
0149949b 96 }
dcb79bae 97
6c139d6e 98 if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
dcb79bae 99 return false;
8efa2a3b 100 if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false)
dcb79bae 101 return false;
6c139d6e 102 if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
dcb79bae 103 return false;
6c139d6e 104 if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
dcb79bae 105 return false;
6c139d6e 106 if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
dcb79bae 107 return false;
308c7d30
IJ
108 if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
109 return false;
f55ece0e 110 if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
dcb79bae
AL
111 return false;
112
b2e465d6
AL
113 // Obsolete.
114 if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false)
115 return false;
116
dcb79bae
AL
117 if (ParseProvides(Ver) == false)
118 return false;
0149949b 119
f55a958f
AL
120 return true;
121}
122 /*}}}*/
a52f938b
OS
123// ListParser::Description - Return the description string /*{{{*/
124// ---------------------------------------------------------------------
125/* This is to return the string describing the package in debian
126 form. If this returns the blank string then the entry is assumed to
127 only describe package properties */
128string debListParser::Description()
129{
130 if (DescriptionLanguage().empty())
131 return Section.FindS("Description");
132 else
133 return Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str());
134}
135 /*}}}*/
136// ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
137// ---------------------------------------------------------------------
138/* This is to return the string describing the language of
139 description. If this returns the blank string then the entry is
140 assumed to describe original description. */
141string debListParser::DescriptionLanguage()
142{
143 return Section.FindS("Description").empty() ? pkgIndexFile::LanguageCode() : "";
144}
145 /*}}}*/
146// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
147// ---------------------------------------------------------------------
770c32ec
MV
148/* This is to return the md5 string to allow the check if it is the right
149 description. If no Description-md5 is found in the section it will be
150 calculated.
151 */
a52f938b
OS
152MD5SumValue debListParser::Description_md5()
153{
154 string value = Section.FindS("Description-md5");
155
770c32ec
MV
156 if (value.empty())
157 {
a52f938b
OS
158 MD5Summation md5;
159 md5.Add((Description() + "\n").c_str());
160 return md5.Result();
161 } else
162 return MD5SumValue(value);
163}
164 /*}}}*/
f55a958f
AL
165// ListParser::UsePackage - Update a package structure /*{{{*/
166// ---------------------------------------------------------------------
167/* This is called to update the package with any new information
168 that might be found in the section */
169bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
170 pkgCache::VerIterator Ver)
171{
172 if (Pkg->Section == 0)
b35d2f5f 173 Pkg->Section = UniqFindTagWrite("Section");
b0b4efb9 174 if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
f55a958f 175 return false;
138d4b3d 176 if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
f55a958f 177 return false;
138d4b3d
AL
178
179 if (strcmp(Pkg.Name(),"apt") == 0)
180 Pkg->Flags |= pkgCache::Flag::Important;
181
f55a958f
AL
182 if (ParseStatus(Pkg,Ver) == false)
183 return false;
184 return true;
185}
186 /*}}}*/
204fbdcc
AL
187// ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
188// ---------------------------------------------------------------------
189/* */
190unsigned short debListParser::VersionHash()
191{
192 const char *Sections[] ={"Installed-Size",
193 "Depends",
194 "Pre-Depends",
f78439bf
AL
195// "Suggests",
196// "Recommends",
204fbdcc 197 "Conflicts",
308c7d30 198 "Breaks",
204fbdcc
AL
199 "Replaces",0};
200 unsigned long Result = INIT_FCS;
418a471f 201 char S[1024];
204fbdcc
AL
202 for (const char **I = Sections; *I != 0; I++)
203 {
204 const char *Start;
205 const char *End;
206 if (Section.Find(*I,Start,End) == false || End - Start >= (signed)sizeof(S))
207 continue;
208
209 /* Strip out any spaces from the text, this undoes dpkgs reformatting
421c8d10
AL
210 of certain fields. dpkg also has the rather interesting notion of
211 reformatting depends operators < -> <= */
204fbdcc
AL
212 char *I = S;
213 for (; Start != End; Start++)
421c8d10 214 {
204fbdcc 215 if (isspace(*Start) == 0)
ddc1d8d0 216 *I++ = tolower(*Start);
421c8d10
AL
217 if (*Start == '<' && Start[1] != '<' && Start[1] != '=')
218 *I++ = '=';
219 if (*Start == '>' && Start[1] != '>' && Start[1] != '=')
220 *I++ = '=';
221 }
418a471f 222
204fbdcc
AL
223 Result = AddCRC16(Result,S,I - S);
224 }
225
226 return Result;
227}
228 /*}}}*/
dcb79bae 229// ListParser::ParseStatus - Parse the status field /*{{{*/
f55a958f
AL
230// ---------------------------------------------------------------------
231/* Status lines are of the form,
232 Status: want flag status
233 want = unknown, install, hold, deinstall, purge
234 flag = ok, reinstreq, hold, hold-reinstreq
a005475e 235 status = not-installed, unpacked, half-configured,
f55a958f
AL
236 half-installed, config-files, post-inst-failed,
237 removal-failed, installed
238
239 Some of the above are obsolete (I think?) flag = hold-* and
240 status = post-inst-failed, removal-failed at least.
241 */
242bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
243 pkgCache::VerIterator Ver)
244{
245 const char *Start;
246 const char *Stop;
247 if (Section.Find("Status",Start,Stop) == false)
248 return true;
249
250 // Isolate the first word
251 const char *I = Start;
252 for(; I < Stop && *I != ' '; I++);
253 if (I >= Stop || *I != ' ')
254 return _error->Error("Malformed Status line");
255
256 // Process the want field
6c139d6e
AL
257 WordList WantList[] = {{"unknown",pkgCache::State::Unknown},
258 {"install",pkgCache::State::Install},
259 {"hold",pkgCache::State::Hold},
260 {"deinstall",pkgCache::State::DeInstall},
b2e465d6
AL
261 {"purge",pkgCache::State::Purge},
262 {}};
263 if (GrabWord(string(Start,I-Start),WantList,Pkg->SelectedState) == false)
f55a958f
AL
264 return _error->Error("Malformed 1st word in the Status line");
265
266 // Isloate the next word
267 I++;
268 Start = I;
269 for(; I < Stop && *I != ' '; I++);
270 if (I >= Stop || *I != ' ')
271 return _error->Error("Malformed status line, no 2nd word");
272
273 // Process the flag field
6c139d6e
AL
274 WordList FlagList[] = {{"ok",pkgCache::State::Ok},
275 {"reinstreq",pkgCache::State::ReInstReq},
276 {"hold",pkgCache::State::HoldInst},
b2e465d6
AL
277 {"hold-reinstreq",pkgCache::State::HoldReInstReq},
278 {}};
279 if (GrabWord(string(Start,I-Start),FlagList,Pkg->InstState) == false)
f55a958f
AL
280 return _error->Error("Malformed 2nd word in the Status line");
281
282 // Isloate the last word
283 I++;
284 Start = I;
285 for(; I < Stop && *I != ' '; I++);
286 if (I != Stop)
287 return _error->Error("Malformed Status line, no 3rd word");
288
289 // Process the flag field
6c139d6e
AL
290 WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled},
291 {"unpacked",pkgCache::State::UnPacked},
292 {"half-configured",pkgCache::State::HalfConfigured},
293 {"installed",pkgCache::State::Installed},
6c139d6e
AL
294 {"half-installed",pkgCache::State::HalfInstalled},
295 {"config-files",pkgCache::State::ConfigFiles},
296 {"post-inst-failed",pkgCache::State::HalfConfigured},
b2e465d6
AL
297 {"removal-failed",pkgCache::State::HalfInstalled},
298 {}};
299 if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false)
f55a958f
AL
300 return _error->Error("Malformed 3rd word in the Status line");
301
302 /* A Status line marks the package as indicating the current
303 version as well. Only if it is actually installed.. Otherwise
304 the interesting dpkg handling of the status file creates bogus
305 entries. */
6c139d6e
AL
306 if (!(Pkg->CurrentState == pkgCache::State::NotInstalled ||
307 Pkg->CurrentState == pkgCache::State::ConfigFiles))
f55a958f
AL
308 {
309 if (Ver.end() == true)
310 _error->Warning("Encountered status field in a non-version description");
311 else
312 Pkg->CurrentVer = Ver.Index();
313 }
314
dcb79bae
AL
315 return true;
316}
a1826878 317
b2e465d6
AL
318const char *debListParser::ConvertRelation(const char *I,unsigned int &Op)
319{
320 // Determine the operator
321 switch (*I)
322 {
323 case '<':
324 I++;
325 if (*I == '=')
326 {
327 I++;
328 Op = pkgCache::Dep::LessEq;
329 break;
330 }
331
332 if (*I == '<')
333 {
334 I++;
335 Op = pkgCache::Dep::Less;
336 break;
337 }
338
339 // < is the same as <= and << is really Cs < for some reason
340 Op = pkgCache::Dep::LessEq;
341 break;
342
343 case '>':
344 I++;
345 if (*I == '=')
346 {
347 I++;
348 Op = pkgCache::Dep::GreaterEq;
349 break;
350 }
351
352 if (*I == '>')
353 {
354 I++;
355 Op = pkgCache::Dep::Greater;
356 break;
357 }
358
359 // > is the same as >= and >> is really Cs > for some reason
360 Op = pkgCache::Dep::GreaterEq;
361 break;
362
363 case '=':
364 Op = pkgCache::Dep::Equals;
365 I++;
366 break;
367
368 // HACK around bad package definitions
369 default:
370 Op = pkgCache::Dep::Equals;
371 break;
372 }
373 return I;
374}
375
a1826878
AL
376 /*}}}*/
377// ListParser::ParseDepends - Parse a dependency element /*{{{*/
378// ---------------------------------------------------------------------
379/* This parses the dependency elements out of a standard string in place,
380 bit by bit. */
dcb79bae
AL
381const char *debListParser::ParseDepends(const char *Start,const char *Stop,
382 string &Package,string &Ver,
b2e465d6 383 unsigned int &Op, bool ParseArchFlags)
dcb79bae
AL
384{
385 // Strip off leading space
386 for (;Start != Stop && isspace(*Start) != 0; Start++);
387
388 // Parse off the package name
389 const char *I = Start;
390 for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
391 *I != ',' && *I != '|'; I++);
392
393 // Malformed, no '('
394 if (I != Stop && *I == ')')
395 return 0;
396
397 if (I == Start)
398 return 0;
399
400 // Stash the package name
401 Package.assign(Start,I - Start);
402
403 // Skip white space to the '('
404 for (;I != Stop && isspace(*I) != 0 ; I++);
405
406 // Parse a version
407 if (I != Stop && *I == '(')
408 {
409 // Skip the '('
410 for (I++; I != Stop && isspace(*I) != 0 ; I++);
411 if (I + 3 >= Stop)
412 return 0;
b2e465d6 413 I = ConvertRelation(I,Op);
dcb79bae
AL
414
415 // Skip whitespace
416 for (;I != Stop && isspace(*I) != 0; I++);
417 Start = I;
418 for (;I != Stop && *I != ')'; I++);
419 if (I == Stop || Start == I)
420 return 0;
421
02f000a9
AL
422 // Skip trailing whitespace
423 const char *End = I;
424 for (; End > Start && isspace(End[-1]); End--);
425
171c75f1 426 Ver.assign(Start,End-Start);
dcb79bae
AL
427 I++;
428 }
429 else
430 {
171c75f1 431 Ver.clear();
6c139d6e 432 Op = pkgCache::Dep::NoOp;
dcb79bae
AL
433 }
434
435 // Skip whitespace
436 for (;I != Stop && isspace(*I) != 0; I++);
b2e465d6
AL
437
438 if (ParseArchFlags == true)
439 {
440 string arch = _config->Find("APT::Architecture");
9e10ad8a 441
b2e465d6
AL
442 // Parse an architecture
443 if (I != Stop && *I == '[')
444 {
445 // malformed
446 I++;
447 if (I == Stop)
448 return 0;
449
450 const char *End = I;
451 bool Found = false;
9e10ad8a 452 bool NegArch = false;
b2e465d6
AL
453 while (I != Stop)
454 {
455 // look for whitespace or ending ']'
456 while (End != Stop && !isspace(*End) && *End != ']')
457 End++;
458
459 if (End == Stop)
460 return 0;
9e10ad8a
AL
461
462 if (*I == '!')
463 {
464 NegArch = true;
465 I++;
466 }
467
3e18cc75 468 if (stringcmp(arch,I,End) == 0)
b2e465d6
AL
469 Found = true;
470
471 if (*End++ == ']') {
472 I = End;
473 break;
474 }
475
476 I = End;
477 for (;I != Stop && isspace(*I) != 0; I++);
478 }
9e10ad8a
AL
479
480 if (NegArch)
481 Found = !Found;
b2e465d6 482
9e10ad8a 483 if (Found == false)
b2e465d6
AL
484 Package = ""; /* not for this arch */
485 }
486
487 // Skip whitespace
488 for (;I != Stop && isspace(*I) != 0; I++);
489 }
490
dcb79bae 491 if (I != Stop && *I == '|')
6c139d6e 492 Op |= pkgCache::Dep::Or;
dcb79bae
AL
493
494 if (I == Stop || *I == ',' || *I == '|')
495 {
496 if (I != Stop)
497 for (I++; I != Stop && isspace(*I) != 0; I++);
498 return I;
499 }
500
501 return 0;
502}
503 /*}}}*/
504// ListParser::ParseDepends - Parse a dependency list /*{{{*/
505// ---------------------------------------------------------------------
506/* This is the higher level depends parser. It takes a tag and generates
507 a complete depends tree for the given version. */
508bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
509 const char *Tag,unsigned int Type)
510{
511 const char *Start;
512 const char *Stop;
513 if (Section.Find(Tag,Start,Stop) == false)
514 return true;
515
516 string Package;
517 string Version;
518 unsigned int Op;
519
8efa2a3b 520 while (1)
dcb79bae 521 {
8efa2a3b 522 Start = ParseDepends(Start,Stop,Package,Version,Op);
dcb79bae
AL
523 if (Start == 0)
524 return _error->Error("Problem parsing dependency %s",Tag);
8efa2a3b 525
dcb79bae
AL
526 if (NewDepends(Ver,Package,Version,Op,Type) == false)
527 return false;
8efa2a3b
AL
528 if (Start == Stop)
529 break;
dcb79bae
AL
530 }
531 return true;
532}
533 /*}}}*/
534// ListParser::ParseProvides - Parse the provides list /*{{{*/
535// ---------------------------------------------------------------------
536/* */
537bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
538{
539 const char *Start;
540 const char *Stop;
541 if (Section.Find("Provides",Start,Stop) == false)
542 return true;
543
544 string Package;
545 string Version;
546 unsigned int Op;
547
548 while (1)
549 {
550 Start = ParseDepends(Start,Stop,Package,Version,Op);
551 if (Start == 0)
552 return _error->Error("Problem parsing Provides line");
b63380b0
MV
553 if (Op != pkgCache::Dep::NoOp) {
554 _error->Warning("Ignoring Provides line with DepCompareOp for package %s", Package.c_str());
555 } else {
556 if (NewProvides(Ver,Package,Version) == false)
557 return false;
558 }
dcb79bae
AL
559
560 if (Start == Stop)
561 break;
562 }
563
f55a958f
AL
564 return true;
565}
566 /*}}}*/
567// ListParser::GrabWord - Matches a word and returns /*{{{*/
568// ---------------------------------------------------------------------
569/* Looks for a word in a list of words - for ParseStatus */
b2e465d6 570bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
f55a958f 571{
b2e465d6 572 for (unsigned int C = 0; List[C].Str != 0; C++)
f55a958f
AL
573 {
574 if (strcasecmp(Word.c_str(),List[C].Str) == 0)
575 {
576 Out = List[C].Val;
577 return true;
578 }
579 }
580 return false;
581}
582 /*}}}*/
583// ListParser::Step - Move to the next section in the file /*{{{*/
584// ---------------------------------------------------------------------
0149949b 585/* This has to be carefull to only process the correct architecture */
f55a958f
AL
586bool debListParser::Step()
587{
dcb79bae 588 iOffset = Tags.Offset();
0149949b 589 while (Tags.Step(Section) == true)
ddc1d8d0
AL
590 {
591 /* See if this is the correct Architecture, if it isn't then we
592 drop the whole section. A missing arch tag only happens (in theory)
593 inside the Status file, so that is a positive return */
0149949b
AL
594 const char *Start;
595 const char *Stop;
596 if (Section.Find("Architecture",Start,Stop) == false)
597 return true;
9c14e3d6 598
3e18cc75 599 if (stringcmp(Arch,Start,Stop) == 0)
0149949b
AL
600 return true;
601
9c14e3d6 602 if (stringcmp(Start,Stop,"all") == 0)
0149949b 603 return true;
dcb79bae
AL
604
605 iOffset = Tags.Offset();
0149949b
AL
606 }
607 return false;
f55a958f
AL
608}
609 /*}}}*/
b0b4efb9
AL
610// ListParser::LoadReleaseInfo - Load the release information /*{{{*/
611// ---------------------------------------------------------------------
612/* */
613bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
f2152f03 614 FileFd &File, string component)
b0b4efb9 615{
b3d44315 616 pkgTagFile Tags(&File, File.Size() + 256); // XXX
b0b4efb9
AL
617 pkgTagSection Section;
618 if (Tags.Step(Section) == false)
619 return false;
620
f2152f03
MV
621 //mvo: I don't think we need to fill that in (it's unused since apt-0.6)
622 //FileI->Architecture = WriteUniqString(Arch);
623
624 // apt-secure does no longer download individual (per-section) Release
625 // file. to provide Component pinning we use the section name now
626 FileI->Component = WriteUniqString(component);
627
b0b4efb9
AL
628 const char *Start;
629 const char *Stop;
b3d44315 630 if (Section.Find("Suite",Start,Stop) == true)
b0b4efb9
AL
631 FileI->Archive = WriteUniqString(Start,Stop - Start);
632 if (Section.Find("Component",Start,Stop) == true)
633 FileI->Component = WriteUniqString(Start,Stop - Start);
634 if (Section.Find("Version",Start,Stop) == true)
635 FileI->Version = WriteUniqString(Start,Stop - Start);
636 if (Section.Find("Origin",Start,Stop) == true)
637 FileI->Origin = WriteUniqString(Start,Stop - Start);
638 if (Section.Find("Label",Start,Stop) == true)
639 FileI->Label = WriteUniqString(Start,Stop - Start);
640 if (Section.Find("Architecture",Start,Stop) == true)
641 FileI->Architecture = WriteUniqString(Start,Stop - Start);
0dbb95d8 642
3c124dde
AL
643 if (Section.FindFlag("NotAutomatic",FileI->Flags,
644 pkgCache::Flag::NotAutomatic) == false)
0dbb95d8 645 _error->Warning("Bad NotAutomatic flag");
f2152f03 646
b0b4efb9
AL
647 return !_error->PendingError();
648}
649 /*}}}*/
b2e465d6
AL
650// ListParser::GetPrio - Convert the priority from a string /*{{{*/
651// ---------------------------------------------------------------------
652/* */
653unsigned char debListParser::GetPrio(string Str)
654{
655 unsigned char Out;
656 if (GrabWord(Str,PrioList,Out) == false)
657 Out = pkgCache::State::Extra;
658
659 return Out;
660}
661 /*}}}*/