[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?
From: |
Lorenzo Bettini |
Subject: |
Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static? |
Date: |
Thu, 11 May 2006 11:37:11 +0200 |
User-agent: |
Thunderbird 1.5.0.2 (X11/20060501) |
Andre Noll wrote:
On 12:41, Lorenzo Bettini wrote:
on what happend during the first call. How about coding up an own
version of getopt() with sane semantics?
that would be the other possibility I was thinking of... but I'm quite
scared of writing another version of getopt with the same semantics...
would you be interested in that?
Something like the attached?
This is glibc's getopt() and getopt_long() in a single file, with
its monster getopt_internal_r() function split up into three smaller
functions, and some glibc cruft removed.
It's still a bit crufty, so it sure needs some more work. But it is
hopefully more readable than the original glibc source and definitely
much shorter.
The getopt() and getopt_long() functions of this version take the same
arguments as the original ones, so they may used as a drop-in
replacement for the corresponding functions of the system.
At the bottom of the file there's a test included. Activate it with
gcc -Wall -DTEST getopt.c
Regards
Andre
Hi Andre
thanks for the file, I guess I have the problem clear now.
I think you're right about the fact that even with non-dynamic memory
the problem still raises (although I haven't tried it I guess it's like
you said).
I think the problem is a sort of design problem of the getopt
implementation itself, or, at least, the implementation is correct but
under the (quite strong) condition that if you call one of the functions
twice you have to use the same arguments (I mean the same argv).
I'd like to post a bug report at the glibc bugzilla about this, but
first I'd like to have a confirmation from you about the problem (by the
way could you please send me, in private, all the original sources of
glibc of getopt stuff you extracted this file from?).
struct getopt_data {
/*
* These have exactly the same meaning as the corresponding global
variables,
* except that they are used for the reentrant versions of getopt.
*/
int optind;
int opterr;
int optopt;
char *optarg;
/* True if the internal members have been initialized. */
int initialized;
/*
* The next char to be scanned in the option-element in which the last
option
* character we returned was found. This allows us to pick up the scan
where
* we left off. If this is zero, or a null string, it means resume the
scan by
* advancing to the next ARGV-element.
*/
char *nextchar;
/*
* Describe the part of ARGV that contains non-options that have been
skipped.
* `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is
* the index after the last of them.
*/
int first_nonopt;
int last_nonopt;
};
so internally this struct is used, instead of the global variables, and
the problem, I think, is in the last three fields...
/*
* Index in ARGV of the next element to be scanned. This is used for
* communication to and from the caller and for communication between
* successive calls to `getopt'.
*
* On entry to `getopt', zero means this is the first call; initialize.
*
* When `getopt' returns -1, this is the index of the first of the non-option
* elements that the caller should itself scan.
*
* Otherwise, `optind' communicates from one call to the next how much of ARGV
* has been scanned so far.
*
* 1003.2 says this must be 1 before any call.
*/
int optind = 1;
this is the confirmation that the standard says that it must be 1, but
they use the 0 value for initializations...
/*
* Exchange two adjacent subsequences of ARGV. One subsequence is elements
* [first_nonopt,last_nonopt) which contains all the non-options that have been
* skipped so far. The other is elements [last_nonopt,optind), which contains
* all the options processed since those non-options were skipped.
* `first_nonopt' and `last_nonopt' are relocated so that they describe the new
* indices of the non-options in ARGV after they are moved.
*/
static void exchange(char **argv, struct getopt_data *d)
{
int bottom = d->first_nonopt;
int middle = d->last_nonopt;
int top = d->optind;
char *tem;
<snip>
this function exchanges elements of argv according to the values
d->first_nonopt and d->last_nonopt... so their values must be correct
otherwise we spoil memory...
/* Initialize the internal data when the first call is made. */
static void getopt_initialize(struct getopt_data *d)
{
/*
* Start processing options with ARGV-element 1 (since ARGV-element 0
* is the program name); the sequence of previously skipped non-option
* ARGV-elements is empty.
*/
d->first_nonopt = d->last_nonopt = d->optind;
d->nextchar = NULL;
d->initialized = 1;
}
this initialization function resets d->first_nonopt and d->last_nonopt
static int getopt_internal_r(int argc, char *const *argv, const char *optstring,
const struct option *longopts, int *longind,
struct getopt_data *d)
{
int ret, print_errors = d->opterr;
if (optstring[0] == ':')
print_errors = 0;
if (argc < 1)
return -1;
d->optarg = NULL;
if (d->optind == 0 || !d->initialized) {
if (d->optind == 0)
d->optind = 1; /* Don't scan ARGV[0], the program
name. */
getopt_initialize(d);
}
if (d->nextchar == NULL || *d->nextchar == '\0') {
ret = shuffle_argv(argc, argv, longopts, d);
if (ret)
return ret;
}
this is the point where the struct is initialized, i.e., only when
d->optind == 0 (or !d->initialized)
static int getopt_internal(int argc, char *const *argv, const char *optstring,
const struct option *longopts, int *longind)
{
int result;
/* Keep a global copy of all internal members of d */
static struct getopt_data d;
d.optind = optind;
d.opterr = opterr;
result = getopt_internal_r(argc, argv, optstring, longopts,
longind, &d);
optind = d.optind;
optarg = d.optarg;
optopt = d.optopt;
return result;
}
the struct that is passed to getopt_internal_r is static, so its fields
are initialized to 0 only once: the first time getopt_internal_r is
called the struct is correctly initialized, the other times it is not
(unless you set optind to 0, which is not standard)
what do you think?
I'd really like to hear from glibc people to know whether this is the
intended behavior (which is not documented anyway)
I hope to hear from you soon
cheers
Lorenzo
--
+-----------------------------------------------------+
| Lorenzo Bettini ICQ# lbetto, 16080134 |
| PhD in Computer Science |
| Dip. Sistemi e Informatica, Univ. di Firenze |
| Florence - Italy (GNU/Linux User # 158233) |
| Home Page : http://www.lorenzobettini.it |
| http://music.dsi.unifi.it XKlaim language |
| http://www.purplesucker.com Deep Purple Cover Band |
| http://www.gnu.org/software/src-highlite |
| http://www.gnu.org/software/gengetopt |
| http://www.lorenzobettini.it/software/gengen |
| http://www.lorenzobettini.it/software/doublecpp |
+-----------------------------------------------------+
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Andre Noll, 2006/05/01
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Lorenzo Bettini, 2006/05/02
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Andre Noll, 2006/05/04
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Lorenzo Bettini, 2006/05/05
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Andre Noll, 2006/05/06
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Lorenzo Bettini, 2006/05/07
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Andre Noll, 2006/05/08
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?,
Lorenzo Bettini <=
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Andre Noll, 2006/05/13
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Lorenzo Bettini, 2006/05/14
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Andre Noll, 2006/05/16
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Lorenzo Bettini, 2006/05/16
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Lorenzo Bettini, 2006/05/14
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Andre Noll, 2006/05/16
- Re: [help-gengetopt] make cmd_line_list and cmd_line_list_tmp static?, Lorenzo Bettini, 2006/05/16