]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/cmndline.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: cmndline.cc,v 1.11 2001/02/20 07:03:17 jgg Exp $
4 /* ######################################################################
6 Command Line Class - Sophisticated command line parser
8 ##################################################################### */
10 // Include files /*{{{*/
12 #pragma implementation "apt-pkg/cmndline.h"
14 #include <apt-pkg/cmndline.h>
15 #include <apt-pkg/error.h>
16 #include <apt-pkg/strutl.h>
21 // CommandLine::CommandLine - Constructor /*{{{*/
22 // ---------------------------------------------------------------------
24 CommandLine::CommandLine(Args
*AList
,Configuration
*Conf
) : ArgList(AList
),
25 Conf(Conf
), FileList(0)
29 // CommandLine::~CommandLine - Destructor /*{{{*/
30 // ---------------------------------------------------------------------
32 CommandLine::~CommandLine()
37 // CommandLine::Parse - Main action member /*{{{*/
38 // ---------------------------------------------------------------------
40 bool CommandLine::Parse(int argc
,const char **argv
)
43 FileList
= new const char *[argc
];
44 const char **Files
= FileList
;
46 for (I
= 1; I
!= argc
; I
++)
48 const char *Opt
= argv
[I
];
50 // It is not an option
59 // Double dash signifies the end of option processing
60 if (*Opt
== '-' && Opt
[1] == 0)
63 // Single dash is a short option
66 // Iterate over each letter
69 // Search for the option
71 for (A
= ArgList
; A
->end() == false && A
->ShortOpt
!= *Opt
; A
++);
73 return _error
->Error(_("Command line option '%c' [from %s] is not known."),*Opt
,argv
[I
]);
75 if (HandleOpt(I
,argc
,argv
,Opt
,A
) == false)
85 // Match up to a = against the list
86 const char *OptEnd
= Opt
;
88 for (; *OptEnd
!= 0 && *OptEnd
!= '='; OptEnd
++);
89 for (A
= ArgList
; A
->end() == false &&
90 stringcasecmp(Opt
,OptEnd
,A
->LongOpt
) != 0; A
++);
92 // Failed, look for a word after the first - (no-foo)
93 bool PreceedMatch
= false;
96 for (; Opt
!= OptEnd
&& *Opt
!= '-'; Opt
++);
99 return _error
->Error(_("Command line option %s is not understood"),argv
[I
]);
102 for (A
= ArgList
; A
->end() == false &&
103 stringcasecmp(Opt
,OptEnd
,A
->LongOpt
) != 0; A
++);
106 if (A
->end() == true && OptEnd
- Opt
!= 1)
107 return _error
->Error(_("Command line option %s is not understood"),argv
[I
]);
109 // The option could be a single letter option prefixed by a no-..
110 if (A
->end() == true)
112 for (A
= ArgList
; A
->end() == false && A
->ShortOpt
!= *Opt
; A
++);
114 if (A
->end() == true)
115 return _error
->Error(_("Command line option %s is not understood"),argv
[I
]);
118 // The option is not boolean
119 if (A
->IsBoolean() == false)
120 return _error
->Error(_("Command line option %s is not boolean"),argv
[I
]);
126 if (HandleOpt(I
,argc
,argv
,OptEnd
,A
,PreceedMatch
) == false)
130 // Copy any remaining file names over
131 for (; I
!= argc
; I
++)
138 // CommandLine::HandleOpt - Handle a single option including all flags /*{{{*/
139 // ---------------------------------------------------------------------
140 /* This is a helper function for parser, it looks at a given argument
141 and looks for specific patterns in the string, it gets tokanized
142 -ruffly- like -*[yes|true|enable]-(o|longopt)[=][ ][argument] */
143 bool CommandLine::HandleOpt(int &I
,int argc
,const char *argv
[],
144 const char *&Opt
,Args
*A
,bool PreceedMatch
)
146 const char *Argument
= 0;
147 bool CertainArg
= false;
150 /* Determine the possible location of an option or 0 if their is
152 if (Opt
[1] == 0 || (Opt
[1] == '=' && Opt
[2] == 0))
154 if (I
+ 1 < argc
&& argv
[I
+1][0] != '-')
155 Argument
= argv
[I
+1];
157 // Equals was specified but we fell off the end!
158 if (Opt
[1] == '=' && Argument
== 0)
159 return _error
->Error(_("Option %s requires an argument."),argv
[I
]);
176 // Option is an argument set
177 if ((A
->Flags
& HasArg
) == HasArg
)
180 return _error
->Error(_("Option %s requires an argument."),argv
[I
]);
184 // Parse a configuration file
185 if ((A
->Flags
& ConfigFile
) == ConfigFile
)
186 return ReadConfigFile(*Conf
,Argument
);
188 // Arbitary item specification
189 if ((A
->Flags
& ArbItem
) == ArbItem
)
192 for (J
= Argument
; *J
!= 0 && *J
!= '='; J
++);
194 return _error
->Error(_("Option %s: Configuration item sepecification must have an =<val>."),argv
[I
]);
200 return _error
->Error(_("Option %s: Configuration item sepecification must have an =<val>."),argv
[I
]);
201 Conf
->Set(string(Argument
,J
-Argument
),string(argv
[I
++ +1]));
204 Conf
->Set(string(Argument
,J
-Argument
),string(J
+1));
209 const char *I
= A
->ConfName
;
210 for (; *I
!= 0 && *I
!= ' '; I
++);
212 Conf
->Set(string(A
->ConfName
,0,I
-A
->ConfName
),string(I
+1) + Argument
);
214 Conf
->Set(A
->ConfName
,string(I
) + Argument
);
219 // Option is an integer level
220 if ((A
->Flags
& IntLevel
) == IntLevel
)
222 // There might be an argument
226 unsigned long Value
= strtol(Argument
,&EndPtr
,10);
228 // Conversion failed and the argument was specified with an =s
229 if (EndPtr
== Argument
&& CertainArg
== true)
230 return _error
->Error(_("Option %s requires an integer argument, not '%s'"),argv
[I
],Argument
);
232 // Conversion was ok, set the value and return
233 if (EndPtr
!= 0 && EndPtr
!= Argument
&& *EndPtr
== 0)
235 Conf
->Set(A
->ConfName
,Value
);
242 // Increase the level
243 Conf
->Set(A
->ConfName
,Conf
->FindI(A
->ConfName
)+1);
247 // Option is a boolean
248 int Sense
= -1; // -1 is unspecified, 0 is yes 1 is no
250 // Look for an argument.
253 // Look at preceeding text
257 if (PreceedMatch
== false)
260 if (strlen(argv
[I
]) >= sizeof(Buffer
))
261 return _error
->Error(_("Option '%s' is too long"),argv
[I
]);
263 // Skip the leading dash
264 const char *J
= argv
[I
];
265 for (; *J
!= 0 && *J
== '-'; J
++);
267 const char *JEnd
= J
;
268 for (; *JEnd
!= 0 && *JEnd
!= '-'; JEnd
++);
271 strncpy(Buffer
,J
,JEnd
- J
);
272 Buffer
[JEnd
- J
] = 0;
281 Sense
= StringToBool(Argument
);
285 if (Argument
!= Buffer
)
293 if (CertainArg
== true)
294 return _error
->Error(_("Sense %s is not understood, try true or false."),Argument
);
299 // Indeterminate sense depends on the flag
302 if ((A
->Flags
& InvBoolean
) == InvBoolean
)
308 Conf
->Set(A
->ConfName
,Sense
);
312 // CommandLine::FileSize - Count the number of filenames /*{{{*/
313 // ---------------------------------------------------------------------
315 unsigned int CommandLine::FileSize() const
317 unsigned int Count
= 0;
318 for (const char **I
= FileList
; I
!= 0 && *I
!= 0; I
++)
323 // CommandLine::DispatchArg - Do something with the first arg /*{{{*/
324 // ---------------------------------------------------------------------
326 bool CommandLine::DispatchArg(Dispatch
*Map
,bool NoMatch
)
329 for (I
= 0; Map
[I
].Match
!= 0; I
++)
331 if (strcmp(FileList
[0],Map
[I
].Match
) == 0)
333 bool Res
= Map
[I
].Handler(*this);
334 if (Res
== false && _error
->PendingError() == false)
335 _error
->Error("Handler silently failed");
341 if (Map
[I
].Match
== 0)
344 _error
->Error(_("Invalid operation %s"),FileList
[0]);