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