2 * Copyright (C) 2006-2009 Tollef Fog Heen <tfheen@err.no>
3 * Copyright (C) 2001, 2002, 2005-2006 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
32 #ifdef HAVE_SYS_WAIT_H
35 #include <sys/types.h>
38 int dont_define_prefix = FALSE;
39 char *prefix_variable = "prefix";
40 int msvc_syntax = FALSE;
44 #ifndef G_IS_DIR_SEPARATOR
45 #define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/')
50 * Read an entire line from a file into a buffer. Lines may
51 * be delimited with '\n', '\r', '\n\r', or '\r\n'. The delimiter
52 * is not written into the buffer. Text after a '#' character is treated as
53 * a comment and skipped. '\' can be used to escape a # character.
54 * '\' proceding a line delimiter combines adjacent lines. A '\' proceding
55 * any other character is ignored and written into the output buffer
58 * Return value: %FALSE if the stream was already at an EOF character.
61 read_one_line (FILE *stream, GString *str)
63 gboolean quoted = FALSE;
64 gboolean comment = FALSE;
67 g_string_truncate (str, 0);
78 g_string_append_c (str, '\\');
92 g_string_append_c (str, '#');
97 int next_c = getc (stream);
100 (c == '\r' && next_c == '\n') ||
101 (c == '\n' && next_c == '\r')))
102 ungetc (next_c, stream);
107 g_string_append_c (str, '\\');
108 g_string_append_c (str, c);
124 int next_c = getc (stream);
127 (c == '\r' && next_c == '\n') ||
128 (c == '\n' && next_c == '\r')))
129 ungetc (next_c, stream);
135 g_string_append_c (str, c);
146 trim_string (const char *str)
150 g_return_val_if_fail (str != NULL, NULL);
152 while (*str && isspace ((guchar)*str))
156 while (len > 0 && isspace ((guchar)str[len-1]))
159 return g_strndup (str, len);
163 trim_and_sub (Package *pkg, const char *str, const char *path)
169 trimmed = trim_string (str);
171 subst = g_string_new ("");
180 g_string_append_c (subst, '$');
183 else if (p[0] == '$' &&
193 /* Get up to close brace. */
194 while (*p && *p != '}')
197 varname = g_strndup (var_start, p - var_start);
199 ++p; /* past brace */
201 varval = package_get_var (pkg, varname);
205 verbose_error ("Variable '%s' not defined in '%s'\n",
213 g_string_append (subst, varval);
218 g_string_append_c (subst, *p);
226 g_string_free (subst, FALSE);
232 parse_name (Package *pkg, const char *str, const char *path)
236 verbose_error ("Name field occurs twice in '%s'\n", path);
241 pkg->name = trim_and_sub (pkg, str, path);
245 parse_version (Package *pkg, const char *str, const char *path)
249 verbose_error ("Version field occurs twice in '%s'\n", path);
254 pkg->version = trim_and_sub (pkg, str, path);
258 parse_description (Package *pkg, const char *str, const char *path)
260 if (pkg->description)
262 verbose_error ("Description field occurs twice in '%s'\n", path);
267 pkg->description = trim_and_sub (pkg, str, path);
271 #define MODULE_SEPARATOR(c) ((c) == ',' || isspace ((guchar)(c)))
272 #define OPERATOR_CHAR(c) ((c) == '<' || (c) == '>' || (c) == '!' || (c) == '=')
274 /* A module list is a list of modules with optional version specification,
275 * separated by commas and/or spaces. Commas are treated just like whitespace,
276 * in order to allow stuff like: Requires: @FRIBIDI_PC@, glib, gmodule
277 * where @FRIBIDI_PC@ gets substituted to nothing or to 'fribidi'
282 /* put numbers to help interpret lame debug spew ;-) */
288 IN_MODULE_VERSION = 5
294 split_module_list (const char *str, const char *path)
296 GSList *retval = NULL;
299 ModuleSplitState state = OUTSIDE_MODULE;
300 ModuleSplitState last_state = OUTSIDE_MODULE;
302 /* fprintf (stderr, "Parsing: '%s'\n", str); */
310 fprintf (stderr, "p: %c state: %d last_state: %d\n", *p, state, last_state);
316 if (!MODULE_SEPARATOR (*p))
317 state = IN_MODULE_NAME;
321 if (isspace ((guchar)*p))
323 /* Need to look ahead to determine next state */
325 while (*s && isspace ((guchar)*s))
329 state = OUTSIDE_MODULE;
330 else if (MODULE_SEPARATOR (*s))
331 state = OUTSIDE_MODULE;
332 else if (OPERATOR_CHAR (*s))
333 state = BEFORE_OPERATOR;
335 state = OUTSIDE_MODULE;
337 else if (MODULE_SEPARATOR (*p))
338 state = OUTSIDE_MODULE; /* comma precludes any operators */
341 case BEFORE_OPERATOR:
342 /* We know an operator is coming up here due to lookahead from
345 if (isspace ((guchar)*p))
347 else if (OPERATOR_CHAR (*p))
350 g_assert_not_reached ();
354 if (!OPERATOR_CHAR (*p))
355 state = AFTER_OPERATOR;
359 if (!isspace ((guchar)*p))
360 state = IN_MODULE_VERSION;
363 case IN_MODULE_VERSION:
364 if (MODULE_SEPARATOR (*p))
365 state = OUTSIDE_MODULE;
369 g_assert_not_reached ();
372 if (state == OUTSIDE_MODULE &&
373 last_state != OUTSIDE_MODULE)
375 /* We left a module */
376 char *module = g_strndup (start, p - start);
377 retval = g_slist_prepend (retval, module);
380 fprintf (stderr, "found module: '%s'\n", module);
393 /* get the last module */
394 char *module = g_strndup (start, p - start);
395 retval = g_slist_prepend (retval, module);
398 fprintf (stderr, "found module: '%s'\n", module);
403 retval = g_slist_reverse (retval);
409 parse_module_list (Package *pkg, const char *str, const char *path)
413 GSList *retval = NULL;
415 split = split_module_list (str, path);
420 RequiredVersion *ver;
426 ver = g_new0 (RequiredVersion, 1);
427 ver->comparison = ALWAYS_MATCH;
429 retval = g_slist_prepend (retval, ver);
431 while (*p && MODULE_SEPARATOR (*p))
436 while (*p && !isspace ((guchar)*p))
439 while (*p && MODULE_SEPARATOR (*p))
447 verbose_error ("Empty package name in Requires or Conflicts in file '%s'\n", path);
452 ver->name = g_strdup (start);
456 while (*p && !isspace ((guchar)*p))
459 while (*p && isspace ((guchar)*p))
467 if (strcmp (start, "=") == 0)
468 ver->comparison = EQUAL;
469 else if (strcmp (start, ">=") == 0)
470 ver->comparison = GREATER_THAN_EQUAL;
471 else if (strcmp (start, "<=") == 0)
472 ver->comparison = LESS_THAN_EQUAL;
473 else if (strcmp (start, ">") == 0)
474 ver->comparison = GREATER_THAN;
475 else if (strcmp (start, "<") == 0)
476 ver->comparison = LESS_THAN;
477 else if (strcmp (start, "!=") == 0)
478 ver->comparison = NOT_EQUAL;
481 verbose_error ("Unknown version comparison operator '%s' after package name '%s' in file '%s'\n", start, ver->name, path);
489 while (*p && !MODULE_SEPARATOR (*p))
492 while (*p && MODULE_SEPARATOR (*p))
498 if (ver->comparison != ALWAYS_MATCH && *start == '\0')
500 verbose_error ("Comparison operator but no version after package name '%s' in file '%s'\n", ver->name, path);
507 ver->version = g_strdup (start);
510 g_assert (ver->name);
512 iter = g_slist_next (iter);
515 g_slist_foreach (split, (GFunc) g_free, NULL);
516 g_slist_free (split);
518 retval = g_slist_reverse (retval);
524 parse_requires (Package *pkg, const char *str, const char *path)
532 verbose_error ("Requires field occurs twice in '%s'\n", path);
537 trimmed = trim_and_sub (pkg, str, path);
538 parsed = parse_module_list (pkg, trimmed, path);
545 RequiredVersion *ver = iter->data;
547 req = get_package (ver->name);
551 verbose_error ("Package '%s', required by '%s', not found\n",
552 ver->name, pkg->name ? pkg->name : path);
557 if (pkg->required_versions == NULL)
558 pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal);
560 g_hash_table_insert (pkg->required_versions, ver->name, ver);
562 pkg->requires = g_slist_prepend (pkg->requires, req);
564 iter = g_slist_next (iter);
567 g_slist_free (parsed);
571 parse_requires_private (Package *pkg, const char *str, const char *path)
577 if (pkg->requires_private)
579 verbose_error ("Requires.private field occurs twice in '%s'\n", path);
584 trimmed = trim_and_sub (pkg, str, path);
585 parsed = parse_module_list (pkg, trimmed, path);
592 RequiredVersion *ver = iter->data;
594 req = get_package (ver->name);
598 verbose_error ("Package '%s', required by '%s', not found\n",
599 ver->name, pkg->name ? pkg->name : path);
604 if (pkg->required_versions == NULL)
605 pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal);
607 g_hash_table_insert (pkg->required_versions, ver->name, ver);
609 pkg->requires_private = g_slist_prepend (pkg->requires_private, req);
611 iter = g_slist_next (iter);
614 g_slist_free (parsed);
618 parse_conflicts (Package *pkg, const char *str, const char *path)
626 verbose_error ("Conflicts field occurs twice in '%s'\n", path);
631 trimmed = trim_and_sub (pkg, str, path);
632 pkg->conflicts = parse_module_list (pkg, trimmed, path);
636 static void _do_parse_libs (Package *pkg, int argc, char **argv)
640 char *L_flag = (msvc_syntax ? "/libpath:" : "-L");
641 char *l_flag = (msvc_syntax ? "" : "-l");
642 char *lib_suffix = (msvc_syntax ? ".lib" : "");
646 char *lib_suffix = "";
652 char *arg = trim_string (argv[i]);
661 /* -lib: is used by the C# compiler for libs; it's not an -l
663 (strncmp(p, "-lib:", 5) != 0))
668 while (*p && isspace ((guchar)*p))
672 while (*p && !isspace ((guchar)*p))
675 libname = g_strndup (start, p - start);
677 pkg->l_libs = g_slist_prepend (pkg->l_libs,
678 g_strconcat (l_flag, libname, lib_suffix, NULL));
682 else if (p[0] == '-' &&
688 while (*p && isspace ((guchar)*p))
692 while (*p && !isspace ((guchar)*p))
695 libname = g_strndup (start, p - start);
697 pkg->L_libs = g_slist_prepend (pkg->L_libs,
698 g_strconcat (L_flag, libname, NULL));
702 else if (strcmp("-framework",p) == 0 && i+1 < argc)
704 /* Mac OS X has a -framework Foo which is really one option,
705 * so we join those to avoid having -framework Foo
706 * -framework Bar being changed into -framework Foo Bar
709 gchar *framework = trim_string (argv[i+1]);
711 pkg->other_libs = g_slist_prepend (pkg->other_libs,
712 g_strconcat(arg, " ", framework, NULL));
719 pkg->other_libs = g_slist_prepend (pkg->other_libs,
732 parse_libs (Package *pkg, const char *str, const char *path)
734 /* Strip out -l and -L flags, put them in a separate list. */
741 if (pkg->libs_num > 0)
743 verbose_error ("Libs field occurs twice in '%s'\n", path);
748 trimmed = trim_and_sub (pkg, str, path);
750 result = poptParseArgvString (trimmed, &argc, &argv);
754 verbose_error ("Couldn't parse Libs field into an argument vector: %s\n",
755 poptStrerror (result));
760 _do_parse_libs(pkg, argc, argv);
768 parse_libs_private (Package *pkg, const char *str, const char *path)
771 List of private libraries. Private libraries are libraries which
772 are needed in the case of static linking or on platforms not
773 supporting inter-library dependencies. They are not supposed to
774 be used for libraries which are exposed through the library in
775 question. An example of an exposed library is GTK+ exposing Glib.
776 A common example of a private library is libm.
778 Generally, if include another library's headers in your own, it's
779 a public dependency and not a private one.
787 if (pkg->libs_private_num > 0)
789 verbose_error ("Libs.private field occurs twice in '%s'\n", path);
794 trimmed = trim_and_sub (pkg, str, path);
796 result = poptParseArgvString (trimmed, &argc, &argv);
800 verbose_error ("Couldn't parse Libs.private field into an argument vector: %s\n",
801 poptStrerror (result));
806 _do_parse_libs(pkg, argc, argv);
811 pkg->libs_private_num++;
815 parse_cflags (Package *pkg, const char *str, const char *path)
817 /* Strip out -I flags, put them in a separate list. */
825 if (pkg->I_cflags || pkg->other_cflags)
827 verbose_error ("Cflags field occurs twice in '%s'\n", path);
832 trimmed = trim_and_sub (pkg, str, path);
834 result = poptParseArgvString (trimmed, &argc, &argv);
838 verbose_error ("Couldn't parse Cflags field into an argument vector: %s\n",
839 poptStrerror (result));
847 char *arg = trim_string (argv[i]);
860 while (*p && isspace ((guchar)*p))
864 while (*p && !isspace ((guchar)*p))
867 libname = g_strndup (start, p - start);
869 pkg->I_cflags = g_slist_prepend (pkg->I_cflags,
870 g_strconcat ("-I", libname, NULL));
877 pkg->other_cflags = g_slist_prepend (pkg->other_cflags,
891 parse_url (Package *pkg, const char *str, const char *path)
893 if (pkg->url != NULL)
895 verbose_error ("URL field occurs twice in '%s'\n", path);
900 pkg->url = trim_and_sub (pkg, str, path);
904 static char *orig_prefix = NULL;
907 pathnamecmp (const char *a,
911 ((G_IS_DIR_SEPARATOR (*a) && G_IS_DIR_SEPARATOR (*b)) ||
912 g_ascii_toupper (*a) == g_ascii_toupper (*b)))
917 return g_ascii_toupper (*a) - g_ascii_toupper (*b);
922 parse_line (Package *pkg, const char *untrimmed, const char *path,
923 gboolean ignore_requires, gboolean ignore_private_libs,
924 gboolean ignore_requires_private)
930 debug_spew (" line>%s\n", untrimmed);
932 str = trim_string (untrimmed);
934 if (*str == '\0') /* empty line */
943 while ((*p >= 'A' && *p <= 'Z') ||
944 (*p >= 'a' && *p <= 'z') ||
945 (*p >= '0' && *p <= '9') ||
946 *p == '_' || *p == '.')
949 tag = g_strndup (str, p - str);
951 while (*p && isspace ((guchar)*p))
958 while (*p && isspace ((guchar)*p))
961 if (strcmp (tag, "Name") == 0)
962 parse_name (pkg, p, path);
963 else if (strcmp (tag, "Description") == 0)
964 parse_description (pkg, p, path);
965 else if (strcmp (tag, "Version") == 0)
966 parse_version (pkg, p, path);
967 else if (strcmp (tag, "Requires.private") == 0)
969 if (!ignore_requires_private)
970 parse_requires_private (pkg, p, path);
972 else if (strcmp (tag, "Requires") == 0)
974 if (ignore_requires == FALSE)
975 parse_requires (pkg, p, path);
979 else if ((strcmp (tag, "Libs.private") == 0) &&
980 ignore_private_libs == FALSE)
981 parse_libs_private (pkg, p, path);
982 else if (strcmp (tag, "Libs") == 0)
983 parse_libs (pkg, p, path);
984 else if (strcmp (tag, "Cflags") == 0 ||
985 strcmp (tag, "CFlags") == 0)
986 parse_cflags (pkg, p, path);
987 else if (strcmp (tag, "Conflicts") == 0)
988 parse_conflicts (pkg, p, path);
989 else if (strcmp (tag, "URL") == 0)
990 parse_url (pkg, p, path);
993 /* we don't error out on unknown keywords because they may
994 * represent additions to the .pc file format from future
995 * versions of pkg-config. We do make a note of them in the
996 * debug spew though, in order to help catch mistakes in .pc
998 debug_spew ("Unknown keyword '%s' in '%s'\n",
1009 while (*p && isspace ((guchar)*p))
1012 if (pkg->vars == NULL)
1013 pkg->vars = g_hash_table_new (g_str_hash, g_str_equal);
1016 if (!dont_define_prefix && strcmp (tag, prefix_variable) == 0)
1018 /* This is the prefix variable. Try to guesstimate a value for it
1019 * for this package from the location of the .pc file.
1022 gchar *prefix = pkg->pcfiledir;
1023 const int prefix_len = strlen (prefix);
1024 const char *const lib_pkgconfig = "\\lib\\pkgconfig";
1025 const char *const share_pkgconfig = "\\share\\pkgconfig";
1026 const int lib_pkgconfig_len = strlen (lib_pkgconfig);
1027 const int share_pkgconfig_len = strlen (share_pkgconfig);
1029 if ((strlen (prefix) > lib_pkgconfig_len &&
1030 pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0) ||
1031 (strlen (prefix) > share_pkgconfig_len &&
1032 pathnamecmp (prefix + prefix_len - share_pkgconfig_len, share_pkgconfig) == 0))
1034 /* It ends in lib\pkgconfig or share\pkgconfig. Good. */
1038 orig_prefix = g_strdup (p);
1040 prefix = g_strdup (prefix);
1041 if (strlen (prefix) > lib_pkgconfig_len &&
1042 pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0)
1043 prefix[prefix_len - lib_pkgconfig_len] = '\0';
1045 prefix[prefix_len - share_pkgconfig_len] = '\0';
1047 /* Turn backslashes into slashes or
1048 * poptParseArgvString() will eat them when ${prefix}
1049 * has been expanded in parse_libs().
1058 varname = g_strdup (tag);
1059 debug_spew (" Variable declaration, '%s' overridden with '%s'\n",
1061 g_hash_table_insert (pkg->vars, varname, prefix);
1065 else if (!dont_define_prefix &&
1066 orig_prefix != NULL &&
1067 strncmp (p, orig_prefix, strlen (orig_prefix)) == 0 &&
1068 G_IS_DIR_SEPARATOR (p[strlen (orig_prefix)]))
1072 p = str = g_strconcat (g_hash_table_lookup (pkg->vars, prefix_variable), p + strlen (orig_prefix), NULL);
1077 if (g_hash_table_lookup (pkg->vars, tag))
1079 verbose_error ("Duplicate definition of variable '%s' in '%s'\n",
1085 varname = g_strdup (tag);
1086 varval = trim_and_sub (pkg, p, path);
1088 debug_spew (" Variable declaration, '%s' has value '%s'\n",
1090 g_hash_table_insert (pkg->vars, varname, varval);
1100 parse_package_file (const char *path, gboolean ignore_requires,
1101 gboolean ignore_private_libs,
1102 gboolean ignore_requires_private)
1107 gboolean one_line = FALSE;
1109 f = fopen (path, "r");
1113 verbose_error ("Failed to open '%s': %s\n",
1114 path, strerror (errno));
1119 debug_spew ("Parsing package file '%s'\n", path);
1121 pkg = g_new0 (Package, 1);
1125 pkg->pcfiledir = g_dirname (path);
1129 debug_spew ("No pcfiledir determined for package\n");
1130 pkg->pcfiledir = g_strdup ("???????");
1133 str = g_string_new ("");
1135 while (read_one_line (f, str))
1139 parse_line (pkg, str->str, path, ignore_requires, ignore_private_libs,
1140 ignore_requires_private);
1142 g_string_truncate (str, 0);
1146 verbose_error ("Package file '%s' appears to be empty\n",
1148 g_string_free (str, TRUE);
1151 /* make ->requires_private include a copy of the public requires too */
1152 pkg->requires_private = g_slist_concat(g_slist_copy (pkg->requires),
1153 pkg->requires_private);
1155 pkg->requires = g_slist_reverse (pkg->requires);
1157 pkg->requires_private = g_slist_reverse (pkg->requires_private);
1159 pkg->I_cflags = g_slist_reverse (pkg->I_cflags);
1160 pkg->other_cflags = g_slist_reverse (pkg->other_cflags);
1162 pkg->l_libs = g_slist_reverse (pkg->l_libs);
1163 pkg->L_libs = g_slist_reverse (pkg->L_libs);
1164 pkg->other_libs = g_slist_reverse (pkg->other_libs);
1170 backticks (const char *command)
1177 f = popen (command, "r");
1182 len = fread (buf, 1, 4090, f);
1192 status = pclose (f);
1194 return g_strdup (buf);
1198 try_command (const char *command)
1204 munged = g_strdup_printf ("%s > NUL", command);
1206 munged = g_strdup_printf ("%s > /dev/null 2>&1", command);
1209 status = system (munged);
1216 return WIFEXITED(status) && (WEXITSTATUS(status) == 0);
1221 get_compat_package (const char *name)
1224 /* There has never been any of these legacy *-config scripts on
1225 * Windows as far as I know. No use trying to execute them, will
1226 * only confuse users to see the "blabla is not recognized as an
1227 * internal or external command, operable program or batch file"
1235 if (name_ends_in_uninstalled (name))
1236 debug_spew ("Suspiciously looking for compat package for -uninstalled: %s\n", name);
1238 debug_spew ("Looking for '%s' using legacy -config scripts\n", name);
1240 pkg = g_new0 (Package, 1);
1242 pkg->path_position = G_MAXINT;
1244 if (strcmp (name, "glib") == 0)
1248 debug_spew ("Calling glib-config\n");
1250 pkg->version = backticks ("glib-config --version");
1251 if (pkg->version == NULL)
1257 pkg->name = g_strdup ("GLib");
1258 pkg->key = g_strdup ("glib");
1259 pkg->description = g_strdup ("C Utility Library");
1261 output = backticks ("glib-config --libs");
1262 parse_libs (pkg, output, "glib-config");
1265 output = backticks ("glib-config --cflags");
1266 parse_cflags (pkg, output, "glib-config");
1271 else if (strcmp (name, "gtk+") == 0)
1275 debug_spew ("Calling gtk-config\n");
1277 pkg->version = backticks ("gtk-config --version");
1278 if (pkg->version == NULL)
1284 pkg->name = g_strdup ("GTK+");
1285 pkg->key = g_strdup ("gtk+");
1286 pkg->description = g_strdup ("GIMP Tool Kit");
1288 output = backticks ("gtk-config --libs");
1289 parse_libs (pkg, output, "gtk-config");
1292 output = backticks ("gtk-config --cflags");
1293 parse_cflags (pkg, output, "gtk-config");
1298 else if (strcmp (name, "libgnomevfs") == 0)
1302 debug_spew ("Calling gnome-vfs-config\n");
1304 pkg->version = backticks ("gnome-vfs-config --version");
1305 if (pkg->version == NULL)
1311 pkg->name = g_strdup ("GNOME VFS");
1312 pkg->key = g_strdup ("libgnomevfs");
1313 pkg->description = g_strdup ("GNOME Virtual File System");
1315 output = backticks ("gnome-vfs-config --libs");
1316 parse_libs (pkg, output, "gnome-vfs-config");
1319 output = backticks ("gnome-vfs-config --cflags");
1320 parse_cflags (pkg, output, "gnome-vfs-config");
1325 else if (strcmp (name, "imlib") == 0)
1329 debug_spew ("Calling imlib-config\n");
1331 pkg->version = backticks ("imlib-config --version");
1332 if (pkg->version == NULL)
1338 pkg->name = g_strdup ("Imlib");
1339 pkg->key = g_strdup ("imlib");
1340 pkg->description = g_strdup ("Imlib image loading library");
1342 output = backticks ("imlib-config --libs-gdk");
1343 parse_libs (pkg, output, "imlib-config");
1346 output = backticks ("imlib-config --cflags-gdk");
1347 parse_cflags (pkg, output, "imlib-config");
1352 else if (strcmp (name, "orbit-client") == 0)
1357 debug_spew ("Calling orbit-config\n");
1359 output = backticks ("orbit-config --version");
1369 while (*p && isspace ((guchar)*p))
1380 /* only heuristic; find a number or . */
1381 while (*p && ! (isdigit ((guchar)*p) || *p == '.'))
1384 pkg->version = g_strdup (p);
1388 pkg->name = g_strdup ("ORBit Client");
1389 pkg->key = g_strdup ("orbit-client");
1390 pkg->description = g_strdup ("ORBit Client Libraries");
1392 output = backticks ("orbit-config --libs client");
1393 parse_libs (pkg, output, "orbit-config");
1396 output = backticks ("orbit-config --cflags client");
1397 parse_cflags (pkg, output, "orbit-config");
1402 else if (strcmp (name, "orbit-server") == 0)
1407 debug_spew ("Calling orbit-config\n");
1409 output = backticks ("orbit-config --version");
1419 while (*p && isspace ((guchar)*p))
1430 /* only heuristic; find a number or . */
1431 while (*p && ! (isdigit ((guchar)*p) || *p == '.'))
1434 pkg->version = g_strdup (p);
1438 pkg->name = g_strdup ("ORBit Server");
1439 pkg->key = g_strdup ("orbit-server");
1440 pkg->description = g_strdup ("ORBit Server Libraries");
1442 output = backticks ("orbit-config --libs server");
1443 parse_libs (pkg, output, "orbit-config");
1446 output = backticks ("orbit-config --cflags server");
1447 parse_cflags (pkg, output, "orbit-config");
1454 /* Check for the module in gnome-config */
1459 debug_spew ("Calling gnome-config\n");
1461 /* Annoyingly, --modversion doesn't return a failure
1462 * code if the lib is unknown, so we have to use --libs
1466 command = g_strdup_printf ("gnome-config --libs %s",
1469 if (!try_command (command))
1478 command = g_strdup_printf ("gnome-config --modversion %s",
1481 output = backticks (command);
1489 /* Unknown modules give "Unknown library `foo'" from gnome-config
1490 * (but on stderr so this is useless, nevermind)
1492 if (strstr (output, "Unknown") || *output == '\0')
1499 /* gnome-config --modversion gnomeui outputs e.g. "gnome-libs-1.2.4"
1504 while (*p && isspace ((guchar)*p))
1515 /* only heuristic; find a number or . */
1516 while (*p && ! (isdigit ((guchar)*p) || *p == '.'))
1519 pkg->version = g_strdup (p);
1533 pkg->name = g_strdup (name);
1534 pkg->key = g_strdup (name);
1535 pkg->description = g_strdup ("No description");
1537 command = g_strdup_printf ("gnome-config --libs %s", name);
1538 output = backticks (command);
1540 parse_libs (pkg, output, "gnome-config");
1543 command = g_strdup_printf ("gnome-config --cflags %s", name);
1544 output = backticks (command);
1546 parse_cflags (pkg, output, "gnome-config");