Category : C++ Source Code
Archive   : CMDLNC.ZIP
Filename : CMDLN.CPP

 
Output of file : CMDLN.CPP contained in archive : CMDLNC.ZIP
/*

cmdln.cpp
3-8-91
Command line option parser

Copyright 1991
John W. Small
All rights reserved
Use freely but acknowledge authorship and copyright.
CIS: 73757,2233

PSW / Power SoftWare
P.O. Box 10072
McLean, Virginia 22102 8072
(703) 759-3838



Notes:


1. Call getOption() repeatedly to parse command
line arguments. The options to look for along with
the argc and argv must be passed as parameters to
the constructor CmdLn() or the member function
CmdLnReset(). The options string is a string of
the option characters that may appear on your
programs command line after the switch character,
'/' or '-' for DOS. If an option takes argument
then a colon must immediately follow that option
character in the options string to let
getOption() know to look for the argument. The
syntax for the option string is as follows:

options string ::= {optch[:]}*

Your read the syntax as: An options string is zero
or more (the "*" indicates this) option characters
any of which may be followed by a colon to indicate
that the option has an argument.


2. GetOption() returns the current option
character being processed along with any argument
in the variable optArg. OptArg is valid only
when an option requiring an argument is processed.
If the argument is missing then optArg == 0. If
the current option character being processed is
unrecognized, i.e. not in the options string passed
to CmdLn(), then getOption() returns '?' with
the unrecognized character stored in optNot. This
is the only time that optNot is valid!
getOption() returns -1 when there are no more
options to process. The variable, optCh,
maintains a copy of the latest value returned by
getOption().


3. When your program is invoked, getOption()
recognizes clusters of command line options. A
cluster is the switch character followed immediately
by any number of option characters, no white space.
The options clusters must preceed any other command
line parameters since getOption() stops processing
on the first parameter that is not a switch. This
is the Unix convention. If you would like to be
able to intersperse command line switches with other
parameters on the command line then call
lookForMoreOptions() to reenable getOption()
to continue looking for more options. If an option
takes an argument then the option's character must
be the last option in the cluster with the argument
immediately following or separated by white space.
The argument must not have any white space, though
it may contain the switch character.

command line option cluster ::=

{'/'|'-'}{[optch]*argch[whitespace]argument}|optch+

Wow! That reads: a command line option cluster
starts with the switch character ('/' or '-' in DOS)
with one or more option characters (+ means one or
more) or (| means or) any number of option
characters, only the last of which is allowed to
take an argument. The argument can be either tacked
on to the end of the option cluster or stand off by
itself. In either case, argument contains no white
space! If a switch character appears in a cluster
by itself or if two switch characters lead off a
cluster then no more options are processed and the
next parameter starts the non switched arguments.
This allows the first non switched argument to start
with the switch character, i.e. let the preceeding
cluster be either a single switch character or lead
off with two switch characters. The switch
characters are defined in the static variable:
switches. Switches is currently defined for MS DOS.


4. For example, if the options string contains
"C:af:z" then 'C' and 'f' take arguments. A valid
command line would be:

cmd /afnew /zC cmdfile outfile

with repeated calls to getOption() returning:

'a'
'f' with optArg == "new"
'z'
'C' with optArg == "cmdfile"
-1 with Argi() == 4

The variable, argi, is the index into the next
unprocessed argv cell. You can use Argi() to
initialize your index into the non-switched
command line parameters.


5. Compile and run cmdln.cpp by defining
TEST_CMDLN_CPP towards the end of this file.
By defining TEST_CMDLN_CPP you can compile the
demo/test version of cmdln.cpp. Be sure you
understand the demo/test code before using
cmdln.cpp.

*/

#include /* strchr() */
#include

static char switches[] = "/-";
/*
Switches is initialized here for DOS switch
characters. Change as necessary for your
host OS shell.
*/

void CmdLn::CmdLnReset(int argc, char *argv[],
char *options)
{
this->argv = argv;
this->options = options;
opt = (char *) 0;
this->argc = argc;
optEnd = 0;
optCh = optNot = '\0';
optArg = (char *) 0;
argi = 1;
}

int CmdLn::getOption(void)
{

char *lookup;

optArg = (char *)0;
if (optEnd) /* no more options allowed */
return (optCh = 0);
if (!opt || (*opt == '\0')) {
if (argi >= argc) /* no more parameters */
return (optEnd = optCh = -1);
/* end of options */
opt = argv[argi];
/* next possible option cluster */
if (!strchr(switches,*opt))
/* Not an option cluster? */
return (optEnd = optCh = -1);
/* start non option parameters */
argi++; /* next possible parameter */
opt++; /* next possible option */
if (!*opt || strchr(switches,*opt))
/* Two switches or one by itself */
return (optEnd = optCh = -1);
/* means end of options */
}
if ((lookup = strchr(
/* validate option character */
options? options : "",
optNot = *opt++))
== (char *)0)
return (optCh = '?');
/* unknown option */
if (lookup[1] == ':') {
/* option takes argument */
if (*opt != '\0')
/* Is argument in this parameter? */
optArg = opt;
else if (argi < argc)
/* Is argument in next parameter? */
optArg = argv[argi++];
opt = (char *) 0;
/* no more options in this parameter */
}
return (optCh = *lookup);
/* return option */
}

void CmdLn::nextCluster(void) { opt = (char *) 0; }
/* start processing in next cluster */

void CmdLn::lookForMoreOptions(void)
{
if (optEnd) {
opt = (char *) 0;
argi++;
optEnd = 0;
}
}


/*
To use cmdln.cpp in your own programs be sure to
comment out the following "#define TEST_CMDLN_CPP."
*/
#define TEST_CMDLN_CPP
#ifdef TEST_CMDLN_CPP

#include

char *help[] = {
"\nusage: cmdln -ooptions *",
"\nwhere 'options' consists of the letters to "
"look for, and",
"\n '*' are the command line arguments to"
" be parsed by 'options.'",
"\n For the purposes of this test 'o' "
"switches are skipped.",
"\n\nFor example, with the command line: ",
"\n\n cmdln /oC:af:z /afnew /zC cmdfile outfile",
"\n\nthe 'options' string is 'C:af:z', which "
"means that this particular invocation",
"\nof the demo will recognize 'C', 'a', 'f' "
"and 'z' as switch options. 'C' and",
"\n'f' take arguments, which is indicated by"
" the colon after each in the 'options'",
"\nstring. Switch options are introduced by "
"'/' or '-' in DOS. The 'options'",
"\nstring is then used to parse the rest of "
"the command line. In this case it",
"\nrecognizes 'a', 'f' with argument 'new', "
"'z', and 'C' with argument 'cmdfile.'",
"\nRun this demo with command lines similar "
"to this example to see how it",
"\nworks. Then besure to read the notes in "
"cmdln.cpp for complete instructions on",
"\nhow to use the CmdLn class. The source "
"code of this demo is also found in",
"\ncmdln.cpp. Be sure to study how I coded "
"the demo. You will then be ready to",
"\nstart coding with the CmdLn class.\n",
0
};

main(int argc, char *argv[])
{
int i;
CmdLn CL(argc,argv,"o:");

(void) CL.getOption();
if ((CL.optCh != 'o') || !CL.optArg) {
for (i = 0; help[i]; i++)
printf("%s",help[i]);
return 1;
}
printf("\nTest the CmdLn class instance 'CL'");
printf(" with the following command line:");
printf("\n\n ");
for (i = 0; i < argc; i++)
printf("%s ",argv[i]);
printf("\n\nParse for the following options: \n");
for (i = 0; CL.optArg[i]; i++) {
printf("\n %c",CL.optArg[i]);
if (CL.optArg[i+1] == ':') {
i++;
printf(" with argument");
}
}
printf("\n\nParameters parsed by 'CL' as ...\n");

CL.CmdLnReset(argc, argv, CL.optArg);
do {
while (CL.getOption() != -1)
if (CL.optCh == '?')
if (CL.optNot == 'o')
CL.nextCluster();
else
printf("\n CL.optNot: %c",CL.optNot);
else {
printf("\n CL.optCh: %c",CL.optCh);
printf(" CL.optArg: %s",CL.optArg);
}
if (CL.Argi() < argc) {
printf("\n CL.Argi(): %d",CL.Argi());
printf(" argv[%d]: %s",
CL.Argi(),argv[CL.Argi()]);
}
CL.lookForMoreOptions();
} while (CL.Argi() < argc);
printf("\n");
return 0;
}

#endif

  3 Responses to “Category : C++ Source Code
Archive   : CMDLNC.ZIP
Filename : CMDLN.CPP

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/