
10 changed files with 693 additions and 20 deletions
@ -0,0 +1,280 @@ |
|||
// -*- mode: cpp; mode: fold -*-
|
|||
// Description /*{{{*/
|
|||
// $Id: cmndline.cc,v 1.1 1998/09/22 05:30:26 jgg Exp $
|
|||
/* ######################################################################
|
|||
|
|||
Command Line Class - Sophisticated command line parser |
|||
|
|||
##################################################################### */ |
|||
/*}}}*/ |
|||
// Include files /*{{{*/
|
|||
#ifdef __GNUG__ |
|||
#pragma implementation "apt-pkg/cmndline.h" |
|||
#endif |
|||
#include <apt-pkg/cmndline.h> |
|||
#include <apt-pkg/error.h> |
|||
#include <strutl.h> |
|||
/*}}}*/ |
|||
|
|||
// CommandLine::CommandLine - Constructor /*{{{*/
|
|||
// ---------------------------------------------------------------------
|
|||
/* */ |
|||
CommandLine::CommandLine(Args *AList,Configuration *Conf) : ArgList(AList), |
|||
Conf(Conf), FileList(0) |
|||
{ |
|||
} |
|||
/*}}}*/ |
|||
// CommandLine::Parse - Main action member /*{{{*/
|
|||
// ---------------------------------------------------------------------
|
|||
/* */ |
|||
bool CommandLine::Parse(int argc,const char **argv) |
|||
{ |
|||
FileList = new const char *[argc]; |
|||
const char **Files = FileList; |
|||
int I; |
|||
for (I = 1; I != argc; I++) |
|||
{ |
|||
const char *Opt = argv[I]; |
|||
|
|||
// It is not an option
|
|||
if (*Opt != '-') |
|||
{ |
|||
*Files++ = Opt; |
|||
continue; |
|||
} |
|||
|
|||
Opt++; |
|||
|
|||
// Double dash signifies the end of option processing
|
|||
if (*Opt == '-' && Opt[1] == 0) |
|||
break; |
|||
|
|||
// Single dash is a short option
|
|||
if (*Opt != '-') |
|||
{ |
|||
// Iterate over each letter
|
|||
while (*Opt != 0) |
|||
{ |
|||
// Search for the option
|
|||
Args *A; |
|||
for (A = ArgList; A->end() == false && A->ShortOpt != *Opt; A++); |
|||
if (A->end() == true) |
|||
return _error->Error("Command line option '%c' [from %s] is not known.",*Opt,argv[I]); |
|||
|
|||
if (HandleOpt(I,argc,argv,Opt,A) == false) |
|||
return false; |
|||
if (*Opt != 0) |
|||
Opt++; |
|||
} |
|||
continue; |
|||
} |
|||
|
|||
Opt++; |
|||
|
|||
// Match up to a = against the list
|
|||
const char *OptEnd = Opt; |
|||
Args *A; |
|||
for (; *OptEnd != 0 && *OptEnd != '='; OptEnd++); |
|||
for (A = ArgList; A->end() == false && |
|||
stringcasecmp(Opt,OptEnd,A->LongOpt) != 0; A++); |
|||
|
|||
// Failed, look for a word after the first - (no-foo)
|
|||
if (A->end() == true) |
|||
{ |
|||
for (; Opt != OptEnd && *Opt != '-'; Opt++); |
|||
|
|||
if (Opt == OptEnd) |
|||
return _error->Error("Command line option %s is not understood",argv[I]); |
|||
Opt++; |
|||
|
|||
for (A = ArgList; A->end() == false && |
|||
stringcasecmp(Opt,OptEnd,A->LongOpt) != 0; A++); |
|||
|
|||
// Failed again..
|
|||
if (A->end() == true && OptEnd - Opt != 1) |
|||
return _error->Error("Command line option %s is not understood",argv[I]); |
|||
|
|||
// The option could be a single letter option prefixed by a no-..
|
|||
for (A = ArgList; A->end() == false && A->ShortOpt != *Opt; A++); |
|||
|
|||
if (A->end() == true) |
|||
return _error->Error("Command line option %s is not understood",argv[I]); |
|||
} |
|||
|
|||
// Deal with it.
|
|||
OptEnd--; |
|||
if (HandleOpt(I,argc,argv,OptEnd,A) == false) |
|||
return false; |
|||
} |
|||
|
|||
// Copy any remaining file names over
|
|||
for (; I != argc; I++) |
|||
*Files++ = argv[I]; |
|||
*Files = 0; |
|||
|
|||
return true; |
|||
} |
|||
/*}}}*/ |
|||
// CommandLine::HandleOpt - Handle a single option including all flags /*{{{*/
|
|||
// ---------------------------------------------------------------------
|
|||
/* This is a helper function for parser, it looks at a given argument
|
|||
and looks for specific patterns in the string, it gets tokanized |
|||
-ruffly- like -*[yes|true|enable]-(o|longopt)[=][ ][argument] */ |
|||
bool CommandLine::HandleOpt(int &I,int argc,const char *argv[], |
|||
const char *&Opt,Args *A) |
|||
{ |
|||
const char *Argument = 0; |
|||
bool CertainArg = false; |
|||
int IncI = 0; |
|||
|
|||
/* Determine the possible location of an option or 0 if their is
|
|||
no option */ |
|||
if (Opt[1] == 0 || (Opt[1] == '=' && Opt[2] == 0)) |
|||
{ |
|||
if (I + 1 < argc && argv[I+1][0] != '-') |
|||
Argument = argv[I+1]; |
|||
|
|||
// Equals was specified but we fell off the end!
|
|||
if (Opt[1] == '=' && Argument == 0) |
|||
return _error->Error("Option %s requires an argument.",argv[I]); |
|||
if (Opt[1] == '=') |
|||
CertainArg = true; |
|||
|
|||
IncI = 1; |
|||
} |
|||
else |
|||
{ |
|||
if (Opt[1] == '=') |
|||
{ |
|||
CertainArg = true; |
|||
Argument = Opt + 2; |
|||
} |
|||
else |
|||
Argument = Opt + 1; |
|||
} |
|||
|
|||
// Option is an argument set
|
|||
if ((A->Flags & HasArg) == HasArg) |
|||
{ |
|||
if (Argument == 0) |
|||
return _error->Error("Option %s requires an argument.",argv[I]); |
|||
Opt += strlen(Opt); |
|||
I += IncI; |
|||
|
|||
// Parse a configuration file
|
|||
if ((A->Flags & ConfigFile) == ConfigFile) |
|||
return ReadConfigFile(*Conf,Argument); |
|||
|
|||
Conf->Set(A->ConfName,Argument); |
|||
return true; |
|||
} |
|||
|
|||
// Option is an integer level
|
|||
if ((A->Flags & IntLevel) == IntLevel) |
|||
{ |
|||
// There might be an argument
|
|||
if (Argument != 0) |
|||
{ |
|||
char *EndPtr; |
|||
unsigned long Value = strtol(Argument,&EndPtr,10); |
|||
|
|||
// Conversion failed and the argument was specified with an =s
|
|||
if (EndPtr == Argument && CertainArg == true) |
|||
return _error->Error("Option %s requires an integer argument, not '%s'",argv[I],Argument); |
|||
|
|||
// Conversion was ok, set the value and return
|
|||
if (EndPtr != Argument) |
|||
{ |
|||
Conf->Set(A->ConfName,Value); |
|||
Opt += strlen(Opt); |
|||
I += IncI; |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
// Increase the level
|
|||
Conf->Set(A->ConfName,Conf->FindI(A->ConfName)+1); |
|||
return true; |
|||
} |
|||
|
|||
// Option is a boolean
|
|||
int Sense = -1; // -1 is unspecified, 0 is yes 1 is no
|
|||
|
|||
// Look for an argument.
|
|||
while (1) |
|||
{ |
|||
// Look at preceeding text
|
|||
char Buffer[300]; |
|||
if (Argument == 0) |
|||
{ |
|||
if (strlen(argv[I]) >= sizeof(Buffer)) |
|||
return _error->Error("Option '%s' is too long",argv[I]); |
|||
|
|||
const char *J = argv[I]; |
|||
for (; *J != 0 && *J == '-'; J++); |
|||
const char *JEnd = J; |
|||
for (; *JEnd != 0 && *JEnd != '-'; JEnd++); |
|||
if (*JEnd != 0) |
|||
{ |
|||
strncpy(Buffer,J,JEnd - J); |
|||
Buffer[JEnd - J] = 0; |
|||
Argument = Buffer; |
|||
CertainArg = true; |
|||
} |
|||
else |
|||
break; |
|||
} |
|||
|
|||
// Check for positives
|
|||
if (strcasecmp(Argument,"yes") == 0 || |
|||
strcasecmp(Argument,"true") == 0 || |
|||
strcasecmp(Argument,"with") == 0 || |
|||
strcasecmp(Argument,"enable") == 0) |
|||
{ |
|||
Sense = 1; |
|||
|
|||
// Eat the argument
|
|||
if (Argument != Buffer) |
|||
{ |
|||
Opt += strlen(Opt); |
|||
I += IncI; |
|||
} |
|||
break; |
|||
} |
|||
|
|||
// Check for negatives
|
|||
if (strcasecmp(Argument,"no") == 0 || |
|||
strcasecmp(Argument,"false") == 0 || |
|||
strcasecmp(Argument,"without") == 0 || |
|||
strcasecmp(Argument,"disable") == 0) |
|||
{ |
|||
Sense = 0; |
|||
|
|||
// Eat the argument
|
|||
if (Argument != Buffer) |
|||
{ |
|||
Opt += strlen(Opt); |
|||
I += IncI; |
|||
} |
|||
break; |
|||
} |
|||
|
|||
if (CertainArg == true) |
|||
return _error->Error("Sense %s is not understood, try true or false.",Argument); |
|||
|
|||
Argument = 0; |
|||
} |
|||
|
|||
// Indeterminate sense depends on the flag
|
|||
if (Sense == -1) |
|||
{ |
|||
if ((A->Flags & InvBoolean) == InvBoolean) |
|||
Sense = 0; |
|||
else |
|||
Sense = 1; |
|||
} |
|||
|
|||
Conf->Set(A->ConfName,Sense); |
|||
return true; |
|||
} |
|||
/*}}}*/ |
@ -0,0 +1,91 @@ |
|||
// -*- mode: cpp; mode: fold -*-
|
|||
// Description /*{{{*/
|
|||
// $Id: cmndline.h,v 1.1 1998/09/22 05:30:26 jgg Exp $
|
|||
/* ######################################################################
|
|||
|
|||
Command Line Class - Sophisticated command line parser |
|||
|
|||
This class provides a unified command line parser/option handliner/ |
|||
configuration mechanism. It allows the caller to specify the option |
|||
set and map the option set into the configuration class or other |
|||
special functioning. |
|||
|
|||
Filenames are stripped from the option stream and put into their |
|||
own array. |
|||
|
|||
The argument descriptor array can be initialized as: |
|||
|
|||
CommandLine::Args Args[] = |
|||
{{'q',"quiet","apt::get::quiet",CommandLine::IntLevel}, |
|||
{0,0,0,0,0}}; |
|||
|
|||
The flags mean, |
|||
HasArg - Means the argument has a value |
|||
IntLevel - Means the argument is an integer level indication, the |
|||
following -qqqq (+3) -q5 (=5) -q=5 (=5) are valid |
|||
Boolean - Means it is true/false or yes/no. |
|||
-d (true) --no-d (false) --yes-d (true) |
|||
--long (true) --no-long (false) --yes-long (true) |
|||
-d=yes (true) -d=no (false) Words like enable, disable, |
|||
true false, yes no and on off are recognized in logical |
|||
places. |
|||
InvBoolean - Same as boolean but the case with no specified sense |
|||
(first case) is set to false. |
|||
ConfigFile - Means this flag should be interprited as the name of |
|||
a config file to read in at this point in option processing. |
|||
Implies HasArg. |
|||
The default, if the flags are 0 is to use Boolean |
|||
|
|||
##################################################################### */ |
|||
/*}}}*/ |
|||
// Header section: pkglib
|
|||
#ifndef PKGLIB_CMNDLINE_H |
|||
#define PKGLIB_CMNDLINE_H |
|||
|
|||
#ifdef __GNUG__ |
|||
#pragma interface "apt-pkg/cmndline.h" |
|||
#endif |
|||
|
|||
#include <apt-pkg/configuration.h> |
|||
|
|||
class CommandLine |
|||
{ |
|||
public: |
|||
struct Args; |
|||
|
|||
protected: |
|||
|
|||
Args *ArgList; |
|||
Configuration *Conf; |
|||
bool HandleOpt(int &I,int argc,const char *argv[],const char *&Opt,Args *A); |
|||
|
|||
public: |
|||
|
|||
enum AFlags |
|||
{ |
|||
HasArg = (1 << 0), |
|||
IntLevel = (1 << 1), |
|||
Boolean = (1 << 2), |
|||
InvBoolean = (1 << 3), |
|||
ConfigFile = (1 << 4) | HasArg |
|||
}; |
|||
|
|||
const char **FileList; |
|||
|
|||
bool Parse(int argc,const char **argv); |
|||
void ShowHelp(); |
|||
|
|||
CommandLine(Args *AList,Configuration *Conf); |
|||
}; |
|||
|
|||
struct CommandLine::Args |
|||
{ |
|||
char ShortOpt; |
|||
const char *LongOpt; |
|||
const char *ConfName; |
|||
unsigned long Flags; |
|||
|
|||
inline bool end() {return ShortOpt == 0 && LongOpt == 0;}; |
|||
}; |
|||
|
|||
#endif |
Loading…
Reference in new issue