use a format string in ListSingleVersion
[ntk/apt.git] / ftparchive / override.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
dc738e7a 3// $Id: override.cc,v 1.4 2003/02/10 07:34:41 doogie Exp $
b2e465d6
AL
4/* ######################################################################
5
6 Override
7
8 Store the override file.
9
10 ##################################################################### */
11 /*}}}*/
12// Include Files /*{{{*/
ea542140
DK
13#include <config.h>
14
b2e465d6
AL
15#include <apt-pkg/strutl.h>
16#include <apt-pkg/error.h>
17
18#include <stdio.h>
453b82a3
DK
19#include <ctype.h>
20#include <string.h>
21#include <utility>
ea542140 22
b2e465d6 23#include "override.h"
a00a9b44
DK
24
25#include <apti18n.h>
b2e465d6
AL
26 /*}}}*/
27
28// Override::ReadOverride - Read the override file /*{{{*/
29// ---------------------------------------------------------------------
30/* This parses the override file and reads it into the map */
9209ec47 31bool Override::ReadOverride(string const &File,bool const &Source)
b2e465d6
AL
32{
33 if (File.empty() == true)
34 return true;
35
36 FILE *F = fopen(File.c_str(),"r");
37 if (F == 0)
dc738e7a 38 return _error->Errno("fopen",_("Unable to open %s"),File.c_str());
b2e465d6 39
6c50447e 40 char Line[1000];
650faab0 41 unsigned long long Counter = 0;
b2e465d6
AL
42 while (fgets(Line,sizeof(Line),F) != 0)
43 {
44 Counter++;
45 Item Itm;
46
47 // Silence
48 for (char *I = Line; *I != 0; I++)
49 if (*I == '#')
50 *I = 0;
51
52 // Strip space leading up to the package name, skip blank lines
53 char *Pkg = Line;
54 for (; isspace(*Pkg) && *Pkg != 0;Pkg++);
1c946b57 55 if (*Pkg == 0)
b2e465d6
AL
56 continue;
57
62d8a765
DK
58#define APT_FIND_NEXT_FIELD \
59 for (End++; isspace(*End) != 0 && *End != 0; ++End) \
60 /* skip spaces */ ; \
61 Start = End; \
62 for (; isspace(*End) == 0 && *End != 0; ++End) \
63 /* find end of word */ ;
64
65#define APT_WARNING_MALFORMED_LINE(FIELD) \
66 if (*End == 0) \
67 { \
68 _error->Warning(_("Malformed override %s line %llu (%s)"),File.c_str(), \
69 Counter, FIELD ); \
70 continue; \
71 } \
72 *End = 0;
73
b2e465d6 74 // Find the package and zero..
62d8a765 75 char *Start;
b2e465d6
AL
76 char *End = Pkg;
77 for (; isspace(*End) == 0 && *End != 0; End++);
62d8a765
DK
78 APT_WARNING_MALFORMED_LINE("pkgname");
79
80 APT_FIND_NEXT_FIELD;
b2e465d6
AL
81
82 // Find the priority
83 if (Source == false)
84 {
62d8a765 85 APT_WARNING_MALFORMED_LINE("priority");
b2e465d6 86 Itm.Priority = Start;
62d8a765
DK
87
88 APT_FIND_NEXT_FIELD;
b2e465d6 89 }
62d8a765 90
b2e465d6 91 // Find the Section
62d8a765 92 APT_WARNING_MALFORMED_LINE("section");
64177f17 93 Itm.FieldOverride["Section"] = Start;
b2e465d6
AL
94
95 // Source override files only have the two columns
96 if (Source == true)
97 {
98 Mapping[Pkg] = Itm;
99 continue;
100 }
62d8a765 101
b2e465d6
AL
102 // Find the =>
103 for (End++; isspace(*End) != 0 && *End != 0; End++);
104 if (*End != 0)
105 {
106 Start = End;
107 for (; *End != 0 && (End[0] != '=' || End[1] != '>'); End++);
108 if (*End == 0 || strlen(End) < 4)
109 {
110 Itm.OldMaint = "*";
111 Itm.NewMaint = _strstrip(Start);
112 }
113 else
114 {
115 *End = 0;
116 Itm.OldMaint = _strstrip(Start);
117
118 End += 3;
119 Itm.NewMaint = _strstrip(End);
120 }
121 }
122
123 Mapping[Pkg] = Itm;
124 }
125
64177f17 126 if (ferror(F))
dc738e7a 127 _error->Errno("fgets",_("Failed to read the override file %s"),File.c_str());
64177f17
AL
128 fclose(F);
129 return true;
130}
131 /*}}}*/
132// Override::ReadExtraOverride - Read the extra override file /*{{{*/
133// ---------------------------------------------------------------------
134/* This parses the extra override file and reads it into the map */
65512241 135bool Override::ReadExtraOverride(string const &File,bool const &/*Source*/)
64177f17
AL
136{
137 if (File.empty() == true)
138 return true;
139
140 FILE *F = fopen(File.c_str(),"r");
141 if (F == 0)
dc738e7a 142 return _error->Errno("fopen",_("Unable to open %s"),File.c_str());
64177f17 143
6c50447e 144 char Line[1000];
650faab0 145 unsigned long long Counter = 0;
64177f17
AL
146 while (fgets(Line,sizeof(Line),F) != 0)
147 {
148 Counter++;
149
150 // Silence
151 for (char *I = Line; *I != 0; I++)
152 if (*I == '#')
153 *I = 0;
154
155 // Strip space leading up to the package name, skip blank lines
156 char *Pkg = Line;
157 for (; isspace(*Pkg) && *Pkg != 0;Pkg++);
158 if (Pkg == 0)
159 continue;
160
161 // Find the package and zero..
162 char *End = Pkg;
163 for (; isspace(*End) == 0 && *End != 0; End++);
164 if (*End == 0)
165 {
650faab0 166 _error->Warning(_("Malformed override %s line %llu #1"),File.c_str(),
64177f17
AL
167 Counter);
168 continue;
169 }
170 *End = 0;
171
172 // Find the field
173 for (End++; isspace(*End) != 0 && *End != 0; End++);
174 char *Field = End;
175 for (; isspace(*End) == 0 && *End != 0; End++);
176 if (*End == 0)
177 {
650faab0 178 _error->Warning(_("Malformed override %s line %llu #2"),File.c_str(),
64177f17
AL
179 Counter);
180 continue;
181 }
182 *End = 0;
183
184 // Find the field value
185 for (End++; isspace(*End) != 0 && *End != 0; End++);
186 char *Value = End;
187 for (; *End != 0; End++);
188 for (; isspace(*(End-1)) && End > Value; End--);
189 if (End == Value)
190 {
650faab0 191 _error->Warning(_("Malformed override %s line %llu #3"),File.c_str(),
64177f17
AL
192 Counter);
193 continue;
194 }
195 *End = 0;
196
197 Mapping[Pkg].FieldOverride[Field] = Value;
198 }
199
b2e465d6 200 if (ferror(F))
dc738e7a 201 _error->Errno("fgets",_("Failed to read the override file %s"),File.c_str());
b2e465d6
AL
202 fclose(F);
203 return true;
204}
205 /*}}}*/
0b41e0e7 206
d3e8fbb3 207// Override::GetItem - Get a architecture specific item /*{{{*/
0b41e0e7
MV
208// ---------------------------------------------------------------------
209/* Returns a override item for the given package and the given architecture.
210 * Treats "all" special
211 */
9209ec47 212Override::Item* Override::GetItem(string const &Package, string const &Architecture)
0b41e0e7 213{
9209ec47 214 map<string,Item>::const_iterator I = Mapping.find(Package);
0b41e0e7
MV
215 map<string,Item>::iterator J = Mapping.find(Package + "/" + Architecture);
216
217 if (I == Mapping.end() && J == Mapping.end())
218 {
219 return 0;
220 }
221
222 Item *result = new Item;
223 if (I == Mapping.end()) *result = J->second;
224 else
225 {
226 *result = I->second;
227 if (J != Mapping.end())
228 {
229 Item *R = &J->second;
230 if (R->Priority != "") result->Priority = R->Priority;
231 if (R->OldMaint != "") result->OldMaint = R->OldMaint;
232 if (R->NewMaint != "") result->NewMaint = R->NewMaint;
9209ec47 233 for (map<string,string>::const_iterator foI = R->FieldOverride.begin();
f7f0d6c7 234 foI != R->FieldOverride.end(); ++foI)
0b41e0e7
MV
235 {
236 result->FieldOverride[foI->first] = foI->second;
237 }
d3e8fbb3
DK
238 }
239 }
0b41e0e7 240 return result;
d3e8fbb3 241}
0b41e0e7
MV
242
243
b2e465d6
AL
244// Override::Item::SwapMaint - Swap the maintainer field if necessary /*{{{*/
245// ---------------------------------------------------------------------
246/* Returns the new maintainer string after evaluating the rewriting rule. If
247 there is a rule but it does not match then the empty string is returned,
248 also if there was no rewrite rule the empty string is returned. Failed
249 indicates if there was some kind of problem while rewriting. */
9209ec47 250string Override::Item::SwapMaint(string const &Orig,bool &Failed)
b2e465d6
AL
251{
252 Failed = false;
253
254 // Degenerate case..
255 if (NewMaint.empty() == true)
256 return OldMaint;
257
258 if (OldMaint == "*")
259 return NewMaint;
260
261 /* James: ancient, eliminate it, however it is still being used in the main
262 override file. Thus it persists.*/
263#if 1
264 // Break OldMaint up into little bits on double slash boundaries.
9209ec47 265 string::const_iterator End = OldMaint.begin();
b2e465d6
AL
266 while (1)
267 {
9209ec47 268 string::const_iterator Start = End;
b2e465d6
AL
269 for (; End < OldMaint.end() &&
270 (End + 3 >= OldMaint.end() || End[0] != ' ' ||
f7f0d6c7 271 End[1] != '/' || End[2] != '/'); ++End);
b2e465d6
AL
272 if (stringcasecmp(Start,End,Orig.begin(),Orig.end()) == 0)
273 return NewMaint;
274
275 if (End >= OldMaint.end())
276 break;
277
278 // Skip the divider and white space
f7f0d6c7 279 for (; End < OldMaint.end() && (*End == '/' || *End == ' '); ++End);
b2e465d6
AL
280 }
281#else
282 if (stringcasecmp(OldMaint.begin(),OldMaint.end(),Orig.begin(),Orig.end()) == 0)
283 return NewMaint;
284#endif
285
286 Failed = true;
287 return string();
288}
289 /*}}}*/