Reputation: 77
I am tasked with rewriting the get_some_switches() function in Larry Wall's patch 1.3 (https://groups.google.com/g/mod.sources/c/xSQM63e39YY) using getopt_long().
get_some_switches()
{
register char *s;
rejname[0] = '\0';
if (!Argc)
return;
for (Argc--,Argv++; Argc; Argc--,Argv++) {
s = Argv[0];
if (strEQ(s,"+")) {
return; /* + will be skipped by for loop */
}
if (*s != '-' || !s[1]) {
if (filec == MAXFILEC)
fatal("Too many file arguments.\n");
filearg[filec++] = savestr(s);
}
else {
switch (*++s) {
case 'b':
origext = savestr(Argv[1]);
Argc--,Argv++;
break;
case 'c':
diff_type = CONTEXT_DIFF;
break;
case 'd':
if (chdir(Argv[1]) < 0)
fatal("Can't cd to %s.\n",Argv[1]);
Argc--,Argv++;
break;
case 'D':
do_defines++;
Sprintf(if_defined, "#ifdef %s\n", Argv[1]);
Sprintf(not_defined, "#ifndef %s\n", Argv[1]);
Sprintf(end_defined, "#endif %s\n", Argv[1]);
Argc--,Argv++;
break;
case 'e':
diff_type = ED_DIFF;
break;
case 'l':
canonicalize = TRUE;
break;
case 'n':
diff_type = NORMAL_DIFF;
break;
case 'o':
outname = savestr(Argv[1]);
Argc--,Argv++;
break;
case 'p':
usepath = TRUE; /* do not strip path names */
break;
case 'r':
Strcpy(rejname,Argv[1]);
Argc--,Argv++;
break;
case 'R':
reverse = TRUE;
break;
case 's':
verbose = FALSE;
break;
#ifdef DEBUGGING
case 'x':
debug = atoi(s+1);
break;
#endif
default:
fatal("Unrecognized switch: %s\n",Argv[0]);
}
}
}
}
If I am reading the code correctly, this loop doesn't stop unless it hit a '+' or until it runs out of arguments and is incrementing argc down and argv up as it looks for flags and arguments. This way, when this function gets called again in reinitialize_almost_everything(), argc and argv is already pointing further in than it would have if it were called the first time.
In replacing it with getopt_long, will I have to find a way to increment argc and argv so that it will be ready for the next call, or will getopt_long remember where it left off?
Also, what does the condition !s[1] mean?
Upvotes: 1
Views: 51
Reputation: 180048
Does getopt_long and get_opt advance the argv pointer?
Like all C functions, getopt()
and getopt_long()
receive their parameters by value. They cannot, therefore, alter the caller's corresponding arguments.
Where an argument is a pointer, however, such as argv
, a function can modify the data to which it points. GNU's implementation of getopt()
and getopt_long()
makes use of this capability, over several calls, to permute the non-option arguments to the end of the list. This poses no impediment to parsing the options again, however.
If I am reading the code correctly, this loop doesn't stop unless it hit a '+' or until it runs out of arguments and is incrementing argc down and argv up as it looks for flags and arguments. This way, when this function gets called again in reinitialize_almost_everything(), argc and argv is already pointing further in than it would have if it were called the first time.
The function presented works with variables Argc
and Argv
that are external to the function. The code suggests that these have the same types as and form similar to the parameters to a C main()
function, and the function does modify these. But it is not clear where or when these variables get their initial values, or exactly how those values are related to those of the main()
function's parameters, which are local to main()
. Or what other functions, such as reinitialize_almost_everything()
, may do to those values.
In replacing it with getopt_long, will I have to find a way to increment argc and argv so that it will be ready for the next call, or will getopt_long remember where it left off?
getopt()
and getopt_long()
track their progress through the argument list. During a given pass through an argument list, callers are expected to pass the same parameter values each time.
Also, what does the condition !s[1] mean?
The exclamation point (!
) is the logical negation operator. Thus, !s[1]
evaluates to 1 when s[1]
evaluates to 0; otherwise it evaluates to 0. In the particular context where that expression appears in the code presented, it is testing whether the char
at index 1 in s
is a string terminator.
Upvotes: 2