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