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