main: use our own getopt_long() implementation always, as pkg_getopt_long(). (closes #24)

pull/29/head
William Pitcock 2012-07-20 13:46:14 -05:00
parent 9e30e2a7bb
commit 9d7672fc9a
4 changed files with 100 additions and 113 deletions

View File

@ -2,7 +2,7 @@ AC_PREREQ([2.68])
AC_INIT([pkgconf], [0.8], [http://github.com/nenolod/pkgconf/issues]) AC_INIT([pkgconf], [0.8], [http://github.com/nenolod/pkgconf/issues])
AC_CONFIG_SRCDIR([pkg.c]) AC_CONFIG_SRCDIR([pkg.c])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CHECK_FUNCS([getopt_long strlcpy strlcat strndup]) AC_CHECK_FUNCS([strlcpy strlcat strndup])
AC_PROG_CPP AC_PROG_CPP
AC_PROG_CC AC_PROG_CC

View File

@ -58,8 +58,6 @@
#include "config.h" #include "config.h"
#ifndef HAVE_GETOPT_LONG
#include "getopt_long.h" #include "getopt_long.h"
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -72,13 +70,13 @@
#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ #define GNU_COMPATIBLE /* Be more compatible, configure's use us! */
int opterr = 1; /* if error message should be printed */ int pkg_opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */ int pkg_optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */ int pkg_optopt = '?'; /* character checked for validity */
int optreset; /* reset getopt */ int pkg_optreset; /* reset getopt */
char *optarg; /* argument associated with option */ char *pkg_optarg; /* argument associated with option */
#define PRINT_ERROR ((opterr) && (*options != ':')) #define PRINT_ERROR ((pkg_opterr) && (*options != ':'))
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
@ -99,15 +97,15 @@ char *optarg; /* argument associated with option */
#endif #endif
static int getopt_internal(int, char * const *, const char *, static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int); const struct pkg_option *, int *, int);
static int parse_long_options(char * const *, const char *, static int parse_long_options(char * const *, const char *,
const struct option *, int *, int, int); const struct pkg_option *, int *, int, int);
static int gcd(int, int); static int gcd(int, int);
static void permute_args(int, int, int, char * const *); static void permute_args(int, int, int, char * const *);
static char *place = EMSG; /* option letter processing */ static char *place = EMSG; /* option letter processing */
/* XXX: set optreset to 1 rather than these two */ /* XXX: set pkg_optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */ static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */ static int nonopt_end = -1; /* first option after non options (for permute) */
@ -191,7 +189,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
*/ */
static int static int
parse_long_options(char * const *nargv, const char *options, parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too, int flags) const struct pkg_option *long_options, int *idx, int short_too, int flags)
{ {
char *current_argv, *has_equal; char *current_argv, *has_equal;
#ifdef GNU_COMPATIBLE #ifdef GNU_COMPATIBLE
@ -221,7 +219,7 @@ parse_long_options(char * const *nargv, const char *options,
exact_match = 0; exact_match = 0;
second_partial_match = 0; second_partial_match = 0;
optind++; pkg_optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) { if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */ /* argument found (--option=arg) */
@ -267,7 +265,7 @@ parse_long_options(char * const *nargv, const char *options,
#endif #endif
(int)current_argv_len, (int)current_argv_len,
current_argv); current_argv);
optopt = 0; pkg_optopt = 0;
return (BADCH); return (BADCH);
} }
if (match != -1) { /* option found */ if (match != -1) { /* option found */
@ -281,12 +279,12 @@ parse_long_options(char * const *nargv, const char *options,
(int)current_argv_len, (int)current_argv_len,
current_argv); current_argv);
/* /*
* XXX: GNU sets optopt to val regardless of flag * XXX: GNU sets pkg_optopt to val regardless of flag
*/ */
if (long_options[match].flag == NULL) if (long_options[match].flag == NULL)
optopt = long_options[match].val; pkg_optopt = long_options[match].val;
else else
optopt = 0; pkg_optopt = 0;
#ifdef GNU_COMPATIBLE #ifdef GNU_COMPATIBLE
return (BADCH); return (BADCH);
#else #else
@ -296,17 +294,17 @@ parse_long_options(char * const *nargv, const char *options,
if (long_options[match].has_arg == required_argument || if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) { long_options[match].has_arg == optional_argument) {
if (has_equal) if (has_equal)
optarg = has_equal; pkg_optarg = has_equal;
else if (long_options[match].has_arg == else if (long_options[match].has_arg ==
required_argument) { required_argument) {
/* /*
* optional argument doesn't use next nargv * optional argument doesn't use next nargv
*/ */
optarg = nargv[optind++]; pkg_optarg = nargv[pkg_optind++];
} }
} }
if ((long_options[match].has_arg == required_argument) if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) { && (pkg_optarg == NULL)) {
/* /*
* Missing argument; leading ':' indicates no error * Missing argument; leading ':' indicates no error
* should be generated. * should be generated.
@ -318,18 +316,18 @@ parse_long_options(char * const *nargv, const char *options,
#endif #endif
current_argv); current_argv);
/* /*
* XXX: GNU sets optopt to val regardless of flag * XXX: GNU sets pkg_optopt to val regardless of flag
*/ */
if (long_options[match].flag == NULL) if (long_options[match].flag == NULL)
optopt = long_options[match].val; pkg_optopt = long_options[match].val;
else else
optopt = 0; pkg_optopt = 0;
--optind; --pkg_optind;
return (BADARG); return (BADARG);
} }
} else { /* unknown option */ } else { /* unknown option */
if (short_too) { if (short_too) {
--optind; --pkg_optind;
return (-1); return (-1);
} }
if (PRINT_ERROR) if (PRINT_ERROR)
@ -338,7 +336,7 @@ parse_long_options(char * const *nargv, const char *options,
current_dash, current_dash,
#endif #endif
current_argv); current_argv);
optopt = 0; pkg_optopt = 0;
return (BADCH); return (BADCH);
} }
if (idx) if (idx)
@ -356,7 +354,7 @@ parse_long_options(char * const *nargv, const char *options,
*/ */
static int static int
getopt_internal(int nargc, char * const *nargv, const char *options, getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags) const struct pkg_option *long_options, int *idx, int flags)
{ {
char *oli; /* option letter list index */ char *oli; /* option letter list index */
int optchar, short_too; int optchar, short_too;
@ -385,37 +383,37 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
options++; options++;
/* /*
* XXX Some GNU programs (like cvs) set optind to 0 instead of * XXX Some GNU programs (like cvs) set pkg_optind to 0 instead of
* XXX using optreset. Work around this braindamage. * XXX using pkg_optreset. Work around this braindamage.
*/ */
if (optind == 0) if (pkg_optind == 0)
optind = optreset = 1; pkg_optind = pkg_optreset = 1;
optarg = NULL; pkg_optarg = NULL;
if (optreset) if (pkg_optreset)
nonopt_start = nonopt_end = -1; nonopt_start = nonopt_end = -1;
start: start:
if (optreset || !*place) { /* update scanning pointer */ if (pkg_optreset || !*place) { /* update scanning pointer */
optreset = 0; pkg_optreset = 0;
if (optind >= nargc) { /* end of argument vector */ if (pkg_optind >= nargc) { /* end of argument vector */
place = EMSG; place = EMSG;
if (nonopt_end != -1) { if (nonopt_end != -1) {
/* do permutation, if we have to */ /* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end, permute_args(nonopt_start, nonopt_end,
optind, nargv); pkg_optind, nargv);
optind -= nonopt_end - nonopt_start; pkg_optind -= nonopt_end - nonopt_start;
} }
else if (nonopt_start != -1) { else if (nonopt_start != -1) {
/* /*
* If we skipped non-options, set optind * If we skipped non-options, set pkg_optind
* to the first of them. * to the first of them.
*/ */
optind = nonopt_start; pkg_optind = nonopt_start;
} }
nonopt_start = nonopt_end = -1; nonopt_start = nonopt_end = -1;
return (-1); return (-1);
} }
if (*(place = nargv[optind]) != '-' || if (*(place = nargv[pkg_optind]) != '-' ||
#ifdef GNU_COMPATIBLE #ifdef GNU_COMPATIBLE
place[1] == '\0') { place[1] == '\0') {
#else #else
@ -427,7 +425,7 @@ start:
* GNU extension: * GNU extension:
* return non-option as argument to option 1 * return non-option as argument to option 1
*/ */
optarg = nargv[optind++]; pkg_optarg = nargv[pkg_optind++];
return (INORDER); return (INORDER);
} }
if (!(flags & FLAG_PERMUTE)) { if (!(flags & FLAG_PERMUTE)) {
@ -439,26 +437,26 @@ start:
} }
/* do permutation */ /* do permutation */
if (nonopt_start == -1) if (nonopt_start == -1)
nonopt_start = optind; nonopt_start = pkg_optind;
else if (nonopt_end != -1) { else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end, permute_args(nonopt_start, nonopt_end,
optind, nargv); pkg_optind, nargv);
nonopt_start = optind - nonopt_start = pkg_optind -
(nonopt_end - nonopt_start); (nonopt_end - nonopt_start);
nonopt_end = -1; nonopt_end = -1;
} }
optind++; pkg_optind++;
/* process next argument */ /* process next argument */
goto start; goto start;
} }
if (nonopt_start != -1 && nonopt_end == -1) if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind; nonopt_end = pkg_optind;
/* /*
* If we have "-" do nothing, if "--" we are done. * If we have "-" do nothing, if "--" we are done.
*/ */
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++; pkg_optind++;
place = EMSG; place = EMSG;
/* /*
* We found an option (--), so if we skipped * We found an option (--), so if we skipped
@ -466,8 +464,8 @@ start:
*/ */
if (nonopt_end != -1) { if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end, permute_args(nonopt_start, nonopt_end,
optind, nargv); pkg_optind, nargv);
optind -= nonopt_end - nonopt_start; pkg_optind -= nonopt_end - nonopt_start;
} }
nonopt_start = nonopt_end = -1; nonopt_start = nonopt_end = -1;
return (-1); return (-1);
@ -480,7 +478,7 @@ start:
* 2) the arg is not just "-" * 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only() * 3) either the arg starts with -- we are getopt_long_only()
*/ */
if (long_options != NULL && place != nargv[optind] && if (long_options != NULL && place != nargv[pkg_optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) { (*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0; short_too = 0;
#ifdef GNU_COMPATIBLE #ifdef GNU_COMPATIBLE
@ -513,7 +511,7 @@ start:
if (optchar == (int)'-' && *place == '\0') if (optchar == (int)'-' && *place == '\0')
return (-1); return (-1);
if (!*place) if (!*place)
++optind; ++pkg_optind;
#ifdef GNU_COMPATIBLE #ifdef GNU_COMPATIBLE
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(posixly_correct ? illoptchar : gnuoptchar, warnx(posixly_correct ? illoptchar : gnuoptchar,
@ -522,21 +520,21 @@ start:
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(illoptchar, optchar); warnx(illoptchar, optchar);
#endif #endif
optopt = optchar; pkg_optopt = optchar;
return (BADCH); return (BADCH);
} }
if (long_options != NULL && optchar == 'W' && oli[1] == ';') { if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */ /* -W long-option */
if (*place) /* no space */ if (*place) /* no space */
/* NOTHING */; /* NOTHING */;
else if (++optind >= nargc) { /* no arg */ else if (++pkg_optind >= nargc) { /* no arg */
place = EMSG; place = EMSG;
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(recargchar, optchar); warnx(recargchar, optchar);
optopt = optchar; pkg_optopt = optchar;
return (BADARG); return (BADARG);
} else /* white space */ } else /* white space */
place = nargv[optind]; place = nargv[pkg_optind];
#ifdef GNU_COMPATIBLE #ifdef GNU_COMPATIBLE
dash_prefix = W_PREFIX; dash_prefix = W_PREFIX;
#endif #endif
@ -547,23 +545,23 @@ start:
} }
if (*++oli != ':') { /* doesn't take argument */ if (*++oli != ':') { /* doesn't take argument */
if (!*place) if (!*place)
++optind; ++pkg_optind;
} else { /* takes (optional) argument */ } else { /* takes (optional) argument */
optarg = NULL; pkg_optarg = NULL;
if (*place) /* no white space */ if (*place) /* no white space */
optarg = place; pkg_optarg = place;
else if (oli[1] != ':') { /* arg not optional */ else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */ if (++pkg_optind >= nargc) { /* no arg */
place = EMSG; place = EMSG;
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(recargchar, optchar); warnx(recargchar, optchar);
optopt = optchar; pkg_optopt = optchar;
return (BADARG); return (BADARG);
} else } else
optarg = nargv[optind]; pkg_optarg = nargv[pkg_optind];
} }
place = EMSG; place = EMSG;
++optind; ++pkg_optind;
} }
/* dump back option letter */ /* dump back option letter */
return (optchar); return (optchar);
@ -576,7 +574,7 @@ start:
* [eventually this will replace the BSD getopt] * [eventually this will replace the BSD getopt]
*/ */
int int
getopt(int nargc, char * const *nargv, const char *options) pkg_getopt(int nargc, char * const *nargv, const char *options)
{ {
/* /*
@ -595,8 +593,8 @@ getopt(int nargc, char * const *nargv, const char *options)
* Parse argc/argv argument vector. * Parse argc/argv argument vector.
*/ */
int int
getopt_long(int nargc, char * const *nargv, const char *options, pkg_getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx) const struct pkg_option *long_options, int *idx)
{ {
return (getopt_internal(nargc, nargv, options, long_options, idx, return (getopt_internal(nargc, nargv, options, long_options, idx,
@ -608,12 +606,10 @@ getopt_long(int nargc, char * const *nargv, const char *options,
* Parse argc/argv argument vector. * Parse argc/argv argument vector.
*/ */
int int
getopt_long_only(int nargc, char * const *nargv, const char *options, pkg_getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx) const struct pkg_option *long_options, int *idx)
{ {
return (getopt_internal(nargc, nargv, options, long_options, idx, return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE|FLAG_LONGONLY)); FLAG_PERMUTE|FLAG_LONGONLY));
} }
#endif

View File

@ -35,8 +35,6 @@
#ifndef _GETOPT_LONG_H_ #ifndef _GETOPT_LONG_H_
#define _GETOPT_LONG_H_ #define _GETOPT_LONG_H_
#ifndef HAVE_GETOPT_LONG
#include <sys/cdefs.h> #include <sys/cdefs.h>
/* /*
@ -47,7 +45,7 @@
#define required_argument 1 #define required_argument 1
#define optional_argument 2 #define optional_argument 2
struct option { struct pkg_option {
/* name of long option */ /* name of long option */
const char *name; const char *name;
/* /*
@ -61,16 +59,14 @@ struct option {
int val; int val;
}; };
int getopt_long(int, char * const *, const char *, int pkg_getopt_long(int, char * const *, const char *,
const struct option *, int *); const struct pkg_option *, int *);
int getopt_long_only(int, char * const *, const char *, int pkg_getopt_long_only(int, char * const *, const char *,
const struct option *, int *); const struct pkg_option *, int *);
int getopt(int, char * const [], const char *); int pkg_getopt(int, char * const [], const char *);
extern char *optarg; /* getopt(3) external variables */ extern char *pkg_optarg; /* getopt(3) external variables */
extern int optind, opterr, optopt; extern int pkg_optind, pkg_opterr, pkg_optopt;
extern int optreset; /* getopt(3) external variable */ extern int pkg_optreset; /* getopt(3) external variable */
#endif #endif
#endif /* !_GETOPT_H_ */

53
main.c
View File

@ -23,12 +23,7 @@
#include "config.h" #include "config.h"
#include "pkg.h" #include "pkg.h"
#include "bsdstubs.h"
#ifdef HAVE_GETOPT_LONG
# include <getopt.h>
#else
# include "bsdstubs.h"
#endif
#define WANT_CFLAGS_ONLY_I (19) #define WANT_CFLAGS_ONLY_I (19)
#define WANT_CFLAGS_ONLY_OTHER (20) #define WANT_CFLAGS_ONLY_OTHER (20)
@ -481,7 +476,7 @@ main(int argc, char *argv[])
char *builddir; char *builddir;
int want_errors_on_stdout = 0; int want_errors_on_stdout = 0;
struct option options[] = { struct pkg_option options[] = {
{ "version", no_argument, &want_version, 1, }, { "version", no_argument, &want_version, 1, },
{ "atleast-version", required_argument, NULL, 2, }, { "atleast-version", required_argument, NULL, 2, },
{ "atleast-pkgconfig-version", required_argument, NULL, 3, }, { "atleast-pkgconfig-version", required_argument, NULL, 3, },
@ -517,30 +512,30 @@ main(int argc, char *argv[])
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
while ((ret = getopt_long(argc, argv, "", options, NULL)) != -1) while ((ret = pkg_getopt_long(argc, argv, "", options, NULL)) != -1)
{ {
switch (ret) switch (ret)
{ {
case 2: case 2:
required_module_version = optarg; required_module_version = pkg_optarg;
break; break;
case 3: case 3:
required_pkgconfig_version = optarg; required_pkgconfig_version = pkg_optarg;
break; break;
case 7: case 7:
want_variable = optarg; want_variable = pkg_optarg;
break; break;
case 11: case 11:
maximum_traverse_depth = atoi(optarg); maximum_traverse_depth = atoi(pkg_optarg);
break; break;
case 27: case 27:
pkg_tuple_define_global(optarg); pkg_tuple_define_global(pkg_optarg);
break; break;
case 28: case 28:
required_exact_module_version = optarg; required_exact_module_version = pkg_optarg;
break; break;
case 29: case 29:
required_max_module_version = optarg; required_max_module_version = pkg_optarg;
break; break;
default: default:
break; break;
@ -604,10 +599,10 @@ main(int argc, char *argv[])
pkg_t *pkg; pkg_t *pkg;
pkg_dependency_t *pkghead = NULL, *pkgiter = NULL; pkg_dependency_t *pkghead = NULL, *pkgiter = NULL;
while (argv[optind]) while (argv[pkg_optind])
{ {
pkghead = pkg_dependency_parse_str(pkghead, argv[optind]); pkghead = pkg_dependency_parse_str(pkghead, argv[pkg_optind]);
optind++; pkg_optind++;
} }
PKG_FOREACH_LIST_ENTRY(pkghead, pkgiter) PKG_FOREACH_LIST_ENTRY(pkghead, pkgiter)
@ -628,10 +623,10 @@ main(int argc, char *argv[])
pkg_t *pkg; pkg_t *pkg;
pkg_dependency_t *pkghead = NULL, *pkgiter = NULL; pkg_dependency_t *pkghead = NULL, *pkgiter = NULL;
while (argv[optind]) while (argv[pkg_optind])
{ {
pkghead = pkg_dependency_parse_str(pkghead, argv[optind]); pkghead = pkg_dependency_parse_str(pkghead, argv[pkg_optind]);
optind++; pkg_optind++;
} }
PKG_FOREACH_LIST_ENTRY(pkghead, pkgiter) PKG_FOREACH_LIST_ENTRY(pkghead, pkgiter)
@ -652,10 +647,10 @@ main(int argc, char *argv[])
pkg_t *pkg; pkg_t *pkg;
pkg_dependency_t *pkghead = NULL, *pkgiter = NULL; pkg_dependency_t *pkghead = NULL, *pkgiter = NULL;
while (argv[optind]) while (argv[pkg_optind])
{ {
pkghead = pkg_dependency_parse_str(pkghead, argv[optind]); pkghead = pkg_dependency_parse_str(pkghead, argv[pkg_optind]);
optind++; pkg_optind++;
} }
PKG_FOREACH_LIST_ENTRY(pkghead, pkgiter) PKG_FOREACH_LIST_ENTRY(pkghead, pkgiter)
@ -673,26 +668,26 @@ main(int argc, char *argv[])
while (1) while (1)
{ {
const char *package = argv[optind]; const char *package = argv[pkg_optind];
if (package == NULL) if (package == NULL)
break; break;
if (argv[optind + 1] == NULL || !PKG_OPERATOR_CHAR(*(argv[optind + 1]))) if (argv[pkg_optind + 1] == NULL || !PKG_OPERATOR_CHAR(*(argv[pkg_optind + 1])))
{ {
pkgq = pkg_queue_push(pkgq, package); pkgq = pkg_queue_push(pkgq, package);
if (pkgq_head == NULL) if (pkgq_head == NULL)
pkgq_head = pkgq; pkgq_head = pkgq;
optind++; pkg_optind++;
} }
else else
{ {
char packagebuf[BUFSIZ]; char packagebuf[BUFSIZ];
snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[optind + 1], argv[optind + 2]); snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[pkg_optind + 1], argv[pkg_optind + 2]);
optind += 3; pkg_optind += 3;
pkgq = pkg_queue_push(pkgq, packagebuf); pkgq = pkg_queue_push(pkgq, packagebuf);