Allow errors in .pc files for --list-all

Normally, the parser will exit immediately when it encounters errors in
.pc files. This is good most of the time, but for --list-all, the
purpose is to just get a quick list of packages and not to validate .pc
files. This is especially the case for pkg-config wrappers such as the
Ruby or Bash completion modules that scrape the output from --list-all
and don't expect to encounter errors there.

Freedesktop #26615 (https://bugs.freedesktop.org/show_bug.cgi?id=26615)
This commit is contained in:
Dan Nicholson 2013-05-16 07:03:27 -07:00
parent 2f41b2de42
commit 715cc306b0
6 changed files with 105 additions and 42 deletions

View file

@ -44,6 +44,7 @@ EXTRA_DIST = \
fields-blank.pc \
sub/sub1.pc \
sub/sub2.pc \
sub/broken.pc \
inst.pc \
inst-uninstalled.pc \
other.pc \

View file

@ -34,8 +34,9 @@ RESULT="private-dep >= 1"
run_test --print-requires-private requires-test
# --list-all, limit to a subdirectory
RESULT="sub1 Subdirectory package 1 - Test package 1 for subdirectory
sub2 Subdirectory package 2 - Test package 2 for subdirectory"
RESULT="sub1 Subdirectory package 1 - Test package 1 for subdirectory
sub2 Subdirectory package 2 - Test package 2 for subdirectory
broken Broken package - Module with broken .pc file"
PKG_CONFIG_LIBDIR="$srcdir/sub" run_test --list-all
# Check handling when multiple incompatible options are set

4
check/sub/broken.pc Normal file
View file

@ -0,0 +1,4 @@
Name: Broken package
Description: Module with broken .pc file
Version: 1.0
Name: 2nd name

4
main.c
View file

@ -621,6 +621,10 @@ main (int argc, char **argv)
if (pkg_flags == 0 && !want_requires && !want_exists)
disable_requires();
/* Allow errors in .pc files when listing all. */
if (want_list)
parse_strict = FALSE;
if (want_my_version)
{
printf ("%s\n", VERSION);

130
parse.c
View file

@ -34,6 +34,7 @@
#endif
#include <sys/types.h>
gboolean parse_strict = TRUE;
gboolean define_prefix = ENABLE_DEFINE_PREFIX;
char *prefix_variable = "prefix";
@ -199,8 +200,8 @@ trim_and_sub (Package *pkg, const char *str, const char *path)
{
verbose_error ("Variable '%s' not defined in '%s'\n",
varname, path);
exit (1);
if (parse_strict)
exit (1);
}
g_free (varname);
@ -229,8 +230,10 @@ 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);
if (parse_strict)
exit (1);
else
return;
}
pkg->name = trim_and_sub (pkg, str, path);
@ -242,8 +245,10 @@ 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);
if (parse_strict)
exit (1);
else
return;
}
pkg->version = trim_and_sub (pkg, str, path);
@ -255,8 +260,10 @@ 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);
if (parse_strict)
exit (1);
else
return;
}
pkg->description = trim_and_sub (pkg, str, path);
@ -408,9 +415,8 @@ parse_module_list (Package *pkg, const char *str, const char *path)
GList *retval = NULL;
split = split_module_list (str, path);
iter = split;
while (iter != NULL)
for (iter = split; iter != NULL; iter = g_list_next (iter))
{
RequiredVersion *ver;
char *p;
@ -440,8 +446,10 @@ parse_module_list (Package *pkg, const char *str, const char *path)
if (*start == '\0')
{
verbose_error ("Empty package name in Requires or Conflicts in file '%s'\n", path);
exit (1);
if (parse_strict)
exit (1);
else
continue;
}
ver->name = g_strdup (start);
@ -473,9 +481,13 @@ parse_module_list (Package *pkg, const char *str, const char *path)
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);
verbose_error ("Unknown version comparison operator '%s' after "
"package name '%s' in file '%s'\n", start,
ver->name, path);
if (parse_strict)
exit (1);
else
continue;
}
}
@ -492,9 +504,15 @@ parse_module_list (Package *pkg, const char *str, const char *path)
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);
verbose_error ("Comparison operator but no version after package "
"name '%s' in file '%s'\n", ver->name, path);
if (parse_strict)
exit (1);
else
{
ver->version = g_strdup ("0");
continue;
}
}
if (*start != '\0')
@ -503,8 +521,6 @@ parse_module_list (Package *pkg, const char *str, const char *path)
}
g_assert (ver->name);
iter = g_list_next (iter);
}
g_list_foreach (split, (GFunc) g_free, NULL);
@ -523,8 +539,10 @@ parse_requires (Package *pkg, const char *str, const char *path)
if (pkg->requires)
{
verbose_error ("Requires field occurs twice in '%s'\n", path);
exit (1);
if (parse_strict)
exit (1);
else
return;
}
trimmed = trim_and_sub (pkg, str, path);
@ -540,8 +558,10 @@ parse_requires_private (Package *pkg, const char *str, const char *path)
if (pkg->requires_private)
{
verbose_error ("Requires.private field occurs twice in '%s'\n", path);
exit (1);
if (parse_strict)
exit (1);
else
return;
}
trimmed = trim_and_sub (pkg, str, path);
@ -557,8 +577,10 @@ parse_conflicts (Package *pkg, const char *str, const char *path)
if (pkg->conflicts)
{
verbose_error ("Conflicts field occurs twice in '%s'\n", path);
exit (1);
if (parse_strict)
exit (1);
else
return;
}
trimmed = trim_and_sub (pkg, str, path);
@ -691,8 +713,10 @@ parse_libs (Package *pkg, const char *str, const char *path)
if (pkg->libs_num > 0)
{
verbose_error ("Libs field occurs twice in '%s'\n", path);
exit (1);
if (parse_strict)
exit (1);
else
return;
}
trimmed = trim_and_sub (pkg, str, path);
@ -702,7 +726,13 @@ parse_libs (Package *pkg, const char *str, const char *path)
{
verbose_error ("Couldn't parse Libs field into an argument vector: %s\n",
error ? error->message : "unknown");
exit (1);
if (parse_strict)
exit (1);
else
{
g_free (trimmed);
return;
}
}
_do_parse_libs(pkg, argc, argv);
@ -735,8 +765,10 @@ parse_libs_private (Package *pkg, const char *str, const char *path)
if (pkg->libs_private_num > 0)
{
verbose_error ("Libs.private field occurs twice in '%s'\n", path);
exit (1);
if (parse_strict)
exit (1);
else
return;
}
trimmed = trim_and_sub (pkg, str, path);
@ -746,7 +778,13 @@ parse_libs_private (Package *pkg, const char *str, const char *path)
{
verbose_error ("Couldn't parse Libs.private field into an argument vector: %s\n",
error ? error->message : "unknown");
exit (1);
if (parse_strict)
exit (1);
else
{
g_free (trimmed);
return;
}
}
_do_parse_libs(pkg, argc, argv);
@ -771,8 +809,10 @@ parse_cflags (Package *pkg, const char *str, const char *path)
if (pkg->cflags)
{
verbose_error ("Cflags field occurs twice in '%s'\n", path);
exit (1);
if (parse_strict)
exit (1);
else
return;
}
trimmed = trim_and_sub (pkg, str, path);
@ -782,7 +822,13 @@ parse_cflags (Package *pkg, const char *str, const char *path)
{
verbose_error ("Couldn't parse Cflags field into an argument vector: %s\n",
error ? error->message : "unknown");
exit (1);
if (parse_strict)
exit (1);
else
{
g_free (trimmed);
return;
}
}
i = 0;
@ -843,8 +889,10 @@ parse_url (Package *pkg, const char *str, const char *path)
if (pkg->url != NULL)
{
verbose_error ("URL field occurs twice in '%s'\n", path);
exit (1);
if (parse_strict)
exit (1);
else
return;
}
pkg->url = trim_and_sub (pkg, str, path);
@ -1011,8 +1059,10 @@ parse_line (Package *pkg, const char *untrimmed, const char *path,
{
verbose_error ("Duplicate definition of variable '%s' in '%s'\n",
tag, path);
exit (1);
if (parse_strict)
exit (1);
else
goto cleanup;
}
varname = g_strdup (tag);

3
pkg.h
View file

@ -134,6 +134,9 @@ extern char *pcsysrootdir;
*/
extern char *pkg_config_pc_path;
/* Exit on parse errors if TRUE. */
extern gboolean parse_strict;
/* If TRUE, define "prefix" in .pc files at runtime. */
extern gboolean define_prefix;