This is cmdline.c in view mode; [Download] [Up]
//------------------------------------------------------------------------
// ^FILE: cmdline.c - implement CmdLine member functions.
//
// ^DESCRIPTION:
// Many of the more basic member functions of a CmdLine are implemented
// in this file. They are as follows:
//
// Contructors
// Destructors
// CmdLine::name()
// CmdLine::error()
// CmdLine::append
//
// ^HISTORY:
// 03/21/92 Brad Appleton <brad@ssd.csd.harris.com> Created
//
// 03/01/93 Brad Appleton <brad@ssd.csd.harris.com>
// - Added cmd_nargs_parsed field to CmdLine
// - Added cmd_description field to CmdLine
// - Added exit_handler() and quit() member-functions to CmdLine
//-^^---------------------------------------------------------------------
#include <stdlib.h>
#include <iostream.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include "cmdline.h"
#include "cmdargs.h"
#include "arglist.h"
#include "states.h"
#define va_CmdArgP(ap) va_arg(ap, CmdArg *)
//------------------------------------------------------------------- init_args
//-------------------
// ^FUNCTION: init_args - initialize the arg_list member of a CmdLine
//
// ^SYNOPSIS:
// init_args(list)
//
// ^PARAMETERS:
// CmdArgListList & * list;
// -- a reference to the list that is to be initialized.
//
// ^DESCRIPTION:
// Allocate space for the list of command-arguments and insert
// The default arguments onto the list.
//
// ^REQUIREMENTS:
// list should be NULL upon entry
//
// ^SIDE-EFFECTS:
// creates the arg-list and makes "list" point to it.
//
// ^RETURN-VALUE:
// None.
//
// ^ALGORITHM:
// - Create a new arg-list (sure it is NOT self-cleaning, the user is
// responsible for deleting inserted items)
// - Insert the default arguments onto the list
// - Make list point to the newly created list
//-^^----------------
static void
init_args(CmdArgListList * & list)
{
static CmdArgUsage default_help1('?', "?", "; print usage and exit.");
static CmdArgUsage default_help2('H', "Help", "; print usage and exit.");
list = new CmdArgListList ;
list->self_cleaning(1);
CmdArgList * arg_list = new CmdArgList;
arg_list->self_cleaning(0);
CmdArgList * default_list = new CmdArgList;
default_list->self_cleaning(0);
default_list->add(&default_help1);
default_list->add(&default_help2);
list->add(arg_list);
list->add(default_list);
}
//---------------------------------------------------------------- filebasename
//-------
// ^FUNCTION: filebasename
//
// ^SYNOPSIS:
// static const char * filebasename(filename);
//
// ^PARAMETERS:
// const char * filename;
// -- the filename to get the "base" of.
//
// ^DESCRIPTION:
// Extract and return the basename of "filename".
//
// ^REQUIREMENTS:
// "filename" should be non-NULL and non-empty.
//
// ^SIDE-EFFECTS:
// On VAX/VMS, MS-DOS, and OS/2 systems space is allocated (using malloc)
// for the returned value.
//
// ^RETURN-VALUE:
// The basename portion of the filename.
//
// ^ALGORITHM:
// For Unix systems:
// return everything following the rightmost '/'
//
// For VAX/VMS systems:
// make a copy of filename.
// strip off any device name, any directory name.
// strip off any "." extension.
// strip off any version number.
//
// For MS-DOS systems:
// make a copy of filename.
// strip off any drive and/or directory path.
// strip off any "." extension.
//-^^----
static const char *
filebasename(const char * filename)
{
if (filename == NULL) return filename ;
#if (defined(vms) || defined(msdos) || defined(os2))
const char * start, * p1, * p2 ;
char * str, * ext;
# ifdef vms
char * ver;
// remove leading directory and/or device name
p1 = ::strrchr(filename, ':');
p2 = ::strrchr(filename, ']');
# else
// remove leading directory and/or drive name
p1 = ::strrchr(filename, '/');
p2 = ::strrchr(filename, '\\');
# endif
if ((p1 == NULL) && (p2 == NULL)) {
start = filename ;
} else if (p1 && (p2 == NULL)) {
start = p1 + 1;
} else if (p2 && (p1 == NULL)) {
start = p2 + 1;
} else {
start = ((p1 > p2) ? p1 : p2) + 1;
}
str = new char[strlen(start) + 1];
(void) ::strcpy(str, start);
// remove the extension
ext = ::strrchr(str, '.');
if (ext) *ext = '\0' ;
# ifdef vms
// remove the version
ver = ::strrchr(str, ';');
if (ver) *ver = '\0' ;
# endif
return str ;
#else
char * p = ::strrchr(filename, '/') ;
return (p == NULL) ? filename : (p + 1) ;
#endif /* if (vms || msdos || os2) */
}
//--------------------------------------------------------------- class CmdLine
// Contructor with a command-name
CmdLine::CmdLine(const char * cmdname)
: cmd_parse_state(cmd_START_STATE),
cmd_state(cmd_START_STATE),
cmd_flags(DEFAULT_CMDFLAGS),
cmd_status(CmdLine::NO_ERROR),
cmd_nargs_parsed(0),
cmd_name(NULL),
cmd_description(NULL),
cmd_matched_arg(NULL),
cmd_args(NULL),
cmd_err(NULL),
cmd_quit_handler(NULL)
{
name(cmdname);
::init_args(cmd_args);
}
// Constructor with a name and CmdArgs
CmdLine::CmdLine(const char * cmdname, CmdArg * cmdarg1 ...)
: cmd_parse_state(cmd_START_STATE),
cmd_state(cmd_START_STATE),
cmd_flags(DEFAULT_CMDFLAGS),
cmd_status(CmdLine::NO_ERROR),
cmd_nargs_parsed(0),
cmd_name(NULL),
cmd_description(NULL),
cmd_matched_arg(NULL),
cmd_args(NULL),
cmd_err(NULL),
cmd_quit_handler(NULL)
{
name(cmdname);
::init_args(cmd_args);
CmdArgListListIter iter(cmd_args);
CmdArgList * arg_list = iter();
va_list ap;
va_start(ap, cmdarg1);
for (CmdArg * cmdarg = cmdarg1 ; cmdarg ; cmdarg = va_CmdArgP(ap)) {
arg_list->add(cmdarg);
}
va_end(ap);
}
// Constructor with CmdArgs
CmdLine::CmdLine(CmdArg * cmdarg1 ...)
: cmd_parse_state(cmd_START_STATE),
cmd_state(cmd_START_STATE),
cmd_flags(DEFAULT_CMDFLAGS),
cmd_status(CmdLine::NO_ERROR),
cmd_nargs_parsed(0),
cmd_name(NULL),
cmd_description(NULL),
cmd_matched_arg(NULL),
cmd_args(NULL),
cmd_err(NULL),
cmd_quit_handler(NULL)
{
if (cmdarg1 == NULL) return;
::init_args(cmd_args);
CmdArgListListIter iter(cmd_args);
CmdArgList * arg_list = iter();
va_list ap;
va_start(ap, cmdarg1);
for (CmdArg * cmdarg = cmdarg1 ; cmdarg ; cmdarg = va_CmdArgP(ap)) {
arg_list->add(cmdarg);
}
va_end(ap);
}
// Destructor
CmdLine::~CmdLine(void)
{
delete cmd_args;
#if (defined(vms) || defined(msdos) || defined(os2))
delete [] cmd_name;
#endif
}
// Set the name of the command
void
CmdLine::name(const char * progname)
{
static const char unknown_progname[] = "<unknown-program>" ;
#if (defined(vms) || defined(msdos) || defined(os2))
delete [] cmd_name;
#endif
cmd_name = ::filebasename((progname) ? progname : unknown_progname);
}
// Print an error message prefix and return a reference to the
// error output stream for this command
ostream &
CmdLine::error(unsigned quiet) const
{
ostream * os = (cmd_err) ? cmd_err : &cerr ;
if (cmd_name && *cmd_name && !quiet) *os << cmd_name << ": " ;
return *os;
}
// Add an argument to the current list of CmdArgs
CmdLine &
CmdLine::append(CmdArg * cmdarg)
{
CmdArgListListIter iter(cmd_args);
CmdArgList * arg_list = iter();
arg_list->add(cmdarg);
return *this ;
}
// terminate parsing altogether
void
CmdLine::quit(int status) {
if (cmd_quit_handler != NULL) {
(*cmd_quit_handler)(status);
} else {
::exit(status);
}
}
//---------------------------------------------------------- CmdLineCmdArgIter
// Constructors and Destructors
CmdLineCmdArgIter::CmdLineCmdArgIter(CmdLine & cmd)
: iter(NULL)
{
if (cmd.cmd_args) {
CmdArgListListIter listlist_iter(cmd.cmd_args);
CmdArgList * list = listlist_iter();
if (list) iter = new CmdArgListIter(list);
}
}
CmdLineCmdArgIter::CmdLineCmdArgIter(CmdLine * cmd)
: iter(NULL)
{
if (cmd->cmd_args) {
CmdArgListListIter listlist_iter(cmd->cmd_args);
CmdArgList * list = listlist_iter();
if (list) iter = new CmdArgListIter(list);
}
}
CmdLineCmdArgIter::~CmdLineCmdArgIter(void)
{
delete iter;
}
// Return the current argument and advance to the next one.
// Returns NULL if we are already at the end of the list.
//
CmdArg *
CmdLineCmdArgIter::operator()(void)
{
return (iter) ? iter->operator()() : NULL ;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.