2004-03-03 Marcus Brinkmann * include/getopt.h: Use libc_hidden_proto for getopt_long_r and getopt_long_only_r instead for getopt_long and getopt_long_only. * posix/getopt1.c: Use libc_hidden_def for getopt_long_r and getopt_long_only_r instead for getopt_long and getopt_long_only. * argp/argp-parse.c [_LIBC]: Do not include . [!_LIBC && HAVE_CTHREADS_H]: Do not include . [!_LIBC] (_argp_hang): Make static. (getopt_lock, LOCK_GETOPT, UNLOCK_GETOPT): Remove. (_argp_unlock_xxx): Remove. (parser_init): Do not use LOCK_GETOPT. (parser_finalize): Do not use UNLOCK_GETOPT. (struct parser): New member OPT_DATA. (parser_init): Initialize parser->opt_data. Use parser->opt_data.opterr instead of opterr. (parser_parse_opt): Use parser->opt_data.optarg instead optarg. (parser_parse_next): Likewise. Use parser->opt_data.optind instead optind. Use parser->opt_data.optopt instead of optopt. Call getopt_long_only_r and getopt_long_r instead of getopt_long_only and getopt_long, and pass the extra argument. diff -ru ../cvs/libc/argp/argp-parse.c libc/argp/argp-parse.c --- ../cvs/libc/argp/argp-parse.c 2003-11-29 08:18:50.000000000 +0100 +++ libc/argp/argp-parse.c 2004-03-03 07:44:53.000000000 +0100 @@ -1,5 +1,5 @@ /* Hierarchial argument parsing, layered over getopt - Copyright (C) 1995-2000, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -62,14 +62,6 @@ # define N_(msgid) (msgid) #endif -#if _LIBC - 0 -#include -#else -#ifdef HAVE_CTHREADS_H -#include -#endif -#endif /* _LIBC */ - #include "argp.h" #include "argp-namefrob.h" @@ -97,14 +89,8 @@ /* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep for one second intervals, decrementing _ARGP_HANG until it's zero. Thus you can force the program to continue by attaching a debugger and setting - it to 0 yourself. - - XXX This variable used to be exported. But there seems to be no - need, at least not inside libc. */ -#ifdef _LIBC -static -#endif -volatile int _argp_hang; + it to 0 yourself. */ +static volatile int _argp_hang; #define OPT_PROGNAME -2 #define OPT_USAGE -3 @@ -223,42 +209,7 @@ else return -1; } - -/* If we can, we regulate access to getopt, which is non-reentrant, with a - mutex. Since the case we're trying to guard against is two different - threads interfering, and it's possible that someone might want to call - argp_parse recursively (they're careful), we use a recursive lock if - possible. */ - -#if _LIBC - 0 - -__libc_lock_define_initialized_recursive (static, getopt_lock) -#define LOCK_GETOPT __libc_lock_lock_recursive (getopt_lock) -#define UNLOCK_GETOPT __libc_lock_unlock_recursive (getopt_lock) - -#else /* !_LIBC */ -#ifdef HAVE_CTHREADS_H -static struct mutex getopt_lock = MUTEX_INITIALIZER; -#define LOCK_GETOPT mutex_lock (&getopt_lock) -#define UNLOCK_GETOPT mutex_unlock (&getopt_lock) - -#else /* !HAVE_CTHREADS_H */ - -#define LOCK_GETOPT (void)0 -#define UNLOCK_GETOPT (void)0 - -#endif /* HAVE_CTHREADS_H */ -#endif /* _LIBC */ - -/* This hack to allow programs that know what's going on to call argp - recursively. If someday argp is changed not to use the non-reentrant - getopt interface, we can get rid of this shit. XXX */ -void -_argp_unlock_xxx (void) -{ - UNLOCK_GETOPT; -} /* The state of a `group' during parsing. Each group corresponds to a particular argp structure from the tree of such descending from the top @@ -320,6 +271,8 @@ /* LONG_OPTS is the array of getop long option structures for the union of all the groups of options. */ struct option *long_opts; + /* OPT_DATA is the getopt data used for the re-entrant getopt. */ + struct getopt_data opt_data; /* States of the various parsing groups. */ struct group *groups; @@ -554,6 +507,7 @@ parser->child_inputs = parser->storage + GLEN; parser->long_opts = parser->storage + GLEN + CLEN; parser->short_opts = parser->storage + GLEN + CLEN + LLEN; + parser->opt_data = (struct getopt_data) GETOPT_DATA_INITIALIZER; memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *)); parser_convert (parser, argp, flags); @@ -597,19 +551,16 @@ if (err) return err; - /* Getopt is (currently) non-reentrant. */ - LOCK_GETOPT; - if (parser->state.flags & ARGP_NO_ERRS) { - opterr = 0; + parser->opt_data.opterr = 0; if (parser->state.flags & ARGP_PARSE_ARGV0) /* getopt always skips ARGV[0], so we have to fake it out. As long as OPTERR is 0, then it shouldn't actually try to access it. */ parser->state.argv--, parser->state.argc++; } else - opterr = 1; /* Print error messages. */ + parser->opt_data.opterr = 1; /* Print error messages. */ if (parser->state.argv == argv && argv[0]) /* There's an argv[0]; use it for messages. */ @@ -630,8 +581,6 @@ { struct group *group; - UNLOCK_GETOPT; - if (err == EBADKEY && arg_ebadkey) /* Suppress errors generated by unparsed arguments. */ err = 0; @@ -793,7 +742,8 @@ for (group = parser->groups; group < parser->egroup; group++) if (group->short_end > short_index) { - err = group_parse (group, &parser->state, opt, optarg); + err = group_parse (group, &parser->state, opt, + parser->opt_data.optarg); break; } } @@ -802,7 +752,8 @@ the user value in order to preserve the sign. */ err = group_parse (&parser->groups[group_key - 1], &parser->state, - (opt << GROUP_BITS) >> GROUP_BITS, optarg); + (opt << GROUP_BITS) >> GROUP_BITS, + parser->opt_data.optarg); if (err == EBADKEY) /* At least currently, an option not recognized is an error in the @@ -848,15 +799,20 @@ if (parser->try_getopt && !parser->state.quoted) /* Give getopt a chance to parse this. */ { - optind = parser->state.next; /* Put it back in OPTIND for getopt. */ - optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */ + /* Put it back in OPTIND for getopt. */ + parser->opt_data.optind = parser->state.next; + /* Distinguish KEY_ERR from a real option. */ + parser->opt_data.optopt = KEY_END; if (parser->state.flags & ARGP_LONG_ONLY) - opt = getopt_long_only (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0); + opt = getopt_long_only_r (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0, + &parser->opt_data); else - opt = getopt_long (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0); - parser->state.next = optind; /* And see what getopt did. */ + opt = getopt_long_r (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0, + &parser->opt_data); + /* And see what getopt did. */ + parser->state.next = parser->opt_data.optind; if (opt == KEY_END) /* Getopt says there are no more options, so stop using @@ -872,7 +828,7 @@ here, whatever happens. */ parser->state.quoted = parser->state.next; } - else if (opt == KEY_ERR && optopt != KEY_END) + else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END) /* KEY_ERR can have the same value as a valid user short option, but in the case of a real error, getopt sets OPTOPT to the offending character, which can never be KEY_END. */ @@ -898,15 +854,15 @@ /* A non-option arg; simulate what getopt might have done. */ { opt = KEY_ARG; - optarg = parser->state.argv[parser->state.next++]; + parser->opt_data.optarg = parser->state.argv[parser->state.next++]; } } if (opt == KEY_ARG) /* A non-option argument; try each parser in turn. */ - err = parser_parse_arg (parser, optarg); + err = parser_parse_arg (parser, parser->opt_data.optarg); else - err = parser_parse_opt (parser, opt, optarg); + err = parser_parse_opt (parser, opt, parser->opt_data.optarg); if (err == EBADKEY) *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); diff -ru ../cvs/libc/include/getopt.h libc/include/getopt.h --- ../cvs/libc/include/getopt.h 2002-09-01 14:37:56.000000000 +0200 +++ libc/include/getopt.h 2004-03-03 07:07:39.000000000 +0100 @@ -5,8 +5,8 @@ # ifdef _GETOPT_H -libc_hidden_proto (getopt_long) -libc_hidden_proto (getopt_long_only) +libc_hidden_proto (getopt_long_r) +libc_hidden_proto (getopt_long_only_r) /* Now define the internal interfaces. */ extern void __getopt_clean_environment (char **__env); diff -ru ../cvs/libc/posix/getopt1.c libc/posix/getopt1.c --- ../cvs/libc/posix/getopt1.c 2004-03-03 07:45:39.000000000 +0100 +++ libc/posix/getopt1.c 2004-03-03 07:07:07.000000000 +0100 @@ -121,8 +121,8 @@ } # ifdef _LIBC -libc_hidden_def (getopt_long) -libc_hidden_def (getopt_long_only) +libc_hidden_def (getopt_long_r) +libc_hidden_def (getopt_long_only_r) # endif #endif /* Not ELIDE_CODE. */