From: waltbrad on
I'm having a dickens of a time understanding how this function does
what it does. I thought I understood variable argument lists, but
I've been cracking my skull trying to interpret this code and cannot.

I'm reading Johnson M. Hart's "Windows System Programming". He
includes this function early on in his book as a utility that needs to
be compiled with other his other progam examples. The function is
called "Options.c" it is used to process command line option flags: (-
i, -sl, etc...). So the first program, called cat.c, will be run on
the command line by entering

cat [options] [files]

The particular argument I used was:

cat -s c:\alamo.jpg

The call to the function from the program is:

iFirstFile = Options (argc, argv, _T ("s"), &DashS, NULL);

with _T("s") being the sole flag and $DashS containing a bool value.

Now here is the function:

================
DWORD Options (int argc, LPCTSTR argv [], LPCTSTR OptStr, ...)

/* argv is the command line.
The options, if any, start with a '-' in argv[1], argv[2], ...
OptStr is a text string containing all possible options,
in one-to-one correspondence with the addresses of Boolean variables
in the variable argument list (...).
These flags are set if and only if the corresponding option
character occurs in argv [1], argv [2], ...
The return value is the argv index of the first argument beyond the
options. */

{
va_list pFlagList;
LPBOOL pFlag;
int iFlag = 0, iArg;

va_start (pFlagList, OptStr);

while ((pFlag = va_arg (pFlagList, LPBOOL)) != NULL
&& iFlag < (int)_tcslen (OptStr)) {
*pFlag = FALSE;
for (iArg = 1; !(*pFlag) && iArg < argc && argv [iArg] [0] == '-';
iArg++)
*pFlag = _memtchr (argv [iArg], OptStr [iFlag],
_tcslen (argv [iArg])) != NULL;
iFlag++;
}

va_end (pFlagList);

for (iArg = 1; iArg < argc && argv [iArg] [0] == '-'; iArg++);

return iArg;
}
====================

I take it that argc is still the value 3. _T("s") is OptStr. But,
I'm not sure what argv(1), argv(2) is. The function seems to be
expecting argv to be pBOOL, but I don't know how this jives with the
for statement where it expects argv[iARG][0]=='-'

So, I've tried to let the argv equal my command line entries. In that
case argv[1] would be cat. There is no "-" there so the for loop would
be bypassed and you would get argv[2] as "-s". But as you enter the
for loop it still going to reference argv[1][0]

So, I just don't get the logic employed here. The programs run okay.
No problem there. But not being able to understand this program is
causing me problems understanding programs that rely on this
function.

I hope I've expressed my confusion well enough for someone to correct
me.

Thanks.




From: Jim Langston on
"waltbrad" <waltbrad(a)hotmail.com> wrote in message
news:90f072ba-811c-4b6a-a641-7924a3991c1b(a)e1g2000hsh.googlegroups.com...
> I'm having a dickens of a time understanding how this function does
> what it does. I thought I understood variable argument lists, but
> I've been cracking my skull trying to interpret this code and cannot.
>
> I'm reading Johnson M. Hart's "Windows System Programming". He
> includes this function early on in his book as a utility that needs to
> be compiled with other his other progam examples. The function is
> called "Options.c" it is used to process command line option flags: (-
> i, -sl, etc...). So the first program, called cat.c, will be run on
> the command line by entering
>
> cat [options] [files]
>
> The particular argument I used was:
>
> cat -s c:\alamo.jpg

Okay, when you pass arguments to a program from the command line, main will
accept two parameters. a number of arguments passed, and a list of pointers
to the arguments themselves. argc stands for "Argument Count" (or I think
so anyway) and argv for "Argument Variables" (or so I think of them). There
is always one argument, argument 0, which is the name of the program
executed, although it is platform dependant. argv is a pointer to an array
of pointers to the c-string arguments. argv[0] would point to something
like "cat" or "/cat" or "c:/my programs/cat.exe" or whatever. If you don't
need it (and you usually don't) then you shouldn't worry about this one.

Now, in your case argc shoudl contain the value 3. 3 parameters, Parm 0,
the name of the program. parm 1 "-s" and parm 2 "c:\alamo.jpg". If you
wanted to look at the first real parm (-s) it would be argv[1] which would
point to a string "-s". The first character would be argv[1][0] which would
be an '-' (remember, arrays in c and c++ are 0 bound). Now with that in
mind, look over the function and see if you can figure out what's going on.
If you still get stuck post again.

> The call to the function from the program is:
>
> iFirstFile = Options (argc, argv, _T ("s"), &DashS, NULL);
>
> with _T("s") being the sole flag and $DashS containing a bool value.
>
> Now here is the function:
>
> ================
> DWORD Options (int argc, LPCTSTR argv [], LPCTSTR OptStr, ...)
>
> /* argv is the command line.
> The options, if any, start with a '-' in argv[1], argv[2], ...
> OptStr is a text string containing all possible options,
> in one-to-one correspondence with the addresses of Boolean variables
> in the variable argument list (...).
> These flags are set if and only if the corresponding option
> character occurs in argv [1], argv [2], ...
> The return value is the argv index of the first argument beyond the
> options. */
>
> {
> va_list pFlagList;
> LPBOOL pFlag;
> int iFlag = 0, iArg;
>
> va_start (pFlagList, OptStr);
>
> while ((pFlag = va_arg (pFlagList, LPBOOL)) != NULL
> && iFlag < (int)_tcslen (OptStr)) {
> *pFlag = FALSE;
> for (iArg = 1; !(*pFlag) && iArg < argc && argv [iArg] [0] == '-';
> iArg++)
> *pFlag = _memtchr (argv [iArg], OptStr [iFlag],
> _tcslen (argv [iArg])) != NULL;
> iFlag++;
> }
>
> va_end (pFlagList);
>
> for (iArg = 1; iArg < argc && argv [iArg] [0] == '-'; iArg++);
>
> return iArg;
> }
> ====================
>
> I take it that argc is still the value 3. _T("s") is OptStr. But,
> I'm not sure what argv(1), argv(2) is. The function seems to be
> expecting argv to be pBOOL, but I don't know how this jives with the
> for statement where it expects argv[iARG][0]=='-'
>
> So, I've tried to let the argv equal my command line entries. In that
> case argv[1] would be cat. There is no "-" there so the for loop would
> be bypassed and you would get argv[2] as "-s". But as you enter the
> for loop it still going to reference argv[1][0]
>
> So, I just don't get the logic employed here. The programs run okay.
> No problem there. But not being able to understand this program is
> causing me problems understanding programs that rely on this
> function.
>
> I hope I've expressed my confusion well enough for someone to correct
> me.
>
> Thanks.
>
>
>
>


From: Alf P. Steinbach on
* waltbrad:
> I'm having a dickens of a time understanding how this function does
> what it does. I thought I understood variable argument lists, but
> I've been cracking my skull trying to interpret this code and cannot.
>
> I'm reading Johnson M. Hart's "Windows System Programming". He
> includes this function early on in his book as a utility that needs to
> be compiled with other his other progam examples. The function is
> called "Options.c" it is used to process command line option flags: (-
> i, -sl, etc...). So the first program, called cat.c, will be run on
> the command line by entering
>
> cat [options] [files]
>
> The particular argument I used was:
>
> cat -s c:\alamo.jpg
>
> The call to the function from the program is:
>
> iFirstFile = Options (argc, argv, _T ("s"), &DashS, NULL);
>
> with _T("s") being the sole flag and $DashS containing a bool value.
>
> Now here is the function:
>
> ================
> DWORD Options (int argc, LPCTSTR argv [], LPCTSTR OptStr, ...)

argc and argv are the arguments passed to main.


> /* argv is the command line.
> The options, if any, start with a '-' in argv[1], argv[2], ...
> OptStr is a text string containing all possible options,
> in one-to-one correspondence with the addresses of Boolean variables
> in the variable argument list (...).
> These flags are set if and only if the corresponding option
> character occurs in argv [1], argv [2], ...
> The return value is the argv index of the first argument beyond the
> options. */
>
> {
> va_list pFlagList;
> LPBOOL pFlag;
> int iFlag = 0, iArg;
>
> va_start (pFlagList, OptStr);

Sets up traversal of variable arguments, the "...".


> while ((pFlag = va_arg (pFlagList, LPBOOL)) != NULL
> && iFlag < (int)_tcslen (OptStr)) {

Each variable argument is a LPBOOL. Address of next variable argument
is stored in pFlag. If NULL no more arguments to process. As extra
"precaution" the programmer checks that the corresponding options in
OptStr haven't been exhausted.



> *pFlag = FALSE;
> for (iArg = 1; !(*pFlag) && iArg < argc && argv [iArg] [0] == '-';
> iArg++)
> *pFlag = _memtchr (argv [iArg], OptStr [iFlag],
> _tcslen (argv [iArg])) != NULL;
> iFlag++;
> }

Walks through the 'main' arguments (except first), as long as they are
option arguments ('-' prefix) and option not found, and checks whether
any corresponds to the flag being processed in the outer while loop.


>
> va_end (pFlagList);

Cleaning up traversal of variable arguments.


> for (iArg = 1; iArg < argc && argv [iArg] [0] == '-'; iArg++);

Counting option arguments.

>
> return iArg;
> }


I think it's a good idea to use C++ instead of C.

typedef std::vector<std::string> StringVector;
typedef std::map<char, bool> BoolOptions;

void getValues( BoolOptions& options, StringVector const& args )
{
typedef BoolOptions::iterator OptionsIter;
for( OptionsIter it = options.begin(); it != options.end();
++it )
{
for(
std::size_t i = 1;
i < args.size() && args[i].substr( 0, 1 ) == "-";
++i )
{
bool const optionIsSet =
(args[i].find( it->first ) != std::string::npos);
if( optionIsSet )
{
it->second = true;
break;
}
}
}
}

Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?