--- /dev/null
+aclocal.m4
+config.h.in
+configure
+config.log
+config.cache
+config.status
+Makefile
+Makefile.in
+pkg-config
--- /dev/null
+Original authors
+----------------
+James Henstridge <james@daa.com.au> original pkg-config
+Tim Janik <timj@gtk.org> the PKG_CHECK_VERSION macro
+
+Maintainer
+----------
+Martijn van Beers <martijn@eekeek.org>
--- /dev/null
+2001-05-20 Havoc Pennington <hp@pobox.com>
+
+ * configure.in: revert package name change, just screwing things up.
+
+2001-05-18 Havoc Pennington <hp@redhat.com>
+
+ * main.c (main): Change default to print errors on --cflags,
+ --libs, etc., just not on the predicate-style args
+
+2001-05-18 Havoc Pennington <hp@pobox.com>
+
+ * pkg.m4: always AC_SUBST the cflags/libs
+
+ * pkg-config.1: updates
+
+ * configure.in: call the package 'pkg-config' instead of
+ pkgconfig, for consistency
+
+ * popt.c: conditionalize on HAVE_SETRESUID, HAVE_SETREUID
+ maybe this will help with windows, and improves the #ifdef __hpux
+ test in any case.
+
+ * parse.c: use HAVE_FLOCKFILE to try for windows portability
+
+ * configure.in: check for flockfile
+
+2001-05-17 Havoc Pennington <hp@pobox.com>
+
+ * pkg.m4: change to print errors only if no custom not-found
+ action is specified
+
+ * main.c (main): add PKG_CONFIG_DEBUG_SPEW environment variable
+ (main): implement --print-errors where errors are printed, and
+ otherwise don't print errors related to packages, just usage
+ errors; pointed out by Raja
+ (main): rename pcbuilddir to pc_top_builddir
+
+2001-05-17 Havoc Pennington <hp@redhat.com>
+
+ Changes to support building against uninstalled packages.
+
+ * ${pcfiledir} variable used to locate builddir by locating
+ the .pc file
+
+ * ${pcbuilddir} variable set by the PKG_CONFIG_BUILD_DIR variable,
+ used for the name of the build directory where the cflags/libs
+ will be used, defaults to '$(top_builddir)'
+
+ * "uninstalled" feature looks for foo-uninstalled.pc before
+ foo.pc, unless PKG_CONFIG_DISABLE_UNINSTALLED is set
+
+ * --uninstalled option used to see if foo-uninstalled.pc is in use
+
+ * --define-variable option added, but turned out to be unused for
+ this
+
+2001-05-09 Havoc Pennington <hp@redhat.com>
+
+ * main.c, findme.c, parse.c, pkg.c, poptconfig.c, popthelp.c,
+ poptparse.c: portability fixes from Tomas Ogren
+
+2001-05-09 Havoc Pennington <hp@redhat.com>
+
+ * Makefile.am (EXTRA_DIST): put the m4 files in the distribution
+
+2001-05-09 Havoc Pennington <hp@redhat.com>
+
+ * pkg.m4: switch to double quotes for module list, so you can use
+ a variable there.
+
+2001-05-09 Havoc Pennington <hp@redhat.com>
+
+ * pkg.c (verify_package): fix error message on missing Name field,
+ so that it doesn't try to use the name field to report which
+ package was broken
+
+ * parse.c (parse_package_file): change a debug spew to an actual
+ error message
+
+2001-04-13 Havoc Pennington <hp@redhat.com>
+
+ * pkg.m4: fixed this up
+
+ * main.c (main): remove --check-requires, instead allow version
+ predicates in the module list.
+
+2001-04-12 Havoc Pennington <hp@pobox.com>
+
+ * main.c (main): Implement --check-requires='gtk+-2.0 = 1.3.4'
+ option
+
+2001-01-24 Havoc Pennington <hp@redhat.com>
+
+ Implement --debug spew option.
+
+ * main.c: add debug_spew function and an option --debug
+
+2001-01-06 Havoc Pennington <hp@pobox.com>
+
+ * pkg.c (scan_dir): fail silently if we can't open a directory in
+ the PKG_CONFIG_PATH
+
+2001-01-02 Havoc Pennington <hp@redhat.com>
+
+ * configure.in: bump version
+
+2001-01-02 Havoc Pennington <hp@redhat.com>
+
+ * parse.c (parse_package_file): return NULL instead of exiting
+ if we can't open the file.
+
+ * main.c (main): Add options to check the version of pkg-config
+ itself, and to list all known packages
+
+ * parse.c (split_module_list): fix to work properly
+ (parse_module_list): pass variable-substituted string to
+ split_module_list(), silly typo
+
+ * pkg.c (get_package): Add ability to pass a filename instead of a
+ package name, if you want to use a specific pkg-config file (used
+ for configure.in in GTK+ for example, where you can build against
+ an uninstalled copy of GLib).
+
+2000-11-29 Havoc Pennington <hp@redhat.com>
+
+ * parse.c (parse_module_list): Allow commas before/after the
+ module list, and allow spaces instead of commas to be used as
+ separators. This leniency makes it a lot easier to conditionally
+ build the module list according to configure.in checks.
+
+2000-11-29 Havoc Pennington <hp@pobox.com>
+
+ * pkg.c (packages_get_other_libs): put a space after the
+ other_libs
+ (packages_get_other_cflags): put a space after the other_cflags
+
+2000-11-27 Havoc Pennington <hp@redhat.com>
+
+ * main.c (main): don't print space after variable values
+
+ * pkg.c (packages_get_var): don't add space after last variable
+
+2000-11-22 Martijn van Beers <martijn@earthling.net>
+
+ * main.c: added a --version option for martin
+ * parse.c: added jamesh's patch
+
+ release 0.4.1
+
+2000-10-17 Martijn van Beers <martijn@earthling.net>
+
+ * configure.in:
+ * Makefile.am: Change to use C version only.
+
+ release 0.4.0
+
+2000-09-15 Havoc Pennington <hp@redhat.com>
+
+ * configure.in: AM_PROG_LIBTOOL
+
+ * Makefile.am (experimental_pkg_config_LDADD): Link with .la, not
+ .a
+
+2000-08-10 Havoc Pennington <hp@redhat.com>
+
+ * pkg.c (verify_package): Bugfix from Anders
+
+2000-07-24 Havoc Pennington <hp@redhat.com>
+
+ * parse.c (get_compat_package): Add support
+ for imlib-config and orbit-config
+
+2000-07-22 Havoc Pennington <hp@pobox.com>
+
+ * parse.c (get_compat_package): Make it work with any
+ gnome-config package name.
+
+2000-07-22 Havoc Pennington <hp@pobox.com>
+
+ * parse.c, pkg.c, pkg.h: Add Conflicts: keyword, and do
+ version-checking for Requires: line. Untested.
+
+2000-07-21 Havoc Pennington <hp@redhat.com>
+
+ * parse.c (get_compat_package): Add some compat stuff (execs
+ gnome-config, gtk-config, etc.). We don't yet support all
+ the modules we might want to support.
+
+2000-07-20 Havoc Pennington <hp@redhat.com>
+
+ * pkg.c (get_package): fix error message formatting
+
+2000-07-20 Havoc Pennington <hp@redhat.com>
+
+ * pkg.c (recursive_fill_list): append rather than prepend the
+ current libs to the required libs.
+
+ * parse.c (trim_and_sub): Make variables use ${} instead of %{} so
+ we can accept "shell variables" subbed by configure
+
+2000-07-20 Havoc Pennington <hp@redhat.com>
+
+ * autogen.sh: Run perl on the Makefile.am in the glib tarball to
+ keep it from doing anything in 'make install'
+
+ * pkg.c (scan_dir): Revert to .pc extension
+
+2000-07-20 Havoc Pennington <hp@redhat.com>
+
+ * glib-1.2.8.tar.gz: Decided it was easier to just stick
+ in a copy of the tarball instead of hacking up glib;
+ this way we get bugfixes. If distribution size is a problem,
+ we can hack on it later. Rerun autogen.sh to get the
+ tarball unpacked and configured.
+
+ * configure.in: AC_CONFIG_SUBDIRS(glib-1.2.8)
+
+ * main.c: Add version-comparison
+
+ * Makefile.am: use new glib tarball
+
+2000-07-18 Havoc Pennington <hp@redhat.com>
+
+ * pkg.c: When removing -l duplicates, keep the last not the first
+ -l
+
+ * main.c (main): Added --variable and --module-exists options.
+
+ * Wrote an experimental version of pkg-config in C. For
+ now, glib is required, until I get a cut-and-pasted subset
+ of glib up and running.
+
+ C version is not finished, don't release a tarball yet. ;-)
+
+ * configure.in, Makefile.am: stuff to build the C version
+ of pkg-config
+
+2000-07-10 Martijn van Beers <martijn@earthling.net>
+
+ * pkg-config.in: remove -I/usr/include and -L/usr/lib from
+ the flags we output
+ * pkg.m4: add a PKG_ACLOCALFLAGS macro
+ add a _DEPENDS output variable
+
+2000-07-01 Martijn van Beers <martijn@earthling.net>
+
+ * data/gnomeconfig.pce: make output of --modversion be like
+ the output of .pc files
+
+2000-07-01 Martijn van Beers <martijn@earthling.net>
+
+ * pkg.m4: clean up PKG_CHECK_CFLAG
+
+2000-06-27 Martijn van Beers <martijn@earthling.net>
+
+ * data/gnomeconfig.pce: check for existance with --cflags
+ instead of --libs
+ * pkg.m4: remove stray debug echo command
+ add PKG_CHECK_CFLAGS macro
+
+2000-06-23 Martijn van Beers <martijn@earthling.net>
+
+ * data/gnomeconfig.pce,
+ * pkg-config.in:
+ - add checks to see if we're properly installed
+ - bug fixes for sh on Tru64
+
+Wed Jun 21 2000 Martijn van Beers <martijn@earthling.net>
+
+ * added support for extension modules that will be called
+ if a module doesn't have a .pc file
+ * added a gnomeconfig.pce extension module to allow for
+ old gnome-libs stuff to be used (at the request of hp)
+ * made CFLAGS be like the LIBS_* variables in that you
+ need to do the adding in the .pc file
+
+Thu Jun 15 2000 Martijn van Beers <martijn@earthling.net>
+
+ * add a --print-pc-dir that prints the default search dir
+ * only use the default search dir when nothing else is
+ specified
+
+Sat Jun 10 2000 Martijn van Beers <martijn@earthling.net>
+
+ * made the duplication removing code in a function
+ * fix the duplication code so that it checks $* correctly
+ while we have IFS=":$IFS"
+ * splitted up --libs into --libs-only-L, --libs-only-l-self
+ and --libs-only-l-system, as suggested by Tim Janik
+
+Thu Jun 8 2000 Martijn van Beers <martijn@earthling.net>
+
+ * made it use autoconf/automake
+ * pkg-config: removed in favour of a .in equivalent which generates
+ pkg-config from configure
+ * pkg-config.in: new file, mostly a copy from pkg-config
+ * pkg-config.in: get the prefix for the default pc_path from configure
+
+Wed Jun 7 2000 Martijn van Beers <martijn@earthling.net>
+
+ * pkg.m4: new file, contains a macro that checks for packages and
+ whether they're the right version
+ * pkg-config: added a --modversion flag to get the version of the
+ module (needs a VERSION var in the .pc files)
+
+Tue Jun 6 2000 Martijn van Beers <martijn@earthling.net>
+
+ * pkg-config: removed the pc_name_pkg functionality
+ * pkg-config: show help and error out when there are no arguments
+ * pkg-config: get the version from configure
--- /dev/null
+SUBDIRS = glib-1.2.8
+
+m4dir = $(datadir)/aclocal
+m4_DATA = pkg.m4
+
+man_MANS = pkg-config.1
+EXTRA_DIST = $(m4_DATA) $(man_MANS)
+
+bin_PROGRAMS = pkg-config
+
+INCLUDES=-DPKGLIBDIR="\"$(pkglibdir)\"" -I./glib-1.2.8
+
+pkg_config_SOURCES= \
+ pkg.h \
+ pkg.c \
+ partial-glib.h \
+ partial-glib.c \
+ parse.h \
+ parse.c \
+ main.c \
+ findme.c \
+ findme.h \
+ popt.c \
+ popt.h \
+ poptconfig.c \
+ popthelp.c \
+ poptint.h \
+ poptparse.c
+
+pkg_config_LDADD=glib-1.2.8/libglib.la
--- /dev/null
+pkg-config is a script to make putting together all the build
+flags when compiling/linking a lot easier.
+
+to use it, do something like the following in your configure.in
+
+ PKG_CHECK_MODULES(GNOME, gtk:1.2.8, gnomeui)
+ AC_SUBST(GNOME_CFLAGS)
+ AC_SUBST(GNOME_LIBS)
+
+This puts the neccesary include flags to compile/link something against
+libgnomeui and all its dependencies in $(GNOME_CFLAGS), and the -L/-l flags
+for linking in $(GNOME_LIBS)
+
+The gtk:1.2.8 part is only neccesary if you want to specifically check
+if libgtk is version 1.2.8 or higher. otherwise, the flags for gtk
+will be included automatically, since libgnomeui depends on gtk.
+
--- /dev/null
+#undef SIZEOF_LONG
+#undef SIZEOF_VOID_P
--- /dev/null
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=pkg-config
+TEST_TYPE=-f
+FILE=pkg.m4
+
+DIE=0
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed to compile $PROJECT."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have automake installed to compile $PROJECT."
+ echo "Get ftp://ftp.cygnus.com/pub/home/tromey/automake-1.2d.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+}
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+ echo "You must run this script in the top-level $PROJECT directory"
+ exit 1
+}
+
+gunzip --stdout glib-1.2.8.tar.gz | tar xf - || {
+ echo "glib tarball not unpacked"
+ exit 1
+}
+
+perl -pi -e "s/lib_LTLIBRARIES/noinst_LTLIBRARIES/g" `find glib-1.2.8 -name Makefile.am`
+perl -pi -e "s/bin_SCRIPTS/noinst_SCRIPTS/g" `find glib-1.2.8 -name Makefile.am`
+perl -pi -e "s/include_HEADERS/noinst_HEADERS/g" `find glib-1.2.8 -name Makefile.am`
+perl -pi -e "s/[a-zA-Z0-9]+_DATA/noinst_DATA/g" `find glib-1.2.8 -name Makefile.am`
+perl -pi -e "s/info_TEXINFOS/noinst_TEXINFOS/g" `find glib-1.2.8 -name Makefile.am`
+perl -pi -e "s/man_MANS/noinst_MANS/g" `find glib-1.2.8 -name Makefile.am`
+
+(cd glib-1.2.8 && automake)
+
+if test -z "$*"; then
+ echo "I am going to run ./configure with no arguments - if you wish "
+ echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+echo aclocal $ACLOCAL_FLAGS
+aclocal $ACLOCAL_FLAGS
+
+# optionally feature autoheader
+(autoheader --version) < /dev/null > /dev/null 2>&1 && autoheader
+
+automake -a $am_opt
+autoconf
+
+cd $ORIGDIR
+
+$srcdir/configure --enable-maintainer-mode --disable-shared --disable-threads "$@"
+
+echo
+echo "Now type 'make' to compile $PROJECT."
--- /dev/null
+
+AC_INIT(pkg-config.1)
+
+AC_CONFIG_SUBDIRS(glib-1.2.8)
+
+AM_INIT_AUTOMAKE(pkgconfig, 0.6.0)
+
+AM_MAINTAINER_MODE
+
+AM_CONFIG_HEADER(config.h)
+
+AM_PROG_LIBTOOL
+
+AC_PROG_CC
+
+AC_FUNC_ALLOCA
+
+AC_CHECK_FUNCS(flockfile)
+AC_CHECK_FUNCS(setresuid setreuid,break)
+
+AC_OUTPUT([Makefile])
--- /dev/null
+/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+ file accompanying popt source distributions, available from
+ ftp://ftp.redhat.com/pub/code/popt */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#else
+# ifdef _AIX
+# pragma alloca
+# endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef __NeXT
+/* access macros are not declared in non posix mode in unistd.h -
+ don't try to use posix on NeXTstep 3.3 ! */
+#include <libc.h>
+#endif
+
+#include "findme.h"
+
+char * findProgramPath(char * argv0) {
+ char * path = getenv("PATH");
+ char * pathbuf;
+ char * start, * chptr;
+ char * buf;
+
+ /* If there is a / in the argv[0], it has to be an absolute
+ path */
+ if (strchr(argv0, '/'))
+ return strdup(argv0);
+
+ if (!path) return NULL;
+
+ start = pathbuf = alloca(strlen(path) + 1);
+ buf = malloc(strlen(path) + strlen(argv0) + 2);
+ strcpy(pathbuf, path);
+
+ chptr = NULL;
+ do {
+ if ((chptr = strchr(start, ':')))
+ *chptr = '\0';
+ sprintf(buf, "%s/%s", start, argv0);
+
+ if (!access(buf, X_OK))
+ return buf;
+
+ if (chptr)
+ start = chptr + 1;
+ else
+ start = NULL;
+ } while (start && *start);
+
+ free(buf);
+
+ return NULL;
+}
--- /dev/null
+/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+ file accompanying popt source distributions, available from
+ ftp://ftp.redhat.com/pub/code/popt */
+
+#ifndef H_FINDME
+#define H_FINDME
+
+char * findProgramPath(char * argv0);
+
+#endif
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pkg.h"
+#include "parse.h"
+
+#include "popt.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+static int want_debug_spew = 0;
+static int want_verbose_errors = 0;
+
+void
+debug_spew (const char *format, ...)
+{
+ va_list args;
+ gchar *str;
+
+ g_return_if_fail (format != NULL);
+
+ if (!want_debug_spew)
+ return;
+
+ va_start (args, format);
+ str = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ fputs (str, stderr);
+ fflush (stdout);
+
+ g_free (str);
+}
+
+void
+verbose_error (const char *format, ...)
+{
+ va_list args;
+ gchar *str;
+
+ g_return_if_fail (format != NULL);
+
+ if (!want_verbose_errors)
+ return;
+
+ va_start (args, format);
+ str = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ fputs (str, stderr);
+ fflush (stdout);
+
+ g_free (str);
+}
+
+#define DEFINE_VARIABLE 1
+
+static void
+popt_callback (poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption * opt,
+ const char * arg, void * data)
+{
+ if (opt->val == DEFINE_VARIABLE)
+ {
+ char *varname;
+ char *varval;
+ char *tmp;
+
+ tmp = g_strdup (arg);
+
+ varname = tmp;
+ while (*varname && isspace (*varname))
+ ++varname;
+
+ varval = varname;
+ while (*varval && *varval != '=' && *varval != ' ')
+ ++varval;
+
+ while (*varval && (*varval == '=' || *varval == ' '))
+ {
+ *varval = '\0';
+ ++varval;
+ }
+
+ if (*varval == '\0')
+ {
+ fprintf (stderr, "--define-variable argument does not have a value for the variable\n");
+
+ exit (1);
+ }
+
+ define_global_variable (varname, varval);
+
+ g_free (tmp);
+ }
+}
+
+static gboolean
+pkg_uninstalled (Package *pkg)
+{
+ /* See if > 0 pkgs were uninstalled */
+ GSList *tmp;
+
+ if (pkg->uninstalled)
+ return TRUE;
+
+ tmp = pkg->requires;
+ while (tmp != NULL)
+ {
+ Package *pkg = tmp->data;
+
+ if (pkg_uninstalled (pkg))
+ return TRUE;
+
+ tmp = g_slist_next (tmp);
+ }
+
+ return FALSE;
+}
+
+int
+main (int argc, char **argv)
+{
+ static int want_my_version = 0;
+ static int want_version = 0;
+ static int want_libs = 0;
+ static int want_cflags = 0;
+ static int want_l_libs = 0;
+ static int want_L_libs = 0;
+ static int want_I_cflags = 0;
+ static int want_list = 0;
+ static int result;
+ static int want_uninstalled = 0;
+ static char *variable_name = NULL;
+ static int want_exists = 0;
+ static char *required_atleast_version = NULL;
+ static char *required_exact_version = NULL;
+ static char *required_max_version = NULL;
+ static char *required_pkgconfig_version = NULL;
+ static int want_silence_errors = 0;
+ GString *str;
+ GSList *packages = NULL;
+ char *search_path;
+ char *pcbuilddir;
+ gboolean need_newline;
+
+ const char *pkgname;
+ Package *pkg;
+
+ poptContext opt_context;
+
+ struct poptOption options_table[] = {
+ { NULL, 0, POPT_ARG_CALLBACK, popt_callback, 0, NULL, NULL },
+ { "version", 0, POPT_ARG_NONE, &want_my_version, 0,
+ "output version of pkg-config" },
+ { "modversion", 0, POPT_ARG_NONE, &want_version, 0,
+ "output version for package" },
+ { "atleast-pkgconfig-version", 0, POPT_ARG_STRING, &required_pkgconfig_version, 0,
+ "require given version of pkg-config", "VERSION" },
+ { "libs", 0, POPT_ARG_NONE, &want_libs, 0,
+ "output all linker flags" },
+ { "libs-only-l", 0, POPT_ARG_NONE, &want_l_libs, 0,
+ "output -l flags" },
+ { "libs-only-L", 0, POPT_ARG_NONE, &want_L_libs, 0,
+ "output -L flags" },
+ { "cflags", 0, POPT_ARG_NONE, &want_cflags, 0,
+ "output all pre-processor and compiler flags" },
+ { "cflags-only-I", 0, POPT_ARG_NONE, &want_I_cflags, 0,
+ "output -I flags" },
+ { "variable", 0, POPT_ARG_STRING, &variable_name, 0,
+ "get the value of a variable", "VARIABLENAME" },
+ { "define-variable", 0, POPT_ARG_STRING, NULL, DEFINE_VARIABLE,
+ "set the value of a variable", "VARIABLENAME=VARIABLEVALUE" },
+ { "exists", 0, POPT_ARG_NONE, &want_exists, 0,
+ "return 0 if the module(s) exist" },
+ { "uninstalled", 0, POPT_ARG_NONE, &want_uninstalled, 0,
+ "return 0 if the uninstalled version of one or more module(s) or their dependencies will be used" },
+ { "atleast-version", 0, POPT_ARG_STRING, &required_atleast_version, 0,
+ "return 0 if the module is at least version VERSION", "VERSION" },
+ { "exact-version", 0, POPT_ARG_STRING, &required_exact_version, 0,
+ "return 0 if the module is at exactly version VERSION", "VERSION" },
+ { "max-version", 0, POPT_ARG_STRING, &required_max_version, 0,
+ "return 0 if the module is at no newer than version VERSION", "VERSION" },
+ { "list-all", 0, POPT_ARG_NONE, &want_list, 0,
+ "list all known packages" },
+ { "debug", 0, POPT_ARG_NONE, &want_debug_spew, 0,
+ "show verbose debug information" },
+ { "print-errors", 0, POPT_ARG_NONE, &want_verbose_errors, 0,
+ "show verbose information about missing or conflicting packages" },
+ { "silence-errors", 0, POPT_ARG_NONE, &want_silence_errors, 0,
+ "show verbose information about missing or conflicting packages" },
+ POPT_AUTOHELP
+ { NULL, 0, 0, NULL, 0 }
+ };
+
+ /* This is here so that we get debug spew from the start,
+ * during arg parsing
+ */
+ if (getenv ("PKG_CONFIG_DEBUG_SPEW"))
+ {
+ want_debug_spew = TRUE;
+ want_verbose_errors = TRUE;
+ want_silence_errors = FALSE;
+ }
+
+ search_path = getenv ("PKG_CONFIG_PATH");
+ if (search_path)
+ {
+ char **search_dirs;
+ char **iter;
+
+ search_dirs = g_strsplit (search_path, ":", -1);
+
+ iter = search_dirs;
+ while (*iter)
+ {
+ debug_spew ("Adding directory '%s' from PKG_CONFIG_PATH\n",
+ *iter);
+ add_search_dir (*iter);
+
+ ++iter;
+ }
+
+ g_strfreev (search_dirs);
+ }
+
+ pcbuilddir = getenv ("PKG_CONFIG_TOP_BUILD_DIR");
+ if (pcbuilddir)
+ {
+ define_global_variable ("pc_top_builddir", pcbuilddir);
+ }
+ else
+ {
+ /* Default appropriate for automake */
+ define_global_variable ("pc_top_builddir", "$(top_builddir)");
+ }
+
+ if (getenv ("PKG_CONFIG_DISABLE_UNINSTALLED"))
+ {
+ debug_spew ("disabling auto-preference for uninstalled packages\n");
+ disable_uninstalled = TRUE;
+ }
+
+ opt_context = poptGetContext (NULL, argc, argv,
+ options_table, 0);
+
+ result = poptGetNextOpt (opt_context);
+ if (result != -1)
+ {
+ fprintf(stderr, "%s: %s\n",
+ poptBadOption(opt_context, POPT_BADOPTION_NOALIAS),
+ poptStrerror(result));
+ return 1;
+ }
+
+
+ /* Error printing is determined as follows:
+ * - for --cflags, --libs, etc. it's on by default
+ * and --silence-errors can turn it off
+ * - for --exists, --max-version, etc. and no options
+ * at all, it's off by default and --print-errors
+ * will turn it on
+ */
+
+ if (want_my_version ||
+ want_version ||
+ want_libs ||
+ want_cflags ||
+ want_l_libs ||
+ want_L_libs ||
+ want_I_cflags ||
+ want_list)
+ {
+ if (want_silence_errors && getenv ("PKG_CONFIG_DEBUG_SPEW") == NULL)
+ want_verbose_errors = FALSE;
+ else
+ want_verbose_errors = TRUE;
+ }
+ else
+ {
+ /* Leave want_verbose_errors unchanged, reflecting --print-errors */
+ }
+
+ if (want_my_version)
+ {
+ printf ("%s\n", VERSION);
+ return 0;
+ }
+
+ if (required_pkgconfig_version)
+ {
+ if (compare_versions (VERSION, required_pkgconfig_version) >= 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ package_init ();
+
+ if (want_list)
+ {
+ print_package_list ();
+ return 0;
+ }
+
+ str = g_string_new ("");
+ while (1)
+ {
+ pkgname = poptGetArg (opt_context);
+ if (pkgname == NULL)
+ break;
+
+ g_string_append (str, pkgname);
+ g_string_append (str, " ");
+ }
+
+ g_strstrip (str->str);
+
+ {
+ GSList *reqs;
+ GSList *iter;
+
+ reqs = parse_module_list (NULL, str->str,
+ "(command line arguments)");
+
+ iter = reqs;
+
+ while (iter != NULL)
+ {
+ Package *req;
+ RequiredVersion *ver = iter->data;
+
+ req = get_package (ver->name);
+
+ if (req == NULL)
+ {
+ verbose_error ("No package '%s' found\n", ver->name);
+ return 1;
+ }
+
+ if (!version_test (ver->comparison, req->version, ver->version))
+ {
+ verbose_error ("Requested '%s %s %s' but version of %s is %s\n",
+ ver->name,
+ comparison_to_str (ver->comparison),
+ ver->version,
+ req->name,
+ req->version);
+
+ return 1;
+ }
+
+ packages = g_slist_prepend (packages, req);
+
+ iter = g_slist_next (iter);
+ }
+ }
+
+ g_string_free (str, TRUE);
+
+ packages = g_slist_reverse (packages);
+
+ if (packages == NULL)
+ {
+ fprintf (stderr, "Must specify package names on the command line\n");
+
+ exit (1);
+ }
+
+ if (want_exists)
+ return 0; /* if we got here, all the packages existed. */
+
+ if (want_uninstalled)
+ {
+ /* See if > 0 pkgs (including dependencies recursively) were uninstalled */
+ GSList *tmp;
+ tmp = packages;
+ while (tmp != NULL)
+ {
+ Package *pkg = tmp->data;
+
+ if (pkg_uninstalled (pkg))
+ return 0;
+
+ tmp = g_slist_next (tmp);
+ }
+
+ return 1;
+ }
+
+ if (want_version)
+ {
+ GSList *tmp;
+ tmp = packages;
+ while (tmp != NULL)
+ {
+ Package *pkg = tmp->data;
+
+ printf ("%s\n", pkg->version);
+
+ tmp = g_slist_next (tmp);
+ }
+ }
+
+ if (required_exact_version)
+ {
+ Package *pkg = packages->data;
+
+ if (compare_versions (pkg->version, required_exact_version) == 0)
+ return 0;
+ else
+ return 1;
+ }
+ else if (required_atleast_version)
+ {
+ Package *pkg = packages->data;
+
+ if (compare_versions (pkg->version, required_atleast_version) >= 0)
+ return 0;
+ else
+ return 1;
+ }
+ else if (required_max_version)
+ {
+ Package *pkg = packages->data;
+
+ if (compare_versions (pkg->version, required_max_version) <= 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ /* Print all flags; then print a newline at the end. */
+ need_newline = FALSE;
+
+ if (variable_name)
+ {
+ char *str = packages_get_var (packages, variable_name);
+ printf ("%s", str);
+ g_free (str);
+ need_newline = TRUE;
+ }
+
+ if (want_I_cflags)
+ {
+ char *str = packages_get_I_cflags (packages);
+ printf ("%s ", str);
+ g_free (str);
+ need_newline = TRUE;
+ }
+ else if (want_cflags)
+ {
+ char *str = packages_get_all_cflags (packages);
+ printf ("%s ", str);
+ g_free (str);
+ need_newline = TRUE;
+ }
+
+ if (want_l_libs)
+ {
+ char *str = packages_get_l_libs (packages);
+ printf ("%s ", str);
+ g_free (str);
+ need_newline = TRUE;
+ }
+ else if (want_L_libs)
+ {
+ char *str = packages_get_L_libs (packages);
+ printf ("%s ", str);
+ g_free (str);
+ need_newline = TRUE;
+ }
+ else if (want_libs)
+ {
+ char *str = packages_get_all_libs (packages);
+ printf ("%s ", str);
+ g_free (str);
+ need_newline = TRUE;
+ }
+
+ if (need_newline)
+ printf ("\n");
+
+ return 0;
+}
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "parse.h"
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "popt.h"
+#include <sys/wait.h>
+#include <sys/types.h>
+
+#ifndef HAVE_FLOCKFILE
+# define flockfile(f) (void)1
+# define funlockfile(f) (void)1
+# define getc_unlocked(f) getc(f)
+#endif /* !HAVE_FLOCKFILE */
+
+#ifdef NATIVE_WIN32
+
+#define STRICT
+#include <windows.h>
+
+#endif
+
+/**
+ * Read an entire line from a file into a buffer. Lines may
+ * be delimited with '\n', '\r', '\n\r', or '\r\n'. The delimiter
+ * is not written into the buffer. Text after a '#' character is treated as
+ * a comment and skipped. '\' can be used to escape a # character.
+ * '\' proceding a line delimiter combines adjacent lines. A '\' proceding
+ * any other character is ignored and written into the output buffer
+ * unmodified.
+ *
+ * Return value: %FALSE if the stream was already at an EOF character.
+ **/
+static gboolean
+read_one_line (FILE *stream, GString *str)
+{
+ gboolean quoted = FALSE;
+ gboolean comment = FALSE;
+ int n_read = 0;
+
+ flockfile (stream);
+
+ g_string_truncate (str, 0);
+
+ while (1)
+ {
+ int c;
+
+ c = getc_unlocked (stream);
+
+ if (c == EOF)
+ {
+ if (quoted)
+ g_string_append_c (str, '\\');
+
+ goto done;
+ }
+ else
+ n_read++;
+
+ if (quoted)
+ {
+ quoted = FALSE;
+
+ switch (c)
+ {
+ case '#':
+ g_string_append_c (str, '#');
+ break;
+ case '\r':
+ case '\n':
+ {
+ int next_c = getc_unlocked (stream);
+
+ if (!(c == EOF ||
+ (c == '\r' && next_c == '\n') ||
+ (c == '\n' && next_c == '\r')))
+ ungetc (next_c, stream);
+
+ break;
+ }
+ default:
+ g_string_append_c (str, '\\');
+ g_string_append_c (str, c);
+ }
+ }
+ else
+ {
+ switch (c)
+ {
+ case '#':
+ comment = TRUE;
+ break;
+ case '\\':
+ if (!comment)
+ quoted = TRUE;
+ break;
+ case '\n':
+ {
+ int next_c = getc_unlocked (stream);
+
+ if (!(c == EOF ||
+ (c == '\r' && next_c == '\n') ||
+ (c == '\n' && next_c == '\r')))
+ ungetc (next_c, stream);
+
+ goto done;
+ }
+ default:
+ if (!comment)
+ g_string_append_c (str, c);
+ }
+ }
+ }
+
+ done:
+
+ funlockfile (stream);
+
+ return n_read > 0;
+}
+
+static char *
+trim_string (const char *str)
+{
+ int len;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ while (*str && isspace (*str))
+ str++;
+
+ len = strlen (str);
+ while (len > 0 && isspace (str[len-1]))
+ len--;
+
+ return g_strndup (str, len);
+}
+
+static char *
+trim_and_sub (Package *pkg, const char *str, const char *path)
+{
+ char *trimmed;
+ GString *subst;
+ char *p;
+
+ trimmed = trim_string (str);
+
+ subst = g_string_new ("");
+
+ p = trimmed;
+ while (*p)
+ {
+ if (p[0] == '$' &&
+ p[1] == '$')
+ {
+ /* escaped % */
+ g_string_append_c (subst, '%');
+ p += 2;
+ }
+ else if (p[0] == '$' &&
+ p[1] == '{')
+ {
+ /* variable */
+ char *var_start;
+ char *varname;
+ char *varval;
+
+ var_start = &p[2];
+
+ /* Get up to close brace. */
+ while (*p && *p != '}')
+ ++p;
+
+ varname = g_strndup (var_start, p - var_start);
+
+ ++p; /* past brace */
+
+ varval = package_get_var (pkg, varname);
+
+ if (varval == NULL)
+ {
+ verbose_error ("Variable '%s' not defined in '%s'\n",
+ varname, path);
+
+ exit (1);
+ }
+
+ g_free (varname);
+
+ g_string_append (subst, varval);
+ }
+ else
+ {
+ g_string_append_c (subst, *p);
+
+ ++p;
+ }
+ }
+
+ g_free (trimmed);
+ p = subst->str;
+ g_string_free (subst, FALSE);
+
+ return p;
+}
+
+static void
+parse_name (Package *pkg, const char *str, const char *path)
+{
+ if (pkg->name)
+ {
+ verbose_error ("Name field occurs twice in '%s'\n", path);
+
+ exit (1);
+ }
+
+ pkg->name = trim_and_sub (pkg, str, path);
+}
+
+static void
+parse_version (Package *pkg, const char *str, const char *path)
+{
+ if (pkg->version)
+ {
+ verbose_error ("Version field occurs twice in '%s'\n", path);
+
+ exit (1);
+ }
+
+ pkg->version = trim_and_sub (pkg, str, path);
+}
+
+static void
+parse_description (Package *pkg, const char *str, const char *path)
+{
+ if (pkg->description)
+ {
+ verbose_error ("Description field occurs twice in '%s'\n", path);
+
+ exit (1);
+ }
+
+ pkg->description = trim_and_sub (pkg, str, path);
+}
+
+
+#define MODULE_SEPARATOR(c) ((c) == ',' || isspace ((c)))
+#define OPERATOR_CHAR(c) ((c) == '<' || (c) == '>' || (c) == '!' || (c) == '=')
+
+/* A module list is a list of modules with optional version specification,
+ * separated by commas and/or spaces. Commas are treated just like whitespace,
+ * in order to allow stuff like: Requires: @FRIBIDI_PC@, glib, gmodule
+ * where @FRIBIDI_PC@ gets substituted to nothing or to 'fribidi'
+ */
+
+typedef enum
+{
+ /* put numbers to help interpret lame debug spew ;-) */
+ OUTSIDE_MODULE = 0,
+ IN_MODULE_NAME = 1,
+ BEFORE_OPERATOR = 2,
+ IN_OPERATOR = 3,
+ AFTER_OPERATOR = 4,
+ IN_MODULE_VERSION = 5
+} ModuleSplitState;
+
+#define PARSE_SPEW 0
+
+static GSList*
+split_module_list (const char *str, const char *path)
+{
+ GSList *retval = NULL;
+ const char *p;
+ const char *start;
+ ModuleSplitState state = OUTSIDE_MODULE;
+ ModuleSplitState last_state = OUTSIDE_MODULE;
+
+ /* fprintf (stderr, "Parsing: '%s'\n", str); */
+
+ start = str;
+ p = str;
+
+ while (*p)
+ {
+#if PARSE_SPEW
+ fprintf (stderr, "p: %c state: %d last_state: %d\n", *p, state, last_state);
+#endif
+
+ switch (state)
+ {
+ case OUTSIDE_MODULE:
+ if (!MODULE_SEPARATOR (*p))
+ state = IN_MODULE_NAME;
+ break;
+
+ case IN_MODULE_NAME:
+ if (isspace (*p))
+ {
+ /* Need to look ahead to determine next state */
+ const char *s = p;
+ while (*s && isspace (*s))
+ ++s;
+
+ if (*s == '\0')
+ state = OUTSIDE_MODULE;
+ else if (MODULE_SEPARATOR (*s))
+ state = OUTSIDE_MODULE;
+ else if (OPERATOR_CHAR (*s))
+ state = BEFORE_OPERATOR;
+ else
+ state = OUTSIDE_MODULE;
+ }
+ else if (MODULE_SEPARATOR (*p))
+ state = OUTSIDE_MODULE; /* comma precludes any operators */
+ break;
+
+ case BEFORE_OPERATOR:
+ /* We know an operator is coming up here due to lookahead from
+ * IN_MODULE_NAME
+ */
+ if (isspace (*p))
+ ; /* no change */
+ else if (OPERATOR_CHAR (*p))
+ state = IN_OPERATOR;
+ else
+ g_assert_not_reached ();
+ break;
+
+ case IN_OPERATOR:
+ if (!OPERATOR_CHAR (*p))
+ state = AFTER_OPERATOR;
+ break;
+
+ case AFTER_OPERATOR:
+ if (!isspace (*p))
+ state = IN_MODULE_VERSION;
+ break;
+
+ case IN_MODULE_VERSION:
+ if (MODULE_SEPARATOR (*p))
+ state = OUTSIDE_MODULE;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (state == OUTSIDE_MODULE &&
+ last_state != OUTSIDE_MODULE)
+ {
+ /* We left a module */
+ char *module = g_strndup (start, p - start);
+ retval = g_slist_prepend (retval, module);
+
+#if PARSE_SPEW
+ fprintf (stderr, "found module: '%s'\n", module);
+#endif
+
+ /* reset start */
+ start = p;
+ }
+
+ last_state = state;
+ ++p;
+ }
+
+ if (p != start)
+ {
+ /* get the last module */
+ char *module = g_strndup (start, p - start);
+ retval = g_slist_prepend (retval, module);
+
+#if PARSE_SPEW
+ fprintf (stderr, "found module: '%s'\n", module);
+#endif
+
+ }
+
+ retval = g_slist_reverse (retval);
+
+ return retval;
+}
+
+GSList*
+parse_module_list (Package *pkg, const char *str, const char *path)
+{
+ GSList *split;
+ GSList *iter;
+ GSList *retval = NULL;
+
+ split = split_module_list (str, path);
+
+ iter = split;
+ while (iter != NULL)
+ {
+ RequiredVersion *ver;
+ char *p;
+ char *start;
+
+ p = iter->data;
+
+ ver = g_new0 (RequiredVersion, 1);
+ ver->comparison = ALWAYS_MATCH;
+ ver->owner = pkg;
+ retval = g_slist_prepend (retval, ver);
+
+ while (*p && MODULE_SEPARATOR (*p))
+ ++p;
+
+ start = p;
+
+ while (*p && !isspace (*p))
+ ++p;
+
+ while (*p && MODULE_SEPARATOR (*p))
+ {
+ *p = '\0';
+ ++p;
+ }
+
+ if (*start == '\0')
+ {
+ verbose_error ("Empty package name in Requires or Conflicts in file '%s'\n", path);
+
+ exit (1);
+ }
+
+ ver->name = g_strdup (start);
+
+ start = p;
+
+ while (*p && !isspace (*p))
+ ++p;
+
+ while (*p && isspace (*p))
+ {
+ *p = '\0';
+ ++p;
+ }
+
+ if (*start != '\0')
+ {
+ if (strcmp (start, "=") == 0)
+ ver->comparison = EQUAL;
+ else if (strcmp (start, ">=") == 0)
+ ver->comparison = GREATER_THAN_EQUAL;
+ else if (strcmp (start, "<=") == 0)
+ ver->comparison = LESS_THAN_EQUAL;
+ else if (strcmp (start, ">") == 0)
+ ver->comparison = GREATER_THAN;
+ else if (strcmp (start, "<") == 0)
+ ver->comparison = LESS_THAN;
+ else if (strcmp (start, "!=") == 0)
+ ver->comparison = NOT_EQUAL;
+ else
+ {
+ verbose_error ("Unknown version comparison operator '%s' after package name '%s' in file '%s'\n", start, ver->name, path);
+
+ exit (1);
+ }
+ }
+
+ start = p;
+
+ while (*p && !MODULE_SEPARATOR (*p))
+ ++p;
+
+ while (*p && MODULE_SEPARATOR (*p))
+ {
+ *p = '\0';
+ ++p;
+ }
+
+ if (ver->comparison != ALWAYS_MATCH && *start == '\0')
+ {
+ verbose_error ("Comparison operator but no version after package name '%s' in file '%s'\n", ver->name, path);
+
+ exit (1);
+ }
+
+ if (*start != '\0')
+ {
+ ver->version = g_strdup (start);
+ }
+
+ g_assert (ver->name);
+
+ iter = g_slist_next (iter);
+ }
+
+ g_slist_foreach (split, (GFunc) g_free, NULL);
+ g_slist_free (split);
+
+ retval = g_slist_reverse (retval);
+
+ return retval;
+}
+
+static void
+parse_requires (Package *pkg, const char *str, const char *path)
+{
+ GSList *parsed;
+ GSList *iter;
+ char *trimmed;
+
+ if (pkg->requires)
+ {
+ verbose_error ("Requires field occurs twice in '%s'\n", path);
+
+ exit (1);
+ }
+
+ trimmed = trim_and_sub (pkg, str, path);
+ parsed = parse_module_list (pkg, trimmed, path);
+ g_free (trimmed);
+
+ iter = parsed;
+ while (iter != NULL)
+ {
+ Package *req;
+ RequiredVersion *ver = iter->data;
+
+ req = get_package (ver->name);
+
+ if (req == NULL)
+ {
+ verbose_error ("Package '%s', required by '%s', not found\n",
+ ver->name, pkg->name ? pkg->name : path);
+
+ exit (1);
+ }
+
+ if (pkg->required_versions == NULL)
+ pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_hash_table_insert (pkg->required_versions, ver->name, ver);
+
+ pkg->requires = g_slist_prepend (pkg->requires, req);
+
+ iter = g_slist_next (iter);
+ }
+
+ g_slist_free (parsed);
+
+ pkg->requires = g_slist_reverse (pkg->requires);
+}
+
+static void
+parse_conflicts (Package *pkg, const char *str, const char *path)
+{
+ GSList *parsed;
+ GSList *iter;
+ char *trimmed;
+
+ if (pkg->conflicts)
+ {
+ verbose_error ("Conflicts field occurs twice in '%s'\n", path);
+
+ exit (1);
+ }
+
+ trimmed = trim_and_sub (pkg, str, path);
+ pkg->conflicts = parse_module_list (pkg, trimmed, path);
+ g_free (trimmed);
+}
+
+static void
+parse_libs (Package *pkg, const char *str, const char *path)
+{
+ /* Strip out -l and -L flags, put them in a separate list. */
+
+ char *trimmed;
+ GString *other;
+ char **argv = NULL;
+ int argc;
+ int result;
+ int i;
+
+ if (pkg->l_libs || pkg->L_libs || pkg->other_libs)
+ {
+ verbose_error ("Libs field occurs twice in '%s'\n", path);
+
+ exit (1);
+ }
+
+ trimmed = trim_and_sub (pkg, str, path);
+
+ result = poptParseArgvString (trimmed, &argc, &argv);
+
+ if (result < 0)
+ {
+ verbose_error ("Couldn't parse Libs field into an argument vector: %s\n",
+ poptStrerror (result));
+
+ exit (1);
+ }
+
+ other = g_string_new ("");
+
+ i = 0;
+ while (i < argc)
+ {
+ char *arg = trim_string (argv[i]);
+ char *p;
+ char *start;
+
+ start = arg;
+ p = start;
+
+ if (p[0] == '-' &&
+ p[1] == 'l')
+ {
+ char *libname;
+
+ p += 2;
+ while (*p && isspace (*p))
+ ++p;
+
+ start = p;
+ while (*p && !isspace (*p))
+ ++p;
+
+ libname = g_strndup (start, p - start);
+
+ pkg->l_libs = g_slist_prepend (pkg->l_libs,
+ g_strconcat ("-l", libname, NULL));
+
+ g_free (libname);
+ }
+ else if (p[0] == '-' &&
+ p[1] == 'L')
+ {
+ char *libname;
+
+ p += 2;
+ while (*p && isspace (*p))
+ ++p;
+
+ start = p;
+ while (*p && !isspace (*p))
+ ++p;
+
+ libname = g_strndup (start, p - start);
+
+ pkg->L_libs = g_slist_prepend (pkg->L_libs,
+ g_strconcat ("-L", libname, NULL));
+
+ g_free (libname);
+ }
+ else
+ {
+ g_string_append_c (other, ' ');
+ g_string_append (other, arg);
+ g_string_append_c (other, ' ');
+ }
+
+ g_free (arg);
+
+ ++i;
+ }
+
+ g_free (argv);
+ g_free (trimmed);
+
+ pkg->other_libs = other->str;
+
+ g_string_free (other, FALSE);
+
+ pkg->l_libs = g_slist_reverse (pkg->l_libs);
+ pkg->L_libs = g_slist_reverse (pkg->L_libs);
+}
+
+static void
+parse_cflags (Package *pkg, const char *str, const char *path)
+{
+ /* Strip out -I flags, put them in a separate list. */
+
+ char *trimmed;
+ GString *other;
+ char **argv = NULL;
+ int argc;
+ int result;
+ int i;
+
+ if (pkg->I_cflags || pkg->other_cflags)
+ {
+ verbose_error ("Cflags field occurs twice in '%s'\n", path);
+
+ exit (1);
+ }
+
+ trimmed = trim_and_sub (pkg, str, path);
+
+ result = poptParseArgvString (trimmed, &argc, &argv);
+
+ if (result < 0)
+ {
+ verbose_error ("Couldn't parse Cflags field into an argument vector: %s\n",
+ poptStrerror (result));
+
+ exit (1);
+ }
+
+ other = g_string_new ("");
+
+ i = 0;
+ while (i < argc)
+ {
+ char *arg = trim_string (argv[i]);
+ char *p;
+ char *start;
+
+ start = arg;
+ p = start;
+
+ if (p[0] == '-' &&
+ p[1] == 'I')
+ {
+ char *libname;
+
+ p += 2;
+ while (*p && isspace (*p))
+ ++p;
+
+ start = p;
+ while (*p && !isspace (*p))
+ ++p;
+
+ libname = g_strndup (start, p - start);
+
+ pkg->I_cflags = g_slist_prepend (pkg->I_cflags,
+ g_strconcat ("-I", libname, NULL));
+
+ g_free (libname);
+ }
+ else
+ {
+ g_string_append (other, arg);
+ }
+
+ g_free (arg);
+
+ ++i;
+ }
+
+ g_free (argv);
+ g_free (trimmed);
+
+ pkg->other_cflags = other->str;
+
+ g_string_free (other, FALSE);
+
+ pkg->I_cflags = g_slist_reverse (pkg->I_cflags);
+}
+
+static void
+parse_line (Package *pkg, const char *untrimmed, const char *path)
+{
+ char *str;
+ char *p;
+ char *tag;
+
+ debug_spew (" line>%s\n", untrimmed);
+
+ str = trim_string (untrimmed);
+
+ if (*str == '\0')
+ return; /* empty line */
+
+ p = str;
+
+ /* Get first word */
+ while ((*p >= 'A' && *p <= 'Z') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= '0' && *p <= '9') ||
+ *p == '_')
+ p++;
+
+ tag = g_strndup (str, p - str);
+
+ while (*p && isspace (*p))
+ ++p;
+
+ if (*p == ':')
+ {
+ /* keyword */
+ ++p;
+ while (*p && isspace (*p))
+ ++p;
+
+ if (strcmp (tag, "Name") == 0)
+ parse_name (pkg, p, path);
+ else if (strcmp (tag, "Description") == 0)
+ parse_description (pkg, p, path);
+ else if (strcmp (tag, "Version") == 0)
+ parse_version (pkg, p, path);
+ else if (strcmp (tag, "Requires") == 0)
+ parse_requires (pkg, p, path);
+ else if (strcmp (tag, "Libs") == 0)
+ parse_libs (pkg, p, path);
+ else if (strcmp (tag, "Cflags") == 0)
+ parse_cflags (pkg, p, path);
+ else if (strcmp (tag, "Conflicts") == 0)
+ parse_conflicts (pkg, p, path);
+ else
+ {
+ verbose_error ("Unknown keyword '%s' in '%s'\n",
+ tag, path);
+
+ exit (1);
+ }
+ }
+ else if (*p == '=')
+ {
+ /* variable */
+ char *varname;
+ char *varval;
+
+ ++p;
+ while (*p && isspace (*p))
+ ++p;
+
+ if (pkg->vars == NULL)
+ pkg->vars = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if (g_hash_table_lookup (pkg->vars, tag))
+ {
+ verbose_error ("Duplicate definition of variable '%s' in '%s'\n",
+ tag, path);
+
+ exit (1);
+ }
+
+ varname = g_strdup (tag);
+ varval = trim_and_sub (pkg, p, path);
+
+ debug_spew (" Variable declaration, '%s' has value '%s'\n",
+ varname, varval);
+ g_hash_table_insert (pkg->vars, varname, varval);
+
+ }
+
+ g_free (str);
+ g_free (tag);
+}
+
+Package*
+parse_package_file (const char *path)
+{
+ FILE *f;
+ Package *pkg;
+ GString *str;
+ gboolean one_line = FALSE;
+
+ f = fopen (path, "r");
+
+ if (f == NULL)
+ {
+ verbose_error ("Failed to open '%s': %s\n",
+ path, strerror (errno));
+
+ return NULL;
+ }
+
+ debug_spew ("Parsing package file '%s'\n", path);
+
+ pkg = g_new0 (Package, 1);
+
+ if (path)
+ {
+ pkg->pcfiledir = g_dirname (path);
+ }
+ else
+ {
+ debug_spew ("No pcfiledir determined for package\n");
+ pkg->pcfiledir = g_strdup ("???????");
+ }
+
+ str = g_string_new ("");
+
+ while (read_one_line (f, str))
+ {
+ one_line = TRUE;
+
+ parse_line (pkg, str->str, path);
+
+ g_string_truncate (str, 0);
+ }
+
+ if (!one_line)
+ verbose_error ("Package file '%s' appears to be empty\n",
+ path);
+
+ return pkg;
+}
+
+static char *
+backticks (const char *command)
+{
+ FILE *f;
+ char buf[4096];
+ size_t len;
+ int status;
+
+ f = popen (command, "r");
+
+ if (f == NULL)
+ return NULL;
+
+ len = fread (buf, 1, 4090, f);
+
+ if (ferror (f))
+ {
+ pclose (f);
+ return NULL;
+ }
+
+ buf[len] = '\0';
+
+ status = pclose (f);
+
+ return g_strdup (buf);
+}
+
+static gboolean
+try_command (const char *command)
+{
+ int status;
+ char *munged;
+
+ munged = g_strdup_printf ("%s > /dev/null 2>&1", command);
+
+ status = system (munged);
+
+ g_free (munged);
+
+ return WIFEXITED(status) && (WEXITSTATUS(status) == 0);
+}
+
+Package *
+get_compat_package (const char *name)
+{
+ Package *pkg;
+
+ debug_spew ("Looking for '%s' using old-style -config scripts\n", name);
+
+ pkg = g_new0 (Package, 1);
+
+ if (strcmp (name, "glib") == 0)
+ {
+ char *output;
+
+ debug_spew ("Calling glib-config\n");
+
+ pkg->version = backticks ("glib-config --version");
+ if (pkg->version == NULL)
+ {
+ g_free (pkg);
+ return NULL;
+ }
+
+ pkg->name = g_strdup ("GLib");
+ pkg->key = g_strdup ("glib");
+ pkg->description = g_strdup ("C Utility Library");
+
+ output = backticks ("glib-config --libs");
+ parse_libs (pkg, output, "glib-config");
+ g_free (output);
+
+ output = backticks ("glib-config --cflags");
+ parse_cflags (pkg, output, "glib-config");
+ g_free (output);
+
+ return pkg;
+ }
+ else if (strcmp (name, "gtk+") == 0)
+ {
+ char *output;
+
+ debug_spew ("Calling gtk-config\n");
+
+ pkg->version = backticks ("gtk-config --version");
+ if (pkg->version == NULL)
+ {
+ g_free (pkg);
+ return NULL;
+ }
+
+ pkg->name = g_strdup ("GTK+");
+ pkg->key = g_strdup ("gtk+");
+ pkg->description = g_strdup ("GIMP Tool Kit");
+
+ output = backticks ("gtk-config --libs");
+ parse_libs (pkg, output, "gtk-config");
+ g_free (output);
+
+ output = backticks ("gtk-config --cflags");
+ parse_cflags (pkg, output, "gtk-config");
+ g_free (output);
+
+ return pkg;
+ }
+ else if (strcmp (name, "imlib") == 0)
+ {
+ char *output;
+
+ debug_spew ("Calling imlib-config\n");
+
+ pkg->version = backticks ("imlib-config --version");
+ if (pkg->version == NULL)
+ {
+ g_free (pkg);
+ return NULL;
+ }
+
+ pkg->name = g_strdup ("Imlib");
+ pkg->key = g_strdup ("imlib");
+ pkg->description = g_strdup ("Imlib image loading library");
+
+ output = backticks ("imlib-config --libs-gdk");
+ parse_libs (pkg, output, "imlib-config");
+ g_free (output);
+
+ output = backticks ("imlib-config --cflags-gdk");
+ parse_cflags (pkg, output, "imlib-config");
+ g_free (output);
+
+ return pkg;
+ }
+ else if (strcmp (name, "orbit-client") == 0)
+ {
+ char *output;
+ char *p;
+
+ debug_spew ("Calling orbit-config\n");
+
+ output = backticks ("orbit-config --version");
+
+ if (output == NULL)
+ {
+ g_free (pkg);
+ return NULL;
+ }
+
+ p = output;
+
+ while (*p && isspace (*p))
+ ++p;
+
+ if (*p == '\0')
+ {
+ /* empty output */
+ g_free (output);
+ g_free (pkg);
+ return NULL;
+ }
+
+ /* only heuristic; find a number or . */
+ while (*p && ! (isdigit (*p) || *p == '.'))
+ ++p;
+
+ pkg->version = g_strdup (p);
+
+ g_free (output);
+
+ pkg->name = g_strdup ("ORBit Client");
+ pkg->key = g_strdup ("orbit-client");
+ pkg->description = g_strdup ("ORBit Client Libraries");
+
+ output = backticks ("orbit-config --libs client");
+ parse_libs (pkg, output, "orbit-config");
+ g_free (output);
+
+ output = backticks ("orbit-config --cflags client");
+ parse_cflags (pkg, output, "orbit-config");
+ g_free (output);
+
+ return pkg;
+ }
+ else if (strcmp (name, "orbit-server") == 0)
+ {
+ char *output;
+ char *p;
+
+ debug_spew ("Calling orbit-config\n");
+
+ output = backticks ("orbit-config --version");
+
+ if (output == NULL)
+ {
+ g_free (pkg);
+ return NULL;
+ }
+
+ p = output;
+
+ while (*p && isspace (*p))
+ ++p;
+
+ if (*p == '\0')
+ {
+ /* empty output */
+ g_free (output);
+ g_free (pkg);
+ return NULL;
+ }
+
+ /* only heuristic; find a number or . */
+ while (*p && ! (isdigit (*p) || *p == '.'))
+ ++p;
+
+ pkg->version = g_strdup (p);
+
+ g_free (output);
+
+ pkg->name = g_strdup ("ORBit Server");
+ pkg->key = g_strdup ("orbit-server");
+ pkg->description = g_strdup ("ORBit Server Libraries");
+
+ output = backticks ("orbit-config --libs server");
+ parse_libs (pkg, output, "orbit-config");
+ g_free (output);
+
+ output = backticks ("orbit-config --cflags server");
+ parse_cflags (pkg, output, "orbit-config");
+ g_free (output);
+
+ return pkg;
+ }
+ else
+ {
+ /* Check for the module in gnome-config */
+ char *output;
+ char *p;
+ char *command;
+
+ debug_spew ("Calling gnome-config\n");
+
+ /* Annoyingly, --modversion doesn't return a failure
+ * code if the lib is unknown, so we have to use --libs
+ * for that.
+ */
+
+ command = g_strdup_printf ("gnome-config --libs %s",
+ name);
+
+ if (!try_command (command))
+ {
+ g_free (command);
+ g_free (pkg);
+ return NULL;
+ }
+ else
+ g_free (command);
+
+ command = g_strdup_printf ("gnome-config --modversion %s",
+ name);
+
+ output = backticks (command);
+ g_free (command);
+ if (output == NULL)
+ {
+ g_free (pkg);
+ return NULL;
+ }
+
+ /* Unknown modules give "Unknown library `foo'" from gnome-config
+ * (but on stderr so this is useless, nevermind)
+ */
+ if (strstr (output, "Unknown") || *output == '\0')
+ {
+ g_free (output);
+ g_free (pkg);
+ return NULL;
+ }
+
+ /* gnome-config --modversion gnomeui outputs e.g. "gnome-libs-1.2.4"
+ * or libglade-0.12
+ */
+ p = output;
+
+ while (*p && isspace (*p))
+ ++p;
+
+ if (*p == '\0')
+ {
+ /* empty output */
+ g_free (output);
+ g_free (pkg);
+ return NULL;
+ }
+
+ /* only heuristic; find a number or . */
+ while (*p && ! (isdigit (*p) || *p == '.'))
+ ++p;
+
+ pkg->version = g_strdup (p);
+
+ g_free (output);
+
+ /* Strip newline */
+ p = pkg->version;
+ while (*p)
+ {
+ if (*p == '\n')
+ *p = '\0';
+
+ ++p;
+ }
+
+ pkg->name = g_strdup (name);
+ pkg->key = g_strdup (name);
+ pkg->description = g_strdup ("No description");
+
+ command = g_strdup_printf ("gnome-config --libs %s", name);
+ output = backticks (command);
+ g_free (command);
+ parse_libs (pkg, output, "gnome-config");
+ g_free (output);
+
+ command = g_strdup_printf ("gnome-config --cflags %s", name);
+ output = backticks (command);
+ g_free (command);
+ parse_cflags (pkg, output, "gnome-config");
+ g_free (output);
+
+ return pkg;
+ }
+}
+
--- /dev/null
+#ifndef PKG_CONFIG_PARSE_H
+#define PKG_CONFIG_PARSE_H
+
+#include "pkg.h"
+
+Package *parse_package_file (const char *path);
+
+Package *get_compat_package (const char *name);
+
+GSList *parse_module_list (Package *pkg, const char *str, const char *path);
+
+#endif
+
+
+
--- /dev/null
+#ifndef PKG_CONFIG_PARTIAL_GLIB_H
+#define PKG_CONFIG_PARTIAL_GLIB_H
+
+#include "glib-1.2.8/glib.h"
+
+#endif
--- /dev/null
+.\"
+.\" pkg-config manual page.
+.\" (C) Red Hat, Inc. based on gnome-config man page (C) Miguel de Icaza (miguel@gnu.org)
+.\"
+.TH pkg-config 1
+.SH NAME
+pkg-config \- Return metainformation about installed libraries
+.SH SYNOPSIS
+.PP
+.B pkg-config
+[\-\-modversion] [\-\-help] [\-\-print-errors] [\-\-silence-errors]
+[\-\-cflags] [\-\-libs] [\-\-libs-only-L]
+[\-\-libs-only-l] [\-\-cflags-only-I]
+[\-\-variable=VARIABLENAME]
+[\-\-define-variable=VARIABLENAME=VARIABLEVALUE]
+[\-\-uninstalled]
+[\-\-exists] [\-\-atleast-version=VERSION] [\-\-exact-version=VERSION]
+[\-\-max-version=VERSION] [LIBRARIES...]
+.SH DESCRIPTION
+
+The \fIpkg-config\fP program is used to retrieve information about
+installed libraries in the system. It is typically used to compile
+and link against one or more libraries. Here is a typical usage
+scenario in a Makefile:
+.PP
+.nf
+program: program.c
+ cc program.c `pkg-config --cflags --libs gnomeui`
+.fi
+.PP
+
+.PP
+\fIpkg-config\fP retrieves information about packages from
+special metadata files. These files are named after the package,
+with the extension \fI.pc\fP. By default, pkg-config looks in
+the directory \fIprefix\fP/lib/pkgconfig for these files; it will also
+look in the colon-separated list of directories specified by the
+PKG_CONFIG_PATH environment variable.
+
+.PP
+The package name specified on the \fIpkg-config\fP command line is
+defined to be the name of the metadata file, minus the \fI.pc\fP
+extension. If a library can install multiple versions simultaneously,
+it must give each version its own name (for example, GTK 1.2 might
+have the package name "gtk+" while GTK 2.0 has "gtk+-2.0").
+
+.SH OPTIONS
+The following options are supported:
+.TP
+.I "--modversion"
+Requests that the version information of the libraries specified on
+the command line be displayed. If \fIpkg-config\fP can find all the
+libraries on the command line, each library's version string is
+printed to stdout, one version per line. In this case \fIpkg-config\fP
+exits successfully. If one or more libraries is unknown,
+\fIpkg-config\fP exits with a nonzero code, and the contents of stdout
+are undefined.
+.TP
+.I "--help"
+Displays a help message and terminates.
+
+.TP
+.I "--print-errors"
+If one or more of the modules on the command line, or their
+dependencies, are not found, or if an error occurs in parsing a
+\fI.pc\fP file, then this option will cause errors explaining the
+problem to be printed. With "predicate" options such as "--exists"
+\fIpkg-config\fP runs silently by default, because it's usually used
+in scripts that want to control what's output. This option can be used
+alone (to just print errors encountered locating modules on the
+command line) or with other options. The PKG_CONFIG_DEBUG_SPEW
+environment variable overrides this option.
+
+.TP
+.I "--silence-errors"
+If one or more of the modules on the command line, or their
+dependencies, are not found, or if an error occurs in parsing a
+\fI.pc\fP file, then this option will keep errors explaining the
+problem from being printed. With "predicate" options such as
+"--exists" \fIpkg-config\fP runs silently by default, because it's
+usually used in scripts that want to control what's output. So this
+option is only useful with options such as "--cflags" or
+"--modversion" that print errors by default. The PKG_CONFIG_DEBUG_SPEW
+environment variable overrides this option.
+
+.PP
+The following options are used to compile and link programs:
+.TP
+.I "--cflags"
+This prints pre-processor and compile flags required to compile the
+packages on the command line, including flags for all their
+dependencies. Flags are "compressed" so that each identical flag
+appears only once. \fIpkg-config\fP exits with a nonzero code if it
+can't find metadata for one or more of the packages on the command
+line.
+.TP
+.I "--libs"
+This option is identical to "--cflags", only it prints the link
+flags. As with "--cflags", duplicate flags are merged (maintaining
+proper ordering), and flags for dependencies are included in the
+output.
+.TP
+.I "--libs-only-L"
+This prints the -L/-R part of "--libs". That is, it defines the
+library search path but doesn't specify which libraries to link with.
+.TP
+.I "--libs-only-l"
+This prints the -l part of "--libs" for the libraries specified on
+the command line. Note that the union of "--libs-only-l" and
+"--libs-only-L" may be smaller than "--libs", due to flags such as
+-rdynamic.
+
+.TP
+.I "--variable=VARIABLENAME"
+This returns the value of a variable defined in a package's \fI.pc\fP
+file. Most packages define the variable "prefix", for example, so you
+can say:
+.nf
+ $ pkg-config --variable=prefix glib-2.0
+ /usr/
+.fi
+.TP
+.I "--define-variable=VARIABLENAME=VARIABLEVALUE"
+This sets a global value for a variable, overriding the value in any
+\fI.pc\fP files. Most packages define the variable "prefix", for
+example, so you can say:
+.nf
+ $ pkg-config --print-errors --define-variable=prefix=/foo --variable=prefix glib-2.0
+ /foo
+.fi
+
+.TP
+.I "--uninstalled"
+Normally if you request the package "foo" and the package
+"foo-uninstalled" exists, \fIpkg-config\fP will prefer the
+"-uninstalled" variant. This allows compilation/linking against
+uninstalled packages. If you specify the "--uninstalled" option,
+\fIpkg-config\fP will return successfully if any "-uninstalled"
+packages are being used, and return failure (false) otherwise.
+(The "PKG_CONFIG_DISABLE_UNINSTALLED" environment variable keeps
+\fIpkg-config\fP from implicitly choosing "-uninstalled" packages, so
+if that variable is set, they will only have been used if you pass
+a name like "foo-uninstalled" on the command line explicitly.)
+
+.TP
+.I "--exists"
+.TP
+.I "--atleast-version=VERSION"
+.TP
+.I "--exact-version=VERSION"
+.TP
+.I "--max-version=VERSION"
+These options test whether the package or list of packages on the
+command line are known to \fIpkg-config\fP, and optionally
+whether the version number of a package meets certain contraints.
+If all packages exist and meet the specified version constraints,
+\fIpkg-config\fP exits successfully. Otherwise it exits unsuccessfully.
+
+Rather than using the version-test options, you can simply give a version
+constraint after each package name, for example:
+.nf
+ $ pkg-config --exists 'glib-2.0 >= 1.3.4 libxml = 1.8.3'
+.fi
+Remember to use \-\-print-errors if you want error messages.
+
+.SH ENVIRONMENT VARIABLES
+
+.TP
+.I "PKG_CONFIG_PATH"
+A colon-separated list of directories to search for .pc files.
+The default directory will always be searched after searching the
+path; the default is \fIlibdir\fP/pkgconfig where \fIlibdir\fP
+is the libdir where \fIpkg-config\fP was installed.
+
+.TP
+.I "PKG_CONFIG_DEBUG_SPEW"
+If set, causes \fIpkg-config\fP to print all kinds of
+debugging information and report all errors.
+
+.TP
+.I "PKG_CONFIG_TOP_BUILD_DIR"
+A value to set for the magic variable \fIpc_top_builddir\fP
+which may appear in \fI.pc\fP files. If the environment variable is
+not set, the default value '$(top_builddir)' will be used. This
+variable should refer to the top builddir of the Makefile where the
+compile/link flags reported by \fIpkg-config\fP will be used.
+This only matters when compiling/linking against a package that hasn't
+yet been installed.
+
+.TP
+.I "PKG_CONFIG_DISABLE_UNINSTALLED"
+Normally if you request the package "foo" and the package
+"foo-uninstalled" exists, \fIpkg-config\fP will prefer the
+"-uninstalled" variant. This allows compilation/linking against
+uninstalled packages. If this environment variable is set, it
+disables said behavior.
+
+.SH AUTOCONF MACROS
+
+.TP
+.I "PKG_CHECK_MODULES(VARIABLEBASE,MODULELIST[,ACTION-IF-FOUND,[ACTION-IF-NOT-FOUND]])"
+
+The macro PKG_CHECK_MODULES can be used in \fIconfigure.in\fP to
+check whether modules exist. A typical usage would be:
+.nf
+ PKG_CHECK_MODULES(MYSTUFF, gtk+-2.0 >= 1.3.5 libxml = 1.8.4)
+.fi
+
+This would result in MYSTUFF_LIBS and MYSTUFF_CFLAGS substitution
+variables, set to the libs and cflags for the given module list.
+If a module is missing or has the wrong version, by default configure
+will abort with a message. To replace the default action,
+specify an ACTION-IF-NOT-FOUND. PKG_CHECK_MODULES will not print any
+error messages if you specify your own ACTION-IF-NOT-FOUND.
+
+.SH METADATA FILE SYNTAX
+To add a library to the set of packages \fIpkg-config\fP knows about,
+simply install a \fI.pc\fP file. You should install this file to
+\fIlibdir\fP/pkgconfig.
+
+.PP
+Here is an example file:
+.nf
+# This is a comment
+prefix=/home/hp/unst # this defines a variable
+exec_prefix=${prefix} # defining another variable in terms of the first
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: GObject # human-readable name
+Description: Object/type system for GLib # human-readable description
+Version: 1.3.1
+Requires: glib-2.0 = 1.3.1
+Conflicts: foobar <= 4.5
+Libs: -L${libdir} -lgobject-1.3
+Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib/include
+.fi
+
+.PP
+You would normally generate the file using configure, of course, so
+that the prefix, etc. are set to the proper values.
+
+.PP
+Files have two kinds of line: keyword lines start with a keyword plus
+a colon, and variable definitions start with an alphanumeric string
+plus an equals sign. Keywords are defined in advance and have special
+meaning to \fIpkg-config\fP; variables do not, you can have any
+variables that you wish (however, users may expect to retrieve the
+usual directory name variables).
+
+.PP
+Note that variable references are written "${foo}"; you can escape
+literal "${" as "$${".
+
+.TP
+.I "Name:"
+This field should be a human-readable name for the package. Note that
+it is not the name passed as an argument to \fIpkg-config\fP.
+.TP
+.I "Description:"
+This should be a brief description of the package
+.TP
+.I "Version:"
+This should be the most-specific-possible package version string.
+.TP
+.I "Requires:"
+This is a comma-separated list of packages that are required by your
+package. Flags from dependent packages will be merged in to the flags
+reported for your package. Optionally, you can specify the version
+of the required package (using the operators =, <, >, >=, <=);
+specifying a version allows \fIpkg-config\fP to perform extra sanity
+checks. You may only mention the same package one time on the
+.I "Requires:"
+line. If the version of a package is unspecified, any version will
+be used with no checking.
+.TP
+.I "Conflicts:"
+This optional line allows \fIpkg-config\fP to perform additional
+sanity checks, primarily to detect broken user installations. The
+syntax is the same as
+.I "Requires:"
+except that
+you can list the same package more than once here, for example
+"foobar = 1.2.3, foobar = 1.2.5, foobar >= 1.3", if you have reason to
+do so. If a version isn't specified, then your package conflicts with
+all versions of the mentioned package.
+If a user tries to use your package and a conflicting package at the
+same time, then \fIpkg-config\fP will complain.
+.TP
+.I "Libs:"
+This line should give the link flags specific to your package.
+Don't add any flags for required packages; \fIpkg-config\fP will
+add those automatically.
+
+.TP
+.I "Cflags:"
+This line should list the compile flags specific to your package.
+Don't add any flags for required packages; \fIpkg-config\fP will
+add those automatically.
+
+.SH AUTHOR
+
+\fIpkg-config\fP was written by James Henstridge, rewritten by Martijn
+van Beers, and rewritten again by Havoc Pennington. Tim Janik, Owen
+Taylor, and Raja Harinath submitted suggestions and some code.
+\fIgnome-config\fP was written by Miguel de Icaza, Raja Harinath and
+various hackers in the GNOME team. It was inspired by Owen Taylor's
+\fIgtk-config\fP program.
+
+.SH BUGS
+Hah!
+
+
--- /dev/null
+#!/bin/sh
+
+# All variables are prefixed with pc_ so that there is low likelyhood of
+# conflicts with the .pc files.
+
+IFS=":$IFS"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+pc_default_path=@libexecdir@/pkgconfig
+
+if [ ! -d ${pc_default_path} ]; then
+ echo "${pc_default_path} doesn't exist. Make sure you've installed pkgconfig correctly."
+ exit 1;
+fi
+if [ ! -f "${pc_default_path}/gnomeconfig.pce" ]; then
+ echo "Can't find gnomeconfig.pce. Make sure you've installed pkgconfig correctly."
+ exit 1;
+fi
+
+cleanup() {
+ pc_prepend=$1
+ shift
+ pc_keep=$1
+ shift
+ pc_cleanup_var=$1
+ shift
+ pc_temp=""
+ while [ $# -ne 0 ]; do
+ pc_var=$1 # iterate over $1 ...
+ shift
+ if test "x$pc_keep" = "xkeepfirst"; then
+ case " $pc_temp " in
+ *\ $pc_var\ *) ;;
+ *) if test "x$pc_prepend" = "xprepend"; then
+ pc_temp="$pc_var $pc_temp"
+ else
+ pc_temp="$pc_temp $pc_var"
+ fi
+ ;;
+ esac
+ else
+ # use : as seperator because that's what we prepended to IFS
+ case ":$*:" in
+ *\:$pc_var\:*) ;;
+ *) if test "x$pc_prepend" = "xprepend"; then
+ pc_temp="$pc_var $pc_temp"
+ else
+ pc_temp="$pc_temp $pc_var"
+ fi
+ ;;
+ esac
+ fi
+ done
+ eval $pc_cleanup_var='$pc_temp'
+}
+
+find_configfile() {
+ for pc_dir in $pc_path XXX; do
+ if [ -f "${pc_dir}/${pc_pkg}.pc" ]; then
+ . ${pc_dir}/${pc_pkg}.pc
+ break
+ fi
+ done
+ if [ "$pc_dir" = XXX ]; then
+ pc_extns=`ls ${pc_default_path}/*.pce`
+ for pc_ext in $pc_extns XXX; do
+ if [ -f "${pc_ext}" ]; then
+ . ${pc_ext} $pc_pkg
+ # sh on Tru64 (OSF1??) doesn't like return in sourced
+ # files, so we set $result
+ if [ "$result" = "0" ]; then
+ break;
+ fi
+ fi
+ done
+ if [ "$pc_ext" = XXX ]; then
+ echo "couldn't find information for package $pc_pkg." 1>&2
+ exit 1
+ fi
+
+ fi
+}
+
+# make sure we give a non-zero return value if we get interrupted
+# signals HUP, INT and TERM
+trap 'echo; echo "Interrupted."; exit 1' 1 2 15
+
+pc_help_msg="Usage: $0 [-I DIR] [GENERIC_OPTION | FLAGSOPTION...] [LIBRARY...]
+
+ -I DIR Add a directory to the .pc file search path
+
+Generic options:
+ --version Output the pkg-config version and exit
+ --modversion Output the version of the first library and exit
+ --help Show this help and exit
+ --expand Show expanded list of packages to link with
+ --print-pc-dir Print the default .pc search dir and exit
+ --extra-flags Print the extra flags the selected modules support
+ --get-flag FLAGNAME Print the content of the extra flag specified
+
+Output link information for a combination of libraries
+Options to control which compile/link flags to output
+
+ --cflags Show cflags to compile with
+ --libs-only-L Output only -L/-R flags needed for the libraries listed
+ --libs-onlu-l-self Output the -l flags for the libraries listed
+ --libs-only-l-system Output the -l flags for system libraries the
+ listed libraries depend on.
+ --libs Output a combination of all the --libs-only-* flags above
+ LIBRARIES Packages that your program needs to compile
+
+ "
+
+pc_want_ldflags=no
+pc_want_libs_self=no
+pc_want_libs_system=no
+pc_want_cflags=no
+pc_want_libs=no
+pc_want_expand=no
+pc_want_dir=no
+pc_want_varlist=no
+pc_want_extra_var=no
+pc_prev=
+pc_extra_var=
+
+# show help and exit with an errorstatus when no arguments
+if test $# -eq 0; then
+ echo "$pc_help_msg"
+ exit 1
+fi
+
+# add extra path to searched dirs
+pc_path=
+if [ -n "$PC_INCLUDEPATH" ]; then
+ pc_path="${PC_INCLUDEPATH}:${pc_path}"
+fi
+for pc_extra in `echo $GNOME_PATH | sed 's/:/ /g'`; do
+ pc_path="${extra}/libexec/pkgconfig:${pc_path}"
+done
+# only use default path if no other paths are given, to
+# avoid ACLOCAL_CONFIG type problems
+if [ -z "${GNOME_PATH}${PC_INCLUDEPATH}" ]; then
+ pc_path="${pc_default_path}"
+fi
+
+
+while [ $# -ne 0 ]; do
+ pc_arg="$1"
+ shift
+ case "$pc_arg" in
+ -*=*) pc_optarg=`echo $pc_arg | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) pc_optarg= ;;
+ esac
+ if [ -n "$pc_prev" ]; then
+ if [ "$pc_prev" = pcpath ]; then
+ pc_path="$pc_arg:$pc_path"
+ elif [ "$pc_prev" = "extravar" ]; then
+ pc_extra_var="$pc_arg"
+ else
+ eval "$pc_prev=\$pc_arg"
+ fi
+ pc_prev=
+ continue
+ fi
+ case "$pc_arg" in
+ --help)
+ echo "$pc_help_msg"
+ exit 0 ;;
+ --version)
+ echo "pkgconfig @VERSION@"
+ exit 0 ;;
+ -I*) pc_path="`echo $pc_arg | sed 's/^-I//'`:$pc_path" ;;
+ -I) pc_prev=pcpath ;;
+ --cflags) pc_want_cflags=yes ;;
+ --libs-only-L) pc_want_ldflags=yes ;;
+ --libs-only-l-self) pc_want_libs_self=yes ;;
+ --libs-only-l-system) pc_want_libs_system=yes ;;
+ --libs)
+ pc_want_ldflags=yes
+ pc_want_libs_self=yes
+ pc_want_libs_system=yes ;;
+ --expand) pc_want_expand=yes ;;
+ --modversion) pc_want_modversion=yes ;;
+ --print-pc-dir) pc_want_dir=yes ;;
+ --extra-flags) pc_want_varlist=yes ;;
+ --get-flag) pc_prev="extravar" pc_want_var=yes ;;
+ -*)
+ echo "Unknown option: $pc_arg"
+ echo "$pc_help_msg"
+ exit 1 ;;
+ *) pc_caps="$pc_caps $pc_arg" ;;
+ esac
+done
+
+# print the default pc_path only
+if [ "$pc_want_dir" = yes ]; then
+ echo $pc_default_path
+ exit 0
+fi
+
+# expand the packages list, so to satisfy dependencies ...
+set - $pc_caps
+pc_pkgs=""
+while [ $# -ne 0 ]; do
+ pc_pkg="$1"
+ shift
+
+ if [ -z "$pc_pkg" ]; then
+ # ash seems to count the space at the start of pc_caps as an extra
+ # argument. This catches that case.
+ continue
+ fi
+ pc_pkgs="$pc_pkgs $pc_pkg"
+ REQUIRES=""
+
+ find_configfile $pc_pkg
+
+ if [ "x$REQUIRES" != x ]; then
+ for pc_dep in $REQUIRES; do
+ case ":$*:" in
+ *\:$pc_dep\:*) ;;
+ *) set - $* $pc_dep;;
+ esac
+ done
+ fi
+done
+
+# now remove duplicate packages from the list (all but last duplicate) ...
+cleanup prepend keepfirst pc_pkgs $pc_pkgs
+
+
+#
+# from this point on, the list of packages should all exist, and be ordered
+#
+
+# give the module version
+if [ "$pc_want_modversion" = yes ]; then
+ echo $VERSION
+ exit 0
+fi
+
+# list the expanded list of packages if asked for ...
+if [ "$pc_want_expand" = yes ]; then
+ echo $pc_pkgs
+ exit 0;
+fi
+
+# list the list of extra vars
+if [ "$pc_want_varlist" = yes ]; then
+ cleanup prepend keepfirst pc_varlist $EXTRA_VARS
+ echo $pc_varlist
+ exit 0;
+fi
+
+if [ "$pc_want_var" = yes ]; then
+ eval echo \$`eval echo $pc_extra_var`
+ exit 0;
+fi
+
+#ignore what the previous runs of the scripts have set
+CFLAGS=
+LIBS_PATH=
+LIBS_LINK_SELF=
+LIBS_LINK_SYSTEM=
+
+for pc_pkg in $pc_pkgs; do
+ find_configfile $pc_pkg
+done
+
+# clean up duplicate flags. Discard all but last occurence of -l* flags,
+# and all but first occurence of other flags
+if [ "$pc_want_cflags" = "yes" ]; then
+ pc_includepath=
+ for pc_flag in $CFLAGS; do
+ if [ "$pc_flag" != "-I/usr/include" ]; then
+ pc_includepath="$pc_includepath $pc_flag"
+ fi
+ done
+ cleanup append keepfirst CFLAGS $pc_includepath
+ echo -n $CFLAGS
+fi
+if [ "$pc_want_ldflags" = "yes" ]; then
+ pc_libpath=
+ for pc_flag in $LIBS_PATH; do
+ if [ "$pc_flag" != "-L/usr/lib" ]; then
+ pc_libpath="$pc_libpath $pc_flag"
+ fi
+ done
+ cleanup append keepfirst LIBS_PATH $pc_libpath
+ echo -n "$LIBS_PATH"
+fi
+if [ "$pc_want_libs_self" = "yes" ]; then
+ cleanup append keeplast LIBS_LINK_SELF $LIBS_LINK_SELF
+ echo -n "$LIBS_LINK_SELF"
+fi
+if [ "$pc_want_libs_system" = "yes" ];then
+ cleanup append keeplast LIBS_LINK_SYSTEM $LIBS_LINK_SYSTEM
+ echo -n "$LIBS_LINK_SYSTEM"
+fi
+
+#end the line
+echo
+#everything seems to have gone well
+exit 0
+
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pkg.h"
+#include "parse.h"
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#else
+# ifdef _AIX
+# pragma alloca
+# endif
+#endif
+
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static void verify_package (Package *pkg);
+
+static GHashTable *packages = NULL;
+static GHashTable *locations = NULL;
+static GHashTable *globals = NULL;
+static GSList *search_dirs = NULL;
+
+gboolean disable_uninstalled = FALSE;
+
+void
+add_search_dir (const char *path)
+{
+ search_dirs = g_slist_prepend (search_dirs, g_strdup (path));
+}
+
+#define EXT_LEN 3
+
+static gboolean
+ends_in_dotpc (const char *str)
+{
+ int len = strlen (str);
+
+ if (len > EXT_LEN &&
+ str[len - 3] == '.' &&
+ str[len - 2] == 'p' &&
+ str[len - 1] == 'c')
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* strlen ("uninstalled") */
+#define UNINSTALLED_LEN 11
+
+static gboolean
+ends_in_uninstalled (const char *str)
+{
+ int len = strlen (str);
+
+ if (len > UNINSTALLED_LEN &&
+ strcmp ((str + len - UNINSTALLED_LEN), "uninstalled") == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+/* Look for .pc files in the given directory and add them into
+ * locations, ignoring duplicates
+ */
+static void
+scan_dir (const char *dirname)
+{
+ DIR *dir = opendir (dirname);
+ struct dirent *dent;
+ int dirnamelen = strlen (dirname);
+
+ if (dirnamelen > 0 && dirname[dirnamelen-1] == '/')
+ dirnamelen--;
+
+ if (!dir)
+ {
+ debug_spew ("Cannot open directory '%s' in package search path: %s\n",
+ dirname, g_strerror (errno));
+ return;
+ }
+
+ debug_spew ("Scanning directory '%s'\n", dirname);
+
+ while ((dent = readdir (dir)))
+ {
+ int len = strlen (dent->d_name);
+
+ if (ends_in_dotpc (dent->d_name))
+ {
+ char *pkgname = malloc (len - 2);
+
+ debug_spew ("File '%s' appears to be a .pc file\n", dent->d_name);
+
+ strncpy (pkgname, dent->d_name, len - EXT_LEN);
+ pkgname[len-EXT_LEN] = '\0';
+
+ if (g_hash_table_lookup (locations, pkgname))
+ {
+ debug_spew ("File '%s' ignored, we already know about package '%s'\n", dent->d_name, pkgname);
+ g_free (pkgname);
+ }
+ else
+ {
+ char *filename = g_malloc (dirnamelen + 1 + len + 1);
+ strncpy (filename, dirname, dirnamelen);
+ filename[dirnamelen] = '/';
+ strcpy (filename + dirnamelen + 1, dent->d_name);
+
+ g_hash_table_insert (locations, pkgname, filename);
+
+ debug_spew ("Will find package '%s' in file '%s'\n",
+ pkgname, filename);
+ }
+ }
+ else
+ {
+ debug_spew ("Ignoring file '%s' in search directory; not a .pc file\n",
+ dent->d_name);
+ }
+ }
+}
+
+void
+package_init ()
+{
+ static gboolean initted = FALSE;
+
+ if (!initted)
+ {
+ initted = TRUE;
+
+ packages = g_hash_table_new (g_str_hash, g_str_equal);
+ locations = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_slist_foreach (search_dirs, (GFunc)scan_dir, NULL);
+ scan_dir (PKGLIBDIR);
+ }
+}
+
+static gboolean
+file_readable (const char *path)
+{
+ FILE *f = fopen (path, "r");
+
+ if (f != NULL)
+ {
+ fclose (f);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+static Package *
+internal_get_package (const char *name, gboolean warn)
+{
+ Package *pkg = NULL;
+ const char *location;
+
+ pkg = g_hash_table_lookup (packages, name);
+
+ if (pkg)
+ return pkg;
+
+ debug_spew ("Looking for package '%s'\n", name);
+
+ /* treat "name" as a filename if it ends in .pc and exists */
+ if ( ends_in_dotpc (name) )
+ {
+ debug_spew ("Considering '%s' to be a filename rather than a package name\n", name);
+ location = name;
+ }
+ else
+ {
+ /* See if we should auto-prefer the uninstalled version */
+ if (!disable_uninstalled &&
+ !ends_in_uninstalled (name))
+ {
+ char *un;
+
+ un = g_strconcat (name, "-uninstalled", NULL);
+
+ pkg = internal_get_package (un, FALSE);
+
+ g_free (un);
+
+ if (pkg)
+ {
+ debug_spew ("Preferring uninstalled version of package '%s'\n", name);
+ return pkg;
+ }
+ }
+
+ location = g_hash_table_lookup (locations, name);
+ debug_spew ("Reading '%s' from file '%s'\n", name, location);
+ }
+
+ if (location == NULL)
+ {
+ pkg = get_compat_package (name);
+
+ if (pkg == NULL)
+ {
+ if (warn)
+ verbose_error ("Package %s was not found in the pkg-config search path.\n"
+ "Perhaps you should add the directory containing `%s.pc'\n"
+ "to the PKG_CONFIG_PATH environment variable\n",
+ name, name);
+ }
+
+ debug_spew ("Returning values for '%s' from a legacy -config script\n",
+ name);
+
+ return pkg;
+ }
+
+ pkg = parse_package_file (location);
+
+ if (pkg == NULL)
+ {
+ debug_spew ("Failed to parse '%s'\n", location);
+ return NULL;
+ }
+
+ if (strstr (location, "uninstalled.pc"))
+ pkg->uninstalled = TRUE;
+
+ if (location != name)
+ pkg->key = g_strdup (name);
+ else
+ {
+ /* need to strip package name out of the filename */
+ int len = strlen (name);
+ const char *end = name + (len - EXT_LEN);
+ const char *start = end;
+
+ while (start != name && *start != G_DIR_SEPARATOR)
+ --start;
+
+ g_assert (end >= start);
+
+ pkg->key = g_strndup (start, end - start);
+ }
+
+ verify_package (pkg);
+
+ debug_spew ("Adding '%s' to list of known packages, returning as package '%s'\n",
+ pkg->key, name);
+
+ g_hash_table_insert (packages, pkg->key, pkg);
+
+ return pkg;
+}
+
+Package *
+get_package (const char *name)
+{
+ return internal_get_package (name, TRUE);
+}
+
+static GSList*
+string_list_strip_duplicates (GSList *list)
+{
+ GHashTable *table;
+ GSList *tmp;
+ GSList *nodups = NULL;
+
+ table = g_hash_table_new (g_str_hash, g_str_equal);
+
+ tmp = list;
+ while (tmp != NULL)
+ {
+ if (g_hash_table_lookup (table, tmp->data) == NULL)
+ {
+ nodups = g_slist_prepend (nodups, tmp->data);
+ g_hash_table_insert (table, tmp->data, tmp->data);
+ }
+
+ tmp = g_slist_next (tmp);
+ }
+
+ nodups = g_slist_reverse (nodups);
+
+ g_hash_table_destroy (table);
+
+ return nodups;
+}
+
+static GSList*
+string_list_strip_duplicates_from_back (GSList *list)
+{
+ GHashTable *table;
+ GSList *tmp;
+ GSList *nodups = NULL;
+ GSList *reversed;
+
+ table = g_hash_table_new (g_str_hash, g_str_equal);
+
+ reversed = g_slist_reverse (g_slist_copy (list));
+
+ tmp = reversed;
+ while (tmp != NULL)
+ {
+ if (g_hash_table_lookup (table, tmp->data) == NULL)
+ {
+ /* This unreverses the reversed list */
+ nodups = g_slist_prepend (nodups, tmp->data);
+ g_hash_table_insert (table, tmp->data, tmp->data);
+ }
+
+ tmp = g_slist_next (tmp);
+ }
+
+ g_slist_free (reversed);
+
+ g_hash_table_destroy (table);
+
+ return nodups;
+}
+
+static char *
+string_list_to_string (GSList *list)
+{
+ GSList *tmp;
+ GString *str = g_string_new ("");
+ char *retval;
+
+ tmp = list;
+ while (tmp != NULL)
+ {
+ g_string_append (str, tmp->data);
+ g_string_append_c (str, ' ');
+
+ tmp = g_slist_next (tmp);
+ }
+
+ retval = str->str;
+ g_string_free (str, FALSE);
+
+ return retval;
+}
+
+typedef GSList *(* GetListFunc) (Package *pkg);
+
+static GSList *
+get_l_libs (Package *pkg)
+{
+ return pkg->l_libs;
+}
+
+static GSList *
+get_L_libs (Package *pkg)
+{
+ return pkg->L_libs;
+}
+
+static GSList *
+get_I_cflags (Package *pkg)
+{
+ return pkg->I_cflags;
+}
+
+static GSList *
+get_conflicts (Package *pkg)
+{
+ return pkg->conflicts;
+}
+
+static GSList *
+get_requires (Package *pkg)
+{
+ return pkg->requires;
+}
+
+static void
+recursive_fill_list (Package *pkg, GetListFunc func, GSList **listp)
+{
+ GSList *tmp;
+ GSList *copy;
+
+ copy = g_slist_copy ((*func)(pkg));
+
+ *listp = g_slist_concat (*listp, copy);
+
+ tmp = pkg->requires;
+
+ while (tmp != NULL)
+ {
+ recursive_fill_list (tmp->data, func, listp);
+
+ tmp = g_slist_next (tmp);
+ }
+}
+
+static gint
+compare_req_version_names (gconstpointer a, gconstpointer b)
+{
+ const RequiredVersion *ver_a = a;
+ const RequiredVersion *ver_b = b;
+
+ return strcmp (ver_a->name, ver_b->name);
+}
+
+static gint
+compare_package_keys (gconstpointer a, gconstpointer b)
+{
+ const Package *pkg_a = a;
+ const Package *pkg_b = b;
+
+ return strcmp (pkg_a->key, pkg_b->key);
+}
+
+static void
+verify_package (Package *pkg)
+{
+ GSList *requires = NULL;
+ GSList *conflicts = NULL;
+ GSList *iter;
+ GSList *requires_iter;
+ GSList *conflicts_iter;
+
+ /* Be sure we have the required fields */
+
+ if (pkg->key == NULL)
+ {
+ fprintf (stderr,
+ "Internal pkg-config error, package with no key, please file a bug report\n");
+ exit (1);
+ }
+
+ if (pkg->name == NULL)
+ {
+ verbose_error ("Package '%s' has no Name: field\n",
+ pkg->key);
+ exit (1);
+ }
+
+ if (pkg->version == NULL)
+ {
+ verbose_error ("Package '%s' has no Version: field\n",
+ pkg->name);
+ exit (1);
+ }
+
+ if (pkg->description == NULL)
+ {
+ verbose_error ("Package '%s' has no Description: field\n",
+ pkg->description);
+ exit (1);
+ }
+
+ /* Make sure we have the right version for all requirements */
+
+ iter = pkg->requires;
+
+ while (iter != NULL)
+ {
+ Package *req = iter->data;
+ RequiredVersion *ver = NULL;
+
+ if (pkg->required_versions)
+ ver = g_hash_table_lookup (pkg->required_versions,
+ req->key);
+
+ if (ver)
+ {
+ if (!version_test (ver->comparison, req->version, ver->version))
+ {
+ verbose_error ("Package '%s' requires '%s %s %s' but version of %s is %s\n",
+ pkg->name, req->key,
+ comparison_to_str (ver->comparison),
+ ver->version,
+ req->name,
+ req->version);
+
+ exit (1);
+ }
+ }
+
+ iter = g_slist_next (iter);
+ }
+
+ /* Make sure we didn't drag in any conflicts via Requires
+ * (inefficient algorithm, who cares)
+ */
+
+ recursive_fill_list (pkg, get_requires, &requires);
+ recursive_fill_list (pkg, get_conflicts, &conflicts);
+
+ requires_iter = requires;
+ while (requires_iter != NULL)
+ {
+ Package *req = requires_iter->data;
+
+ conflicts_iter = conflicts;
+
+ while (conflicts_iter != NULL)
+ {
+ RequiredVersion *ver = conflicts_iter->data;
+
+ if (version_test (ver->comparison,
+ req->version,
+ ver->version))
+ {
+ verbose_error ("Version %s of %s creates a conflict.\n"
+ "(%s %s %s conflicts with %s %s)\n",
+ req->version, req->name,
+ ver->name,
+ comparison_to_str (ver->comparison),
+ ver->version,
+ ver->owner->name,
+ ver->owner->version);
+
+ exit (1);
+ }
+
+ conflicts_iter = g_slist_next (conflicts_iter);
+ }
+
+ requires_iter = g_slist_next (requires_iter);
+ }
+
+ g_slist_free (requires);
+ g_slist_free (conflicts);
+}
+
+static char*
+get_merged (Package *pkg, GetListFunc func)
+{
+ GSList *list;
+ GSList *dups_list = NULL;
+ char *retval;
+
+ recursive_fill_list (pkg, func, &dups_list);
+
+ list = string_list_strip_duplicates (dups_list);
+
+ g_slist_free (dups_list);
+
+ retval = string_list_to_string (list);
+
+ g_slist_free (list);
+
+ return retval;
+}
+
+static char*
+get_merged_from_back (Package *pkg, GetListFunc func)
+{
+ GSList *list;
+ GSList *dups_list = NULL;
+ char *retval;
+
+ recursive_fill_list (pkg, func, &dups_list);
+
+ list = string_list_strip_duplicates_from_back (dups_list);
+
+ g_slist_free (dups_list);
+
+ retval = string_list_to_string (list);
+
+ g_slist_free (list);
+
+ return retval;
+}
+
+static char*
+get_multi_merged (GSList *pkgs, GetListFunc func)
+{
+ GSList *tmp;
+ GSList *dups_list = NULL;
+ GSList *list;
+ char *retval;
+
+ tmp = pkgs;
+ while (tmp != NULL)
+ {
+ recursive_fill_list (tmp->data, func, &dups_list);
+
+ tmp = g_slist_next (tmp);
+ }
+
+ list = string_list_strip_duplicates (dups_list);
+
+ g_slist_free (dups_list);
+
+ retval = string_list_to_string (list);
+
+ g_slist_free (list);
+
+ return retval;
+}
+
+static char*
+get_multi_merged_from_back (GSList *pkgs, GetListFunc func)
+{
+ GSList *tmp;
+ GSList *dups_list = NULL;
+ GSList *list;
+ char *retval;
+
+ tmp = pkgs;
+ while (tmp != NULL)
+ {
+ recursive_fill_list (tmp->data, func, &dups_list);
+
+ tmp = g_slist_next (tmp);
+ }
+
+ list = string_list_strip_duplicates_from_back (dups_list);
+
+ g_slist_free (dups_list);
+
+ retval = string_list_to_string (list);
+
+ g_slist_free (list);
+
+ return retval;
+}
+
+char *
+package_get_l_libs (Package *pkg)
+{
+ if (pkg->l_libs_merged == NULL)
+ pkg->l_libs_merged = get_merged_from_back (pkg, get_l_libs);
+
+ return pkg->l_libs_merged;
+}
+
+char *
+packages_get_l_libs (GSList *pkgs)
+{
+ return get_multi_merged_from_back (pkgs, get_l_libs);
+}
+
+char *
+package_get_L_libs (Package *pkg)
+{
+ if (pkg->L_libs_merged == NULL)
+ pkg->L_libs_merged = get_merged (pkg, get_L_libs);
+
+ return pkg->L_libs_merged;
+
+}
+
+char *
+packages_get_L_libs (GSList *pkgs)
+{
+ return get_multi_merged (pkgs, get_L_libs);
+}
+
+char *
+package_get_other_libs (Package *pkg)
+{
+ return g_strdup (pkg->other_libs);
+}
+
+char *
+packages_get_other_libs (GSList *pkgs)
+{
+ GSList *tmp;
+ GString *str;
+ char *retval;
+
+ str = g_string_new ("");
+
+ tmp = pkgs;
+ while (tmp != NULL)
+ {
+ Package *pkg = tmp->data;
+
+ if (pkg->other_libs)
+ {
+ g_string_append (str, pkg->other_libs);
+ g_string_append (str, " ");
+ }
+
+ tmp = g_slist_next (tmp);
+ }
+
+ retval = str->str;
+ g_string_free (str, FALSE);
+
+ return retval;
+}
+
+char *
+packages_get_all_libs (GSList *pkgs)
+{
+ char *l_libs;
+ char *L_libs;
+ char *other_libs;
+ GString *str;
+ char *retval;
+
+ str = g_string_new ("");
+
+ other_libs = packages_get_other_libs (pkgs);
+ L_libs = packages_get_L_libs (pkgs);
+ l_libs = packages_get_l_libs (pkgs);
+
+ if (other_libs)
+ g_string_append (str, other_libs);
+
+ if (L_libs)
+ g_string_append (str, L_libs);
+
+ if (l_libs)
+ g_string_append (str, l_libs);
+
+ g_free (l_libs);
+ g_free (L_libs);
+ g_free (other_libs);
+
+ retval = str->str;
+
+ g_string_free (str, FALSE);
+
+ return retval;
+}
+
+char *
+package_get_I_cflags (Package *pkg)
+{
+ if (pkg->I_cflags_merged == NULL)
+ pkg->I_cflags_merged = get_merged (pkg, get_I_cflags);
+
+ return pkg->I_cflags_merged;
+}
+
+char *
+packages_get_I_cflags (GSList *pkgs)
+{
+ return get_multi_merged (pkgs, get_I_cflags);
+}
+
+char *
+package_get_other_cflags (Package *pkg)
+{
+ return g_strdup (pkg->other_cflags);
+}
+
+char *
+packages_get_other_cflags (GSList *pkgs)
+{
+ GSList *tmp;
+ GString *str;
+ char *retval;
+
+ str = g_string_new ("");
+
+ tmp = pkgs;
+ while (tmp != NULL)
+ {
+ Package *pkg = tmp->data;
+
+ if (pkg->other_cflags)
+ {
+ g_string_append (str, pkg->other_cflags);
+ g_string_append (str, " ");
+ }
+
+ tmp = g_slist_next (tmp);
+ }
+
+ retval = str->str;
+ g_string_free (str, FALSE);
+
+ return retval;
+}
+
+char *
+package_get_cflags (Package *pkg)
+{
+
+ g_assert_not_reached ();
+ return NULL;
+}
+
+char *
+packages_get_all_cflags (GSList *pkgs)
+{
+ char *I_cflags;
+ char *other_cflags;
+ GString *str;
+ char *retval;
+
+ str = g_string_new ("");
+
+ other_cflags = packages_get_other_cflags (pkgs);
+ I_cflags = packages_get_I_cflags (pkgs);
+
+ if (other_cflags)
+ g_string_append (str, other_cflags);
+
+ if (I_cflags)
+ g_string_append (str, I_cflags);
+
+ g_free (I_cflags);
+ g_free (other_cflags);
+
+ retval = str->str;
+
+ g_string_free (str, FALSE);
+
+ return retval;
+}
+
+
+void
+define_global_variable (const char *varname,
+ const char *varval)
+{
+ if (globals == NULL)
+ globals = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if (g_hash_table_lookup (globals, varname))
+ {
+ verbose_error ("Variable '%s' defined twice globally\n", varname);
+ exit (1);
+ }
+
+ g_hash_table_insert (globals, g_strdup (varname), g_strdup (varval));
+
+ debug_spew ("Global variable definition '%s' = '%s'\n",
+ varname, varval);
+}
+
+char *
+package_get_var (Package *pkg,
+ const char *var)
+{
+ char *varval = NULL;
+
+ if (globals)
+ varval = g_hash_table_lookup (globals, var);
+
+ if (varval == NULL && pkg->vars)
+ varval = g_strdup (g_hash_table_lookup (pkg->vars, var));
+
+ /* Magic "pcfiledir" variable */
+ if (varval == NULL && pkg->pcfiledir && strcmp (var, "pcfiledir") == 0)
+ varval = g_strdup (pkg->pcfiledir);
+
+ return varval;
+}
+
+char *
+packages_get_var (GSList *pkgs,
+ const char *varname)
+{
+ GSList *tmp;
+ GString *str;
+ char *retval;
+
+ str = g_string_new ("");
+
+ tmp = pkgs;
+ while (tmp != NULL)
+ {
+ Package *pkg = tmp->data;
+ char *var;
+
+ var = package_get_var (pkg, varname);
+
+ if (var)
+ {
+ g_string_append (str, var);
+ g_string_append_c (str, ' ');
+ g_free (var);
+ }
+
+ tmp = g_slist_next (tmp);
+ }
+
+ /* chop last space */
+ str->str[str->len - 1] = '\0';
+ retval = str->str;
+ g_string_free (str, FALSE);
+
+ return retval;
+}
+
+
+
+/* Stolen verbatim from rpm/lib/misc.c
+ RPM is Copyright (c) 1998 by Red Hat Software, Inc.,
+ and may be distributed under the terms of the GPL and LGPL.
+*/
+/* compare alpha and numeric segments of two versions */
+/* return 1: a is newer than b */
+/* 0: a and b are the same version */
+/* -1: b is newer than a */
+static int rpmvercmp(const char * a, const char * b) {
+ char oldch1, oldch2;
+ char * str1, * str2;
+ char * one, * two;
+ int rc;
+ int isnum;
+
+ /* easy comparison to see if versions are identical */
+ if (!strcmp(a, b)) return 0;
+
+ str1 = alloca(strlen(a) + 1);
+ str2 = alloca(strlen(b) + 1);
+
+ strcpy(str1, a);
+ strcpy(str2, b);
+
+ one = str1;
+ two = str2;
+
+ /* loop through each version segment of str1 and str2 and compare them */
+ while (*one && *two) {
+ while (*one && !isalnum(*one)) one++;
+ while (*two && !isalnum(*two)) two++;
+
+ str1 = one;
+ str2 = two;
+
+ /* grab first completely alpha or completely numeric segment */
+ /* leave one and two pointing to the start of the alpha or numeric */
+ /* segment and walk str1 and str2 to end of segment */
+ if (isdigit(*str1)) {
+ while (*str1 && isdigit(*str1)) str1++;
+ while (*str2 && isdigit(*str2)) str2++;
+ isnum = 1;
+ } else {
+ while (*str1 && isalpha(*str1)) str1++;
+ while (*str2 && isalpha(*str2)) str2++;
+ isnum = 0;
+ }
+
+ /* save character at the end of the alpha or numeric segment */
+ /* so that they can be restored after the comparison */
+ oldch1 = *str1;
+ *str1 = '\0';
+ oldch2 = *str2;
+ *str2 = '\0';
+
+ /* take care of the case where the two version segments are */
+ /* different types: one numeric and one alpha */
+ if (one == str1) return -1; /* arbitrary */
+ if (two == str2) return -1;
+
+ if (isnum) {
+ /* this used to be done by converting the digit segments */
+ /* to ints using atoi() - it's changed because long */
+ /* digit segments can overflow an int - this should fix that. */
+
+ /* throw away any leading zeros - it's a number, right? */
+ while (*one == '0') one++;
+ while (*two == '0') two++;
+
+ /* whichever number has more digits wins */
+ if (strlen(one) > strlen(two)) return 1;
+ if (strlen(two) > strlen(one)) return -1;
+ }
+
+ /* strcmp will return which one is greater - even if the two */
+ /* segments are alpha or if they are numeric. don't return */
+ /* if they are equal because there might be more segments to */
+ /* compare */
+ rc = strcmp(one, two);
+ if (rc) return rc;
+
+ /* restore character that was replaced by null above */
+ *str1 = oldch1;
+ one = str1;
+ *str2 = oldch2;
+ two = str2;
+ }
+
+ /* this catches the case where all numeric and alpha segments have */
+ /* compared identically but the segment sepparating characters were */
+ /* different */
+ if ((!*one) && (!*two)) return 0;
+
+ /* whichever version still has characters left over wins */
+ if (!*one) return -1; else return 1;
+}
+
+int
+compare_versions (const char * a, const char *b)
+{
+ return rpmvercmp (a, b);
+}
+
+gboolean
+version_test (ComparisonType comparison,
+ const char *a,
+ const char *b)
+{
+ switch (comparison)
+ {
+ case LESS_THAN:
+ return compare_versions (a, b) < 0;
+ break;
+
+ case GREATER_THAN:
+ return compare_versions (a, b) > 0;
+ break;
+
+ case LESS_THAN_EQUAL:
+ return compare_versions (a, b) <= 0;
+ break;
+
+ case GREATER_THAN_EQUAL:
+ return compare_versions (a, b) >= 0;
+ break;
+
+ case EQUAL:
+ return compare_versions (a, b) == 0;
+ break;
+
+ case NOT_EQUAL:
+ return compare_versions (a, b) != 0;
+ break;
+
+ case ALWAYS_MATCH:
+ return TRUE;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return FALSE;
+}
+
+const char *
+comparison_to_str (ComparisonType comparison)
+{
+ switch (comparison)
+ {
+ case LESS_THAN:
+ return "<";
+ break;
+
+ case GREATER_THAN:
+ return ">";
+ break;
+
+ case LESS_THAN_EQUAL:
+ return "<=";
+ break;
+
+ case GREATER_THAN_EQUAL:
+ return ">=";
+ break;
+
+ case EQUAL:
+ return "=";
+ break;
+
+ case NOT_EQUAL:
+ return "!=";
+ break;
+
+ case ALWAYS_MATCH:
+ return "(any)";
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return "???";
+}
+
+static void
+packages_foreach (gpointer key, gpointer value, gpointer data)
+{
+ Package *pkg = get_package (key);
+
+ if (pkg != NULL)
+ {
+ printf ("%s \t\t%s - %s\n",
+ pkg->key, pkg->name, pkg->description);
+ }
+}
+
+void
+print_package_list (void)
+{
+ g_hash_table_foreach (locations, packages_foreach, NULL);
+}
+
--- /dev/null
+#ifndef PKG_CONFIG_PKG_H
+#define PKG_CONFIG_PKG_H
+
+#include "partial-glib.h"
+
+typedef enum
+{
+ LESS_THAN,
+ GREATER_THAN,
+ LESS_THAN_EQUAL,
+ GREATER_THAN_EQUAL,
+ EQUAL,
+ NOT_EQUAL,
+ ALWAYS_MATCH
+} ComparisonType;
+
+typedef struct _Package Package;
+typedef struct _RequiredVersion RequiredVersion;
+
+struct _RequiredVersion
+{
+ char *name;
+ ComparisonType comparison;
+ char *version;
+ Package *owner;
+};
+
+struct _Package
+{
+ char *key; /* filename name */
+ char *name; /* human-readable name */
+ char *version;
+ char *description;
+ char *pcfiledir; /* directory it was loaded from */
+ GSList *requires;
+ GSList *l_libs;
+ char *l_libs_merged;
+ GSList *L_libs;
+ char *L_libs_merged;
+ char *other_libs;
+ char *other_libs_merged;
+ GSList *I_cflags;
+ char *I_cflags_merged;
+ char *other_cflags;
+ char *other_cflags_merged;
+ GHashTable *vars;
+ GHashTable *required_versions; /* hash from name to RequiredVersion */
+ GSList *conflicts; /* list of RequiredVersion */
+ gboolean uninstalled; /* used the -uninstalled file */
+};
+
+Package *get_package (const char *name);
+char * package_get_l_libs (Package *pkg);
+char * packages_get_l_libs (GSList *pkgs);
+char * package_get_L_libs (Package *pkg);
+char * packages_get_L_libs (GSList *pkgs);
+char * package_get_other_libs (Package *pkg);
+char * packages_get_other_libs (GSList *pkgs);
+char * packages_get_all_libs (GSList *pkgs);
+char * package_get_I_cflags (Package *pkg);
+char * packages_get_I_cflags (GSList *pkgs);
+char * package_get_other_cflags (Package *pkg);
+char * packages_get_all_cflags (GSList *pkgs);
+char * package_get_var (Package *pkg,
+ const char *var);
+char * packages_get_var (GSList *pkgs,
+ const char *var);
+
+
+void add_search_dir (const char *path);
+void package_init (void);
+int compare_versions (const char * a, const char *b);
+gboolean version_test (ComparisonType comparison,
+ const char *a,
+ const char *b);
+
+const char *comparison_to_str (ComparisonType comparison);
+
+void print_package_list (void);
+
+void define_global_variable (const char *varname,
+ const char *varval);
+
+void debug_spew (const char *format, ...);
+void verbose_error (const char *format, ...);
+
+/* If TRUE, do not automatically prefer uninstalled versions */
+extern gboolean disable_uninstalled;
+
+#endif
+
--- /dev/null
+
+dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
+dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
+AC_DEFUN(PKG_CHECK_MODULES,
+[
+ succeeded=no
+
+ if test -z "$PKG_CONFIG"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ fi
+
+ if test "$PKG_CONFIG" = "no" ; then
+ echo "*** The pkg-config script could not be found. Make sure it is"
+ echo "*** in your path, or set the PKG_CONFIG environment variable"
+ echo "*** to the full path to pkg-config."
+ else
+ if ! $PKG_CONFIG --atleast-pkgconfig-version 0.6.0; then
+ echo "*** Your version of pkg-config is too old. You need version 0.6.0 or newer."
+ else
+ AC_MSG_CHECKING(for $2)
+
+ if $PKG_CONFIG --exists "$2" ; then
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+
+ AC_MSG_CHECKING($1_CFLAGS)
+ $1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
+ AC_MSG_RESULT($$1_CFLAGS)
+
+ AC_MSG_CHECKING($1_LIBS)
+ $1_LIBS=`$PKG_CONFIG --libs "$2"
+ AC_MSG_RESULT($$1_LIBS)
+ else
+ $1_CFLAGS=""
+ $1_LIBS=""
+ ## If we have a custom action on failure, don't print errors
+ ifelse([$4], , $PKG_CONFIG --print-errors "$2",)
+ fi
+
+ AC_SUBST($1_CFLAGS)
+ AC_SUBST($1_LIBS)
+ fi
+ fi
+
+ if test $succeeded = yes; then
+ ifelse([$3], , :, [$3])
+ else
+ ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
+ fi
+])
+
+
+dnl Check if the C compiler accepts a certain C flag, and if so adds it to
+dnl CFLAGS
+AC_DEFUN(PKG_CHECK_CFLAG, [
+ AC_MSG_CHECKING(if C compiler accepts $1)
+ save_CFLAGS="$CFLAGS"
+
+ dnl make sure we add it only once
+ dnl this one doesn't seem to work: *[\ \ ]$1[\ \ ]*) ;;
+ case " $CFLAGS " in
+ *\ $1\ *) echo $ac_n "(already in CFLAGS) ... " ;;
+ *\ $1\ *) echo $ac_n "(already in CFLAGS) ... " ;;
+ *\ $1\ *) echo $ac_n "(already in CFLAGS) ... " ;;
+ *\ $1\ *) echo $ac_n "(already in CFLAGS) ... " ;;
+ *) CFLAGS="$CFLAGS $1" ;;
+ esac
+
+ AC_TRY_COMPILE([#include <stdio.h>], [printf("hello");],
+ [ AC_MSG_RESULT(yes)],dnl
+ [ CFLAGS="$save_CFLAGS" AC_MSG_RESULT(no) ])
+])
+
+dnl add $ACLOCAL_FLAGS (and optionally more dirs) to the aclocal
+dnl commandline, so make can work even if it needs to rerun aclocal
+AC_DEFUN(PKG_ACLOCALFLAGS,
+[
+ test -n "$ACLOCAL_FLAGS" && ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS"
+
+ for i in "$1"; do
+ ACLOCAL="$ACLOCAL -I $i"
+ done
+])
--- /dev/null
+/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+ file accompanying popt source distributions, available from
+ ftp://ftp.redhat.com/pub/code/popt */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#else
+# ifdef _AIX
+# pragma alloca
+# endif
+#endif
+
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "findme.h"
+#include "popt.h"
+#include "poptint.h"
+
+void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) {
+ if (con->execPath) free(con->execPath);
+ con->execPath = strdup(path);
+ con->execAbsolute = allowAbsolute;
+}
+
+static void invokeCallbacks(poptContext con, const struct poptOption * table,
+ int post) {
+ const struct poptOption * opt = table;
+ poptCallbackType cb;
+
+ while (opt->longName || opt->shortName || opt->arg) {
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
+ invokeCallbacks(con, opt->arg, post);
+ } else if (((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) &&
+ ((!post && (opt->argInfo & POPT_CBFLAG_PRE)) ||
+ ( post && (opt->argInfo & POPT_CBFLAG_POST)))) {
+ cb = opt->arg;
+ cb(con, post ? POPT_CALLBACK_REASON_POST : POPT_CALLBACK_REASON_PRE,
+ NULL, NULL, opt->descrip);
+ }
+ opt++;
+ }
+}
+
+poptContext poptGetContext(char * name, int argc, char ** argv,
+ const struct poptOption * options, int flags) {
+ poptContext con = malloc(sizeof(*con));
+
+ memset(con, 0, sizeof(*con));
+
+ con->os = con->optionStack;
+ con->os->argc = argc;
+ con->os->argv = argv;
+
+ if (!(flags & POPT_CONTEXT_KEEP_FIRST))
+ con->os->next = 1; /* skip argv[0] */
+
+ con->leftovers = malloc(sizeof(char *) * (argc + 1));
+ con->options = options;
+ con->finalArgv = malloc(sizeof(*con->finalArgv) * (argc * 2));
+ con->finalArgvAlloced = argc * 2;
+ con->flags = flags;
+ con->execAbsolute = 1;
+
+ if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
+ con->flags |= POPT_CONTEXT_POSIXMEHARDER;
+
+ if (name)
+ con->appName = strcpy(malloc(strlen(name) + 1), name);
+
+ invokeCallbacks(con, con->options, 0);
+
+ return con;
+}
+
+void poptResetContext(poptContext con) {
+ con->os = con->optionStack;
+ con->os->currAlias = NULL;
+ con->os->nextCharArg = NULL;
+ con->os->nextArg = NULL;
+ con->os->next = 1; /* skip argv[0] */
+
+ con->numLeftovers = 0;
+ con->nextLeftover = 0;
+ con->restLeftover = 0;
+ con->doExec = NULL;
+ con->finalArgvCount = 0;
+}
+
+/* Only one of longName, shortName may be set at a time */
+static int handleExec(poptContext con, char * longName, char shortName) {
+ int i;
+
+ i = con->numExecs - 1;
+ if (longName) {
+ while (i >= 0 && (!con->execs[i].longName ||
+ strcmp(con->execs[i].longName, longName))) i--;
+ } else {
+ while (i >= 0 &&
+ con->execs[i].shortName != shortName) i--;
+ }
+
+ if (i < 0) return 0;
+
+ if (con->flags & POPT_CONTEXT_NO_EXEC)
+ return 1;
+
+ if (!con->doExec) {
+ con->doExec = con->execs + i;
+ return 1;
+ }
+
+ /* We already have an exec to do; remember this option for next
+ time 'round */
+ if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) {
+ con->finalArgvAlloced += 10;
+ con->finalArgv = realloc(con->finalArgv,
+ sizeof(*con->finalArgv) * con->finalArgvAlloced);
+ }
+
+ i = con->finalArgvCount++;
+ con->finalArgv[i] = malloc((longName ? strlen(longName) : 0) + 3);
+ if (longName)
+ sprintf(con->finalArgv[i], "--%s", longName);
+ else
+ sprintf(con->finalArgv[i], "-%c", shortName);
+
+ return 1;
+}
+
+/* Only one of longName, shortName may be set at a time */
+static int handleAlias(poptContext con, char * longName, char shortName,
+ char * nextCharArg) {
+ int i;
+
+ if (con->os->currAlias && con->os->currAlias->longName && longName &&
+ !strcmp(con->os->currAlias->longName, longName))
+ return 0;
+ if (con->os->currAlias && shortName == con->os->currAlias->shortName)
+ return 0;
+
+ i = con->numAliases - 1;
+ if (longName) {
+ while (i >= 0 && (!con->aliases[i].longName ||
+ strcmp(con->aliases[i].longName, longName))) i--;
+ } else {
+ while (i >= 0 &&
+ con->aliases[i].shortName != shortName) i--;
+ }
+
+ if (i < 0) return 0;
+
+ if ((con->os - con->optionStack + 1)
+ == POPT_OPTION_DEPTH)
+ return POPT_ERROR_OPTSTOODEEP;
+
+ if (nextCharArg && *nextCharArg)
+ con->os->nextCharArg = nextCharArg;
+
+ con->os++;
+ con->os->next = 0;
+ con->os->stuffed = 0;
+ con->os->nextArg = con->os->nextCharArg = NULL;
+ con->os->currAlias = con->aliases + i;
+ con->os->argc = con->os->currAlias->argc;
+ con->os->argv = con->os->currAlias->argv;
+
+ return 1;
+}
+
+static void execCommand(poptContext con) {
+ char ** argv;
+ int pos = 0;
+ char * script = con->doExec->script;
+
+ argv = malloc(sizeof(*argv) *
+ (6 + con->numLeftovers + con->finalArgvCount));
+
+ if (!con->execAbsolute && strchr(script, '/')) return;
+
+ if (!strchr(script, '/') && con->execPath) {
+ argv[pos] = alloca(strlen(con->execPath) + strlen(script) + 2);
+ sprintf(argv[pos], "%s/%s", con->execPath, script);
+ } else {
+ argv[pos] = script;
+ }
+ pos++;
+
+ argv[pos] = findProgramPath(con->os->argv[0]);
+ if (argv[pos]) pos++;
+ argv[pos++] = ";";
+
+ memcpy(argv + pos, con->finalArgv, sizeof(*argv) * con->finalArgvCount);
+ pos += con->finalArgvCount;
+
+ if (con->numLeftovers) {
+ argv[pos++] = "--";
+ memcpy(argv + pos, con->leftovers, sizeof(*argv) * con->numLeftovers);
+ pos += con->numLeftovers;
+ }
+
+ argv[pos++] = NULL;
+
+#ifdef HAVE_SETRESUID
+ setresuid(getuid(), getuid(),-1);
+#endif
+#ifdef HAVE_SETREUID
+ setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
+#endif
+
+ execvp(argv[0], argv);
+}
+
+static const struct poptOption * findOption(const struct poptOption * table,
+ const char * longName,
+ const char shortName,
+ poptCallbackType * callback,
+ void ** callbackData,
+ int singleDash) {
+ const struct poptOption * opt = table;
+ const struct poptOption * opt2;
+ const struct poptOption * cb = NULL;
+
+ while (opt->longName || opt->shortName || opt->arg) {
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
+ opt2 = findOption(opt->arg, longName, shortName, callback,
+ callbackData, singleDash);
+ if (opt2) {
+ if (*callback && !*callbackData)
+ *callbackData = opt->descrip;
+ return opt2;
+ }
+ } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) {
+ cb = opt;
+ } else if (longName && opt->longName &&
+ (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) &&
+ !strcmp(longName, opt->longName)) {
+ break;
+ } else if (shortName && shortName == opt->shortName) {
+ break;
+ }
+ opt++;
+ }
+
+ if (!opt->longName && !opt->shortName) return NULL;
+ *callbackData = NULL;
+ *callback = NULL;
+ if (cb) {
+ *callback = cb->arg;
+ if (!(cb->argInfo & POPT_CBFLAG_INC_DATA))
+ *callbackData = cb->descrip;
+ }
+
+ return opt;
+}
+
+/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
+int poptGetNextOpt(poptContext con) {
+ char * optString, * chptr, * localOptString;
+ char * longArg = NULL;
+ char * origOptString;
+ long aLong;
+ char * end;
+ const struct poptOption * opt = NULL;
+ int done = 0;
+ int i;
+ poptCallbackType cb;
+ void * cbData;
+ int singleDash;
+
+ while (!done) {
+ while (!con->os->nextCharArg && con->os->next == con->os->argc
+ && con->os > con->optionStack)
+ con->os--;
+ if (!con->os->nextCharArg && con->os->next == con->os->argc) {
+ invokeCallbacks(con, con->options, 1);
+ if (con->doExec) execCommand(con);
+ return -1;
+ }
+
+ if (!con->os->nextCharArg) {
+
+ origOptString = con->os->argv[con->os->next++];
+
+ if (con->restLeftover || *origOptString != '-') {
+ con->leftovers[con->numLeftovers++] = origOptString;
+ if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
+ con->restLeftover = 1;
+ continue;
+ }
+
+ /* Make a copy we can hack at */
+ localOptString = optString =
+ strcpy(alloca(strlen(origOptString) + 1),
+ origOptString);
+
+ if (!optString[0])
+ return POPT_ERROR_BADOPT;
+
+ if (optString[1] == '-' && !optString[2]) {
+ con->restLeftover = 1;
+ continue;
+ } else {
+ optString++;
+ if (*optString == '-')
+ singleDash = 0, optString++;
+ else
+ singleDash = 1;
+
+ if (handleAlias(con, optString, '\0', NULL))
+ continue;
+ if (handleExec(con, optString, '\0'))
+ continue;
+
+ chptr = optString;
+ while (*chptr && *chptr != '=') chptr++;
+ if (*chptr == '=') {
+ longArg = origOptString + (chptr - localOptString) + 1;
+ *chptr = '\0';
+ }
+
+ opt = findOption(con->options, optString, '\0', &cb, &cbData,
+ singleDash);
+ if (!opt && !singleDash) return POPT_ERROR_BADOPT;
+ }
+
+ if (!opt)
+ con->os->nextCharArg = origOptString + 1;
+ }
+
+ if (con->os->nextCharArg) {
+ origOptString = con->os->nextCharArg;
+
+ con->os->nextCharArg = NULL;
+
+ if (handleAlias(con, NULL, *origOptString,
+ origOptString + 1)) {
+ origOptString++;
+ continue;
+ }
+ if (handleExec(con, NULL, *origOptString))
+ continue;
+
+ opt = findOption(con->options, NULL, *origOptString, &cb,
+ &cbData, 0);
+ if (!opt) return POPT_ERROR_BADOPT;
+
+ origOptString++;
+ if (*origOptString)
+ con->os->nextCharArg = origOptString;
+ }
+
+ if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE)
+ *((int *)opt->arg) = 1;
+ else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
+ if (longArg) {
+ con->os->nextArg = longArg;
+ } else if (con->os->nextCharArg) {
+ con->os->nextArg = con->os->nextCharArg;
+ con->os->nextCharArg = NULL;
+ } else {
+ while (con->os->next == con->os->argc &&
+ con->os > con->optionStack)
+ con->os--;
+ if (con->os->next == con->os->argc)
+ return POPT_ERROR_NOARG;
+
+ con->os->nextArg = con->os->argv[con->os->next++];
+ }
+
+ if (opt->arg) {
+ switch (opt->argInfo & POPT_ARG_MASK) {
+ case POPT_ARG_STRING:
+ *((char **) opt->arg) = con->os->nextArg;
+ break;
+
+ case POPT_ARG_INT:
+ case POPT_ARG_LONG:
+ aLong = strtol(con->os->nextArg, &end, 0);
+ if (*end)
+ return POPT_ERROR_BADNUMBER;
+
+ if (aLong == LONG_MIN || aLong == LONG_MAX)
+ return POPT_ERROR_OVERFLOW;
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
+ *((long *) opt->arg) = aLong;
+ } else {
+ if (aLong > INT_MAX || aLong < INT_MIN)
+ return POPT_ERROR_OVERFLOW;
+ *((int *) opt->arg) =aLong;
+ }
+ break;
+
+ default:
+ fprintf(stdout, POPT_("option type (%d) not implemented in popt\n"),
+ opt->argInfo & POPT_ARG_MASK);
+ exit(1);
+ }
+ }
+ }
+
+ if (cb)
+ cb(con, POPT_CALLBACK_REASON_OPTION, opt, con->os->nextArg, cbData);
+ else if (opt->val)
+ done = 1;
+
+ if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
+ con->finalArgvAlloced += 10;
+ con->finalArgv = realloc(con->finalArgv,
+ sizeof(*con->finalArgv) * con->finalArgvAlloced);
+ }
+
+ i = con->finalArgvCount++;
+ con->finalArgv[i] =
+ malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
+ if (opt->longName)
+ sprintf(con->finalArgv[i], "--%s", opt->longName);
+ else
+ sprintf(con->finalArgv[i], "-%c", opt->shortName);
+
+ if (opt->arg && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE)
+ con->finalArgv[con->finalArgvCount++] = strdup(con->os->nextArg);
+ }
+
+ return opt->val;
+}
+
+char * poptGetOptArg(poptContext con) {
+ char * ret = con->os->nextArg;
+ con->os->nextArg = NULL;
+ return ret;
+}
+
+char * poptGetArg(poptContext con) {
+ if (con->numLeftovers == con->nextLeftover) return NULL;
+ return (con->leftovers[con->nextLeftover++]);
+}
+
+char * poptPeekArg(poptContext con) {
+ if (con->numLeftovers == con->nextLeftover) return NULL;
+ return (con->leftovers[con->nextLeftover]);
+}
+
+char ** poptGetArgs(poptContext con) {
+ if (con->numLeftovers == con->nextLeftover) return NULL;
+
+ /* some apps like [like RPM ;-) ] need this NULL terminated */
+ con->leftovers[con->numLeftovers] = NULL;
+
+ return (con->leftovers + con->nextLeftover);
+}
+
+void poptFreeContext(poptContext con) {
+ int i;
+
+ for (i = 0; i < con->numAliases; i++) {
+ if (con->aliases[i].longName) free(con->aliases[i].longName);
+ free(con->aliases[i].argv);
+ }
+
+ for (i = 0; i < con->numExecs; i++) {
+ if (con->execs[i].longName) free(con->execs[i].longName);
+ free(con->execs[i].script);
+ }
+
+ for (i = 0; i < con->finalArgvCount; i++)
+ free(con->finalArgv[i]);
+
+ free(con->leftovers);
+ free(con->finalArgv);
+ if (con->appName) free(con->appName);
+ if (con->aliases) free(con->aliases);
+ if (con->otherHelp) free(con->otherHelp);
+ free(con);
+}
+
+int poptAddAlias(poptContext con, struct poptAlias newAlias, int flags) {
+ int aliasNum = con->numAliases++;
+ struct poptAlias * alias;
+
+ /* SunOS won't realloc(NULL, ...) */
+ if (!con->aliases)
+ con->aliases = malloc(sizeof(newAlias) * con->numAliases);
+ else
+ con->aliases = realloc(con->aliases,
+ sizeof(newAlias) * con->numAliases);
+ alias = con->aliases + aliasNum;
+
+ *alias = newAlias;
+ if (alias->longName)
+ alias->longName = strcpy(malloc(strlen(alias->longName) + 1),
+ alias->longName);
+ else
+ alias->longName = NULL;
+
+ return 0;
+}
+
+char * poptBadOption(poptContext con, int flags) {
+ struct optionStackEntry * os;
+
+ if (flags & POPT_BADOPTION_NOALIAS)
+ os = con->optionStack;
+ else
+ os = con->os;
+
+ return os->argv[os->next - 1];
+}
+
+#define POPT_ERROR_NOARG -10
+#define POPT_ERROR_BADOPT -11
+#define POPT_ERROR_OPTSTOODEEP -13
+#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */
+#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */
+
+const char * poptStrerror(const int error) {
+ switch (error) {
+ case POPT_ERROR_NOARG:
+ return POPT_("missing argument");
+ case POPT_ERROR_BADOPT:
+ return POPT_("unknown option");
+ case POPT_ERROR_OPTSTOODEEP:
+ return POPT_("aliases nested too deeply");
+ case POPT_ERROR_BADQUOTE:
+ return POPT_("error in paramter quoting");
+ case POPT_ERROR_BADNUMBER:
+ return POPT_("invalid numeric value");
+ case POPT_ERROR_OVERFLOW:
+ return POPT_("number too large or too small");
+ case POPT_ERROR_ERRNO:
+ return strerror(errno);
+ default:
+ return POPT_("unknown error");
+ }
+}
+
+int poptStuffArgs(poptContext con, char ** argv) {
+ int i;
+
+ if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
+ return POPT_ERROR_OPTSTOODEEP;
+
+ for (i = 0; argv[i]; i++);
+
+ con->os++;
+ con->os->next = 0;
+ con->os->nextArg = con->os->nextCharArg = NULL;
+ con->os->currAlias = NULL;
+ con->os->argc = i;
+ con->os->argv = argv;
+ con->os->stuffed = 1;
+
+ return 0;
+}
+
+const char * poptGetInvocationName(poptContext con) {
+ return con->os->argv[0];
+}
--- /dev/null
+/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+ file accompanying popt source distributions, available from
+ ftp://ftp.redhat.com/pub/code/popt */
+
+#ifndef H_POPT
+#define H_POPT
+
+#include <stdio.h> /* for FILE * */
+
+#define POPT_OPTION_DEPTH 10
+
+#define POPT_ARG_NONE 0
+#define POPT_ARG_STRING 1
+#define POPT_ARG_INT 2
+#define POPT_ARG_LONG 3
+#define POPT_ARG_INCLUDE_TABLE 4 /* arg points to table */
+#define POPT_ARG_CALLBACK 5 /* table-wide callback... must be
+ set first in table; arg points
+ to callback, descrip points to
+ callback data to pass */
+#define POPT_ARG_MASK 0x0000FFFF
+#define POPT_ARGFLAG_ONEDASH 0x80000000 /* allow -longoption */
+#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /* don't show in help/usage */
+#define POPT_CBFLAG_PRE 0x80000000 /* call the callback before parse */
+#define POPT_CBFLAG_POST 0x40000000 /* call the callback after parse */
+#define POPT_CBFLAG_INC_DATA 0x20000000 /* use data from the include line,
+ not the subtable */
+
+#define POPT_ERROR_NOARG -10
+#define POPT_ERROR_BADOPT -11
+#define POPT_ERROR_OPTSTOODEEP -13
+#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */
+#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */
+#define POPT_ERROR_BADNUMBER -17
+#define POPT_ERROR_OVERFLOW -18
+
+/* poptBadOption() flags */
+#define POPT_BADOPTION_NOALIAS (1 << 0) /* don't go into an alias */
+
+/* poptGetContext() flags */
+#define POPT_CONTEXT_NO_EXEC (1 << 0) /* ignore exec expansions */
+#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /* pay attention to argv[0] */
+#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /* options can't follow args */
+
+struct poptOption {
+ const char * longName; /* may be NULL */
+ char shortName; /* may be '\0' */
+ int argInfo;
+ void * arg; /* depends on argInfo */
+ int val; /* 0 means don't return, just update flag */
+ char * descrip; /* description for autohelp -- may be NULL */
+ char * argDescrip; /* argument description for autohelp */
+};
+
+struct poptAlias {
+ char * longName; /* may be NULL */
+ char shortName; /* may be '\0' */
+ int argc;
+ char ** argv; /* must be free()able */
+};
+
+extern struct poptOption poptHelpOptions[];
+#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
+ 0, "Help options", NULL },
+
+typedef struct poptContext_s * poptContext;
+#ifndef __cplusplus
+typedef struct poptOption * poptOption;
+#endif
+
+enum poptCallbackReason { POPT_CALLBACK_REASON_PRE,
+ POPT_CALLBACK_REASON_POST,
+ POPT_CALLBACK_REASON_OPTION };
+typedef void (*poptCallbackType)(poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption * opt,
+ const char * arg, void * data);
+
+poptContext poptGetContext(char * name, int argc, char ** argv,
+ const struct poptOption * options, int flags);
+void poptResetContext(poptContext con);
+
+/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
+int poptGetNextOpt(poptContext con);
+/* returns NULL if no argument is available */
+char * poptGetOptArg(poptContext con);
+/* returns NULL if no more options are available */
+char * poptGetArg(poptContext con);
+char * poptPeekArg(poptContext con);
+char ** poptGetArgs(poptContext con);
+/* returns the option which caused the most recent error */
+char * poptBadOption(poptContext con, int flags);
+void poptFreeContext(poptContext con);
+int poptStuffArgs(poptContext con, char ** argv);
+int poptAddAlias(poptContext con, struct poptAlias alias, int flags);
+int poptReadConfigFile(poptContext con, char * fn);
+/* like above, but reads /etc/popt and $HOME/.popt along with environment
+ vars */
+int poptReadDefaultConfig(poptContext con, int useEnv);
+/* argv should be freed -- this allows ', ", and \ quoting, but ' is treated
+ the same as " and both may include \ quotes */
+int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr);
+const char * poptStrerror(const int error);
+void poptSetExecPath(poptContext con, const char * path, int allowAbsolute);
+void poptPrintHelp(poptContext con, FILE * f, int flags);
+void poptPrintUsage(poptContext con, FILE * f, int flags);
+void poptSetOtherOptionHelp(poptContext con, const char * text);
+const char * poptGetInvocationName(poptContext con);
+
+#endif
--- /dev/null
+/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+ file accompanying popt source distributions, available from
+ ftp://ftp.redhat.com/pub/code/popt */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#else
+# ifdef _AIX
+# pragma alloca
+# endif
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "popt.h"
+#include "poptint.h"
+
+static void configLine(poptContext con, char * line) {
+ int nameLength = strlen(con->appName);
+ char * opt;
+ struct poptAlias alias;
+ char * entryType;
+ char * longName = NULL;
+ char shortName = '\0';
+
+ if (strncmp(line, con->appName, nameLength)) return;
+ line += nameLength;
+ if (!*line || !isspace(*line)) return;
+ while (*line && isspace(*line)) line++;
+ entryType = line;
+
+ while (!*line || !isspace(*line)) line++;
+ *line++ = '\0';
+ while (*line && isspace(*line)) line++;
+ if (!*line) return;
+ opt = line;
+
+ while (!*line || !isspace(*line)) line++;
+ *line++ = '\0';
+ while (*line && isspace(*line)) line++;
+ if (!*line) return;
+
+ if (opt[0] == '-' && opt[1] == '-')
+ longName = opt + 2;
+ else if (opt[0] == '-' && !opt[2])
+ shortName = opt[1];
+
+ if (!strcmp(entryType, "alias")) {
+ if (poptParseArgvString(line, &alias.argc, &alias.argv)) return;
+ alias.longName = longName, alias.shortName = shortName;
+ poptAddAlias(con, alias, 0);
+ } else if (!strcmp(entryType, "exec")) {
+ con->execs = realloc(con->execs,
+ sizeof(*con->execs) * (con->numExecs + 1));
+ if (longName)
+ con->execs[con->numExecs].longName = strdup(longName);
+ else
+ con->execs[con->numExecs].longName = NULL;
+
+ con->execs[con->numExecs].shortName = shortName;
+ con->execs[con->numExecs].script = strdup(line);
+
+ con->numExecs++;
+ }
+}
+
+int poptReadConfigFile(poptContext con, char * fn) {
+ char * file, * chptr, * end;
+ char * buf, * dst;
+ int fd, rc;
+ int fileLength;
+
+ fd = open(fn, O_RDONLY);
+ if (fd < 0) {
+ if (errno == ENOENT)
+ return 0;
+ else
+ return POPT_ERROR_ERRNO;
+ }
+
+ fileLength = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, 0);
+
+ file = alloca(fileLength + 1);
+ if ((fd = read(fd, file, fileLength)) != fileLength) {
+ rc = errno;
+ close(fd);
+ errno = rc;
+ return POPT_ERROR_ERRNO;
+ }
+ close(fd);
+
+ dst = buf = alloca(fileLength + 1);
+
+ chptr = file;
+ end = (file + fileLength);
+ while (chptr < end) {
+ switch (*chptr) {
+ case '\n':
+ *dst = '\0';
+ dst = buf;
+ while (*dst && isspace(*dst)) dst++;
+ if (*dst && *dst != '#') {
+ configLine(con, dst);
+ }
+ chptr++;
+ break;
+ case '\\':
+ *dst++ = *chptr++;
+ if (chptr < end) {
+ if (*chptr == '\n')
+ dst--, chptr++;
+ /* \ at the end of a line does not insert a \n */
+ else
+ *dst++ = *chptr++;
+ }
+ break;
+ default:
+ *dst++ = *chptr++;
+ }
+ }
+
+ return 0;
+}
+
+int poptReadDefaultConfig(poptContext con, int useEnv) {
+ char * fn, * home;
+ int rc;
+
+ if (!con->appName) return 0;
+
+ rc = poptReadConfigFile(con, "/etc/popt");
+ if (rc) return rc;
+ if (getuid() != geteuid()) return 0;
+
+ if ((home = getenv("HOME"))) {
+ fn = alloca(strlen(home) + 20);
+ strcpy(fn, home);
+ strcat(fn, "/.popt");
+ rc = poptReadConfigFile(con, fn);
+ if (rc) return rc;
+ }
+
+ return 0;
+}
+
--- /dev/null
+/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+ file accompanying popt source distributions, available from
+ ftp://ftp.redhat.com/pub/code/popt */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#else
+# ifdef _AIX
+# pragma alloca
+# endif
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "popt.h"
+#include "poptint.h"
+
+static void displayArgs(poptContext con, enum poptCallbackReason foo,
+ struct poptOption * key,
+ const char * arg, void * data) {
+ if (key->shortName== '?')
+ poptPrintHelp(con, stderr, 0);
+ else
+ poptPrintUsage(con, stderr, 0);
+ exit(0);
+}
+
+struct poptOption poptHelpOptions[] = {
+ { NULL, '\0', POPT_ARG_CALLBACK, &displayArgs, '\0', NULL },
+ { "help", '?', 0, NULL, '?', N_("Show this help message") },
+ { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message") },
+ { NULL, '\0', 0, NULL, 0 }
+} ;
+
+static const char * getArgDescrip(const struct poptOption * opt) {
+ if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
+
+ if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
+ if (opt->argDescrip) return POPT_(opt->argDescrip);
+
+ if (opt->argDescrip) return _(opt->argDescrip);
+ return POPT_("ARG");
+}
+
+static void singleOptionHelp(FILE * f, int maxLeftCol,
+ const struct poptOption * opt) {
+ int indentLength = maxLeftCol + 5;
+ int lineLength = 79 - indentLength;
+ const char * help = _(opt->descrip);
+ int helpLength;
+ const char * ch;
+ char format[10];
+ char * left = alloca(maxLeftCol + 1);
+ const char * argDescrip = getArgDescrip(opt);
+
+ *left = '\0';
+ if (opt->longName && opt->shortName)
+ sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
+ else if (opt->shortName)
+ sprintf(left, "-%c", opt->shortName);
+ else if (opt->longName)
+ sprintf(left, "--%s", opt->longName);
+ if (!*left) return ;
+ if (argDescrip) {
+ strcat(left, "=");
+ strcat(left, argDescrip);
+ }
+
+ if (help)
+ fprintf(f," %-*s ", maxLeftCol, left);
+ else {
+ fprintf(f," %s\n", left);
+ return;
+ }
+
+ helpLength = strlen(help);
+ while (helpLength > lineLength) {
+ ch = help + lineLength - 1;
+ while (ch > help && !isspace(*ch)) ch--;
+ if (ch == help) break; /* give up */
+ while (ch > (help + 1) && isspace(*ch)) ch--;
+ ch++;
+
+ sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
+ fprintf(f, format, help, " ");
+ help = ch;
+ while (isspace(*help) && *help) help++;
+ helpLength = strlen(help);
+ }
+
+ if (helpLength) fprintf(f, "%s\n", help);
+}
+
+static int maxArgWidth(const struct poptOption * opt) {
+ int max = 0;
+ int this;
+ const char * s;
+
+ while (opt->longName || opt->shortName || opt->arg) {
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
+ this = maxArgWidth(opt->arg);
+ if (this > max) max = this;
+ } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
+ this = opt->shortName ? 2 : 0;
+ if (opt->longName) {
+ if (this) this += 2;
+ this += strlen(opt->longName) + 2;
+ }
+
+ s = getArgDescrip(opt);
+ if (s)
+ this += strlen(s) + 1;
+ if (this > max) max = this;
+ }
+
+ opt++;
+ }
+
+ return max;
+}
+
+static void singleTableHelp(FILE * f, const struct poptOption * table,
+ int left) {
+ const struct poptOption * opt;
+
+ opt = table;
+ while (opt->longName || opt->shortName || opt->arg) {
+ if ((opt->longName || opt->shortName) &&
+ !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
+ singleOptionHelp(f, left, opt);
+ opt++;
+ }
+
+ opt = table;
+ while (opt->longName || opt->shortName || opt->arg) {
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
+ if (opt->descrip)
+ fprintf(f, "\n%s\n", _(opt->descrip));
+ singleTableHelp(f, opt->arg, left);
+ }
+ opt++;
+ }
+}
+
+static int showHelpIntro(poptContext con, FILE * f) {
+ int len = 6;
+ char * fn;
+
+ fprintf(f, POPT_("Usage:"));
+ if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
+ fn = con->optionStack->argv[0];
+ if (strchr(fn, '/')) fn = strchr(fn, '/') + 1;
+ fprintf(f, " %s", fn);
+ len += strlen(fn) + 1;
+ }
+
+ return len;
+}
+
+void poptPrintHelp(poptContext con, FILE * f, int flags) {
+ int leftColWidth;
+
+ showHelpIntro(con, f);
+ if (con->otherHelp)
+ fprintf(f, " %s\n", con->otherHelp);
+ else
+ fprintf(f, " %s\n", POPT_("[OPTION...]"));
+
+ leftColWidth = maxArgWidth(con->options);
+ singleTableHelp(f, con->options, leftColWidth);
+}
+
+static int singleOptionUsage(FILE * f, int cursor,
+ const struct poptOption * opt) {
+ int len = 3;
+ char shortStr[2];
+ const char * item = shortStr;
+ const char * argDescrip = getArgDescrip(opt);
+
+ if (opt->shortName) {
+ if (!(opt->argInfo & POPT_ARG_MASK))
+ return cursor; /* we did these already */
+ len++;
+ *shortStr = opt->shortName;
+ shortStr[1] = '\0';
+ } else if (opt->longName) {
+ len += 1 + strlen(opt->longName);
+ item = opt->longName;
+ }
+
+ if (len == 3) return cursor;
+
+ if (argDescrip)
+ len += strlen(argDescrip) + 1;
+
+ if ((cursor + len) > 79) {
+ fprintf(f, "\n ");
+ cursor = 7;
+ }
+
+ fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
+ argDescrip ? (opt->shortName ? " " : "=") : "",
+ argDescrip ? argDescrip : "");
+
+ return cursor + len + 1;
+}
+
+int singleTableUsage(FILE * f, int cursor, const struct poptOption * table) {
+ const struct poptOption * opt;
+
+ opt = table;
+ while (opt->longName || opt->shortName || opt->arg) {
+ if ((opt->longName || opt->shortName) &&
+ !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
+ cursor = singleOptionUsage(f, cursor, opt);
+ else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
+ cursor = singleTableUsage(f, cursor, opt->arg);
+ opt++;
+ }
+
+ return cursor;
+}
+
+static int showShortOptions(const struct poptOption * opt, FILE * f,
+ char * str) {
+ char s[300]; /* this is larger then the ascii set, so
+ it should do just fine */
+
+ if (!str) {
+ str = s;
+ memset(str, 0, sizeof(str));
+ }
+
+ while (opt->longName || opt->shortName || opt->arg) {
+ if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
+ str[strlen(str)] = opt->shortName;
+ else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
+ showShortOptions(opt->arg, f, str);
+
+ opt++;
+ }
+
+ if (s != str || !*s)
+ return 0;
+
+ fprintf(f, " [-%s]", s);
+ return strlen(s) + 4;
+}
+
+void poptPrintUsage(poptContext con, FILE * f, int flags) {
+ int cursor;
+
+ cursor = showHelpIntro(con, f);
+ cursor += showShortOptions(con->options, f, NULL);
+ singleTableUsage(f, cursor, con->options);
+
+ if (con->otherHelp) {
+ cursor += strlen(con->otherHelp) + 1;
+ if (cursor > 79) fprintf(f, "\n ");
+ fprintf(f, " %s", con->otherHelp);
+ }
+
+ fprintf(f, "\n");
+}
+
+void poptSetOtherOptionHelp(poptContext con, const char * text) {
+ if (con->otherHelp) free(con->otherHelp);
+ con->otherHelp = strdup(text);
+}
--- /dev/null
+/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+ file accompanying popt source distributions, available from
+ ftp://ftp.redhat.com/pub/code/popt */
+
+#ifndef H_POPTINT
+#define H_POPTINT
+
+struct optionStackEntry {
+ int argc;
+ char ** argv;
+ int next;
+ char * nextArg;
+ char * nextCharArg;
+ struct poptAlias * currAlias;
+ int stuffed;
+};
+
+struct execEntry {
+ char * longName;
+ char shortName;
+ char * script;
+};
+
+struct poptContext_s {
+ struct optionStackEntry optionStack[POPT_OPTION_DEPTH], * os;
+ char ** leftovers;
+ int numLeftovers;
+ int nextLeftover;
+ const struct poptOption * options;
+ int restLeftover;
+ char * appName;
+ struct poptAlias * aliases;
+ int numAliases;
+ int flags;
+ struct execEntry * execs;
+ int numExecs;
+ char ** finalArgv;
+ int finalArgvCount;
+ int finalArgvAlloced;
+ struct execEntry * doExec;
+ char * execPath;
+ int execAbsolute;
+ char * otherHelp;
+};
+
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#endif
+
+#ifdef HAVE_GETTEXT
+#define _(foo) gettext(foo)
+#else
+#define _(foo) (foo)
+#endif
+
+#ifdef HAVE_DGETTEXT
+#define POPT_(foo) dgettext("popt", foo)
+#else
+#define POPT_(foo) (foo)
+#endif
+
+#define N_(foo) (foo)
+
+#endif
--- /dev/null
+/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+ file accompanying popt source distributions, available from
+ ftp://ftp.redhat.com/pub/code/popt */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#else
+# ifdef _AIX
+# pragma alloca
+# endif
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "popt.h"
+
+int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr) {
+ char * buf = strcpy(alloca(strlen(s) + 1), s);
+ char * bufStart = buf;
+ char * src, * dst;
+ char quote = '\0';
+ int argvAlloced = 5;
+ char ** argv = malloc(sizeof(*argv) * argvAlloced);
+ char ** argv2;
+ int argc = 0;
+ int i;
+
+ src = s;
+ dst = buf;
+ argv[argc] = buf;
+
+ memset(buf, '\0', strlen(s) + 1);
+
+ while (*src) {
+ if (quote == *src) {
+ quote = '\0';
+ } else if (quote) {
+ if (*src == '\\') {
+ src++;
+ if (!*src) {
+ free(argv);
+ return POPT_ERROR_BADQUOTE;
+ }
+ if (*src != quote) *buf++ = '\\';
+ }
+ *buf++ = *src;
+ } else if (isspace(*src)) {
+ if (*argv[argc]) {
+ buf++, argc++;
+ if (argc == argvAlloced) {
+ argvAlloced += 5;
+ argv = realloc(argv, sizeof(*argv) * argvAlloced);
+ }
+ argv[argc] = buf;
+ }
+ } else switch (*src) {
+ case '"':
+ case '\'':
+ quote = *src;
+ break;
+ case '\\':
+ src++;
+ if (!*src) {
+ free(argv);
+ return POPT_ERROR_BADQUOTE;
+ }
+ /* fallthrough */
+ default:
+ *buf++ = *src;
+ }
+
+ src++;
+ }
+
+ if (strlen(argv[argc])) {
+ argc++, buf++;
+ }
+
+ dst = malloc(argc * sizeof(*argv) + (buf - bufStart));
+ argv2 = (void *) dst;
+ dst += argc * sizeof(*argv);
+ memcpy(argv2, argv, argc * sizeof(*argv));
+ memcpy(dst, bufStart, buf - bufStart);
+
+ for (i = 0; i < argc; i++) {
+ argv2[i] = dst + (argv[i] - bufStart);
+ }
+
+ free(argv);
+
+ *argvPtr = argv2;
+ *argcPtr = argc;
+
+ return 0;
+}