struct sparse_file *sparse_file_import(int fd, bool verbose, bool crc) { int ret; sparse_header_t sparse_header; int64_t len; struct sparse_file *s; ret = read_all(fd, &sparse_header, sizeof(sparse_header)); if (ret < 0) { verbose_error(verbose, ret, "header"); return NULL; } if (sparse_header.magic != SPARSE_HEADER_MAGIC) { verbose_error(verbose, -EINVAL, "header magic"); return NULL; } if (sparse_header.major_version != SPARSE_HEADER_MAJOR_VER) { verbose_error(verbose, -EINVAL, "header major version"); return NULL; } if (sparse_header.file_hdr_sz < SPARSE_HEADER_LEN) { return NULL; } if (sparse_header.chunk_hdr_sz < sizeof(chunk_header_t)) { return NULL; } len = (int64_t)sparse_header.total_blks * sparse_header.blk_sz; s = sparse_file_new(sparse_header.blk_sz, len); if (!s) { verbose_error(verbose, -EINVAL, NULL); return NULL; } ret = lseek64(fd, 0, SEEK_SET); if (ret < 0) { verbose_error(verbose, ret, "seeking"); sparse_file_destroy(s); return NULL; } s->verbose = verbose; ret = sparse_file_read(s, fd, true, crc); if (ret < 0) { sparse_file_destroy(s); return NULL; } return s; }
static int process_chunk(struct sparse_file *s, int fd, off64_t offset, unsigned int chunk_hdr_sz, chunk_header_t *chunk_header, unsigned int cur_block, uint32_t *crc_ptr) { int ret; unsigned int chunk_data_size; chunk_data_size = chunk_header->total_sz - chunk_hdr_sz; switch (chunk_header->chunk_type) { case CHUNK_TYPE_RAW: ret = process_raw_chunk(s, chunk_data_size, fd, offset, chunk_header->chunk_sz, cur_block, crc_ptr); if (ret < 0) { verbose_error(s->verbose, ret, "data block at %" PRId64, offset); return ret; } return chunk_header->chunk_sz; case CHUNK_TYPE_FILL: ret = process_fill_chunk(s, chunk_data_size, fd, chunk_header->chunk_sz, cur_block, crc_ptr); if (ret < 0) { verbose_error(s->verbose, ret, "fill block at %" PRId64, offset); return ret; } return chunk_header->chunk_sz; case CHUNK_TYPE_DONT_CARE: ret = process_skip_chunk(s, chunk_data_size, fd, chunk_header->chunk_sz, cur_block, crc_ptr); if (chunk_data_size != 0) { if (ret < 0) { verbose_error(s->verbose, ret, "skip block at %" PRId64, offset); return ret; } } return chunk_header->chunk_sz; case CHUNK_TYPE_CRC32: ret = process_crc32_chunk(fd, chunk_data_size, *crc_ptr); if (ret < 0) { verbose_error(s->verbose, -EINVAL, "crc block at %" PRId64, offset); return ret; } return 0; default: verbose_error(s->verbose, -EINVAL, "unknown block %04X at %" PRId64, chunk_header->chunk_type, offset); } return 0; }
static void parse_libs_private (Package *pkg, const char *str, const char *path) { /* List of private libraries. Private libraries are libraries which are needed in the case of static linking or on platforms not supporting inter-library dependencies. They are not supposed to be used for libraries which are exposed through the library in question. An example of an exposed library is GTK+ exposing Glib. A common example of a private library is libm. Generally, if include another library's headers in your own, it's a public dependency and not a private one. */ char *trimmed; char **argv = NULL; int argc = 0; int result; if (pkg->libs_private_num > 0) { verbose_error ("Libs.private field occurs twice in '%s'\n", path); exit (1); } trimmed = trim_and_sub (pkg, str, path); if (trimmed && *trimmed) { result = poptParseArgvString (trimmed, &argc, &argv); if (result < 0) { verbose_error ("Couldn't parse Libs.private field into an argument vector: %s\n", poptStrerror (result)); exit (1); } } _do_parse_libs(pkg, argc, argv); g_free (argv); g_free (trimmed); pkg->libs_private_num++; }
static void parse_requires_private (Package *pkg, const char *str, const char *path) { GSList *parsed; GSList *iter; char *trimmed; if (pkg->requires_private) { verbose_error ("Requires.private 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_private = g_slist_prepend (pkg->requires_private, req); iter = g_slist_next (iter); } g_slist_free (parsed); }
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_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); } pkg->url = 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); }
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; char **argv = NULL; int argc = 0; int result; if (pkg->libs_num > 0) { verbose_error ("Libs field occurs twice in '%s'\n", path); exit (1); } trimmed = trim_and_sub (pkg, str, path); if (trimmed && *trimmed) { 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); } } _do_parse_libs(pkg, argc, argv); g_free (trimmed); g_free (argv); pkg->libs_num++; }
static void parse_conflicts (Package *pkg, const char *str, const char *path) { 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); }
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); }
adlb_data_code xlb_struct_subscript_init(adlb_struct *s, adlb_subscript subscript, bool validate_path, bool *b) { adlb_data_code dc; adlb_struct_field *field; adlb_struct_field_type field_type; size_t sub_pos; // Initialize subscripts as a way to validate path bool init_nested = validate_path; dc = xlb_struct_lookup(s, subscript, init_nested, &field, &field_type, &sub_pos); ADLB_DATA_CHECK_CODE(dc); if (sub_pos == subscript.length) { // Entire subscript was consumed *b = field->initialized; } else { DEBUG("%zu vs %zu", sub_pos, subscript.length); if (validate_path) { verbose_error(ADLB_DATA_ERROR_SUBSCRIPT_NOT_FOUND, "Subscript invalid: [%.*s] (tail of [%.*s])", (int)(subscript.length - sub_pos), &((const char *)subscript.key)[sub_pos], (int)subscript.length, (const char*)subscript.key); } else { *b = false; } } return ADLB_DATA_SUCCESS; }
/* * Format and output a call to the JavaScript alert() function. * The caller must ensure a JavaScript context. */ NSAPI_PUBLIC void output_alert(int type, char *info, char *details, int wait) { char *wrapped=NULL; int err; if(type >= MAX_ERROR) type=DEFAULT_ERROR; wrapped=alert_word_wrap(details, WORD_WRAP_WIDTH, "\\n"); if(!info) info=""; fprintf(stdout, (wait) ? "confirm(\"" : "alert(\""); fprintf(stdout, "%s:%s\\n%s", error_headers[type], info, wrapped); if(type==FILE_ERROR || type==SYSTEM_ERROR) { err = get_error(); if(err != 0) fprintf(stdout, "\\n\\nThe system returned error number %d, " "which is %s.", err, verbose_error()); } fprintf(stdout, "\");"); FREE(wrapped); }
static gboolean process_package_args (const char *cmdline, GList **packages, FILE *log) { gboolean success = TRUE; GList *reqs; reqs = parse_module_list (NULL, cmdline, "(command line arguments)"); if (reqs == NULL) { fprintf (stderr, "Must specify package names on the command line\n"); fflush (stderr); return FALSE; } for (; reqs != NULL; reqs = g_list_next (reqs)) { Package *req; RequiredVersion *ver = reqs->data; /* override requested versions with cmdline options */ if (required_exact_version) { g_free (ver->version); ver->comparison = EQUAL; ver->version = g_strdup (required_exact_version); } else if (required_atleast_version) { g_free (ver->version); ver->comparison = GREATER_THAN_EQUAL; ver->version = g_strdup (required_atleast_version); } else if (required_max_version) { g_free (ver->version); ver->comparison = LESS_THAN_EQUAL; ver->version = g_strdup (required_max_version); } if (want_short_errors) req = get_package_quiet (ver->name); else req = get_package (ver->name); if (log != NULL) { if (req == NULL) fprintf (log, "%s NOT-FOUND\n", ver->name); else fprintf (log, "%s %s %s\n", ver->name, comparison_to_str (ver->comparison), (ver->version == NULL) ? "(null)" : ver->version); } if (req == NULL) { success = FALSE; verbose_error ("No package '%s' found\n", ver->name); continue; } if (!version_test (ver->comparison, req->version, ver->version)) { success = FALSE; 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); if (req->url) verbose_error ("You may find new versions of %s at %s\n", req->name, req->url); continue; } *packages = g_list_prepend (*packages, req); } *packages = g_list_reverse (*packages); return success; }
static void verify_package (Package *pkg) { GSList *requires = NULL; GSList *conflicts = NULL; GSList *system_directories = NULL; GSList *iter; GSList *requires_iter; GSList *conflicts_iter; GSList *system_dir_iter = NULL; int count; gchar *c_include_path; /* 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->key); exit (1); } if (pkg->description == NULL) { verbose_error ("Package '%s' has no Description: field\n", pkg->key); exit (1); } /* Make sure we have the right version for all requirements */ iter = pkg->requires_private; 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); if (req->url) verbose_error ("You may find new versions of %s at %s\n", req->name, req->url); 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_private, &requires); conflicts = get_conflicts (pkg); 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->version : "(any)", 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); /* We make a list of system directories that gcc expects so we can remove * them. */ #ifndef G_OS_WIN32 system_directories = g_slist_append (NULL, g_strdup ("/usr/include")); #endif c_include_path = g_getenv ("C_INCLUDE_PATH"); if (c_include_path != NULL) { system_directories = add_env_variable_to_list (system_directories, c_include_path); } c_include_path = g_getenv ("CPLUS_INCLUDE_PATH"); if (c_include_path != NULL) { system_directories = add_env_variable_to_list (system_directories, c_include_path); } count = 0; iter = pkg->I_cflags; while (iter != NULL) { gint offset = 0; /* we put things in canonical -I/usr/include (vs. -I /usr/include) format, * but if someone changes it later we may as well be robust */ if (((strncmp (iter->data, "-I", 2) == 0) && (offset = 2))|| ((strncmp (iter->data, "-I ", 3) == 0) && (offset = 3))) { if (offset == 0) { iter = iter->next; continue; } system_dir_iter = system_directories; while (system_dir_iter != NULL) { if (strcmp (system_dir_iter->data, ((char*)iter->data) + offset) == 0) { debug_spew ("Package %s has %s in Cflags\n", pkg->name, (gchar *)iter->data); if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") == NULL) { debug_spew ("Removing %s from cflags for %s\n", iter->data, pkg->key); ++count; iter->data = NULL; break; } } system_dir_iter = system_dir_iter->next; } } iter = iter->next; } while (count) { pkg->I_cflags = g_slist_remove (pkg->I_cflags, NULL); --count; } g_slist_foreach (system_directories, (GFunc) g_free, NULL); g_slist_free (system_directories); #ifdef PREFER_LIB64 #define SYSTEM_LIBDIR "/usr/lib64" #else #define SYSTEM_LIBDIR "/usr/lib" #endif count = 0; iter = pkg->L_libs; while (iter != NULL) { if (strcmp (iter->data, "-L" SYSTEM_LIBDIR) == 0 || strcmp (iter->data, "-L " SYSTEM_LIBDIR) == 0) { debug_spew ("Package %s has -L" SYSTEM_LIBDIR " in Libs\n", pkg->name); if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_LIBS") == NULL) { iter->data = NULL; ++count; debug_spew ("Removing -L" SYSTEM_LIBDIR " from libs for %s\n", pkg->key); } } iter = iter->next; } #undef SYSTEM_LIBDIR while (count) { pkg->L_libs = g_slist_remove (pkg->L_libs, NULL); --count; } }
static Package * internal_get_package (const char *name, gboolean warn, gboolean check_compat) { 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 && !name_ends_in_uninstalled (name)) { char *un; un = g_strconcat (name, "-uninstalled", NULL); pkg = internal_get_package (un, FALSE, 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); } if (location == NULL && check_compat) { pkg = get_compat_package (name); if (pkg) { debug_spew ("Returning values for '%s' from a legacy -config script\n", name); return pkg; } } if (location == 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); return NULL; } debug_spew ("Reading '%s' from file '%s'\n", name, location); pkg = parse_package_file (location, ignore_requires, ignore_private_libs); 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); } pkg->path_position = GPOINTER_TO_INT (g_hash_table_lookup (path_positions, pkg->key)); debug_spew ("Path position of '%s' is %d\n", pkg->name, pkg->path_position); 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; }
static void parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean ignore_requires, gboolean ignore_private_libs, gboolean ignore_requires_private) { char *str; char *p; char *tag; debug_spew (" line>%s\n", untrimmed); str = trim_string (untrimmed); if (*str == '\0') /* empty line */ { g_free(str); return; } p = str; /* Get first word */ while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_' || *p == '.') p++; tag = g_strndup (str, p - str); while (*p && isspace ((guchar)*p)) ++p; if (*p == ':') { /* keyword */ ++p; while (*p && isspace ((guchar)*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.private") == 0) { if (!ignore_requires_private) parse_requires_private (pkg, p, path); } else if (strcmp (tag, "Requires") == 0) { if (ignore_requires == FALSE) parse_requires (pkg, p, path); else goto cleanup; } else if ((strcmp (tag, "Libs.private") == 0) && ignore_private_libs == FALSE) parse_libs_private (pkg, p, path); else if (strcmp (tag, "Libs") == 0) parse_libs (pkg, p, path); else if (strcmp (tag, "Cflags") == 0 || strcmp (tag, "CFlags") == 0) parse_cflags (pkg, p, path); else if (strcmp (tag, "Conflicts") == 0) parse_conflicts (pkg, p, path); else if (strcmp (tag, "URL") == 0) parse_url (pkg, p, path); else { /* we don't error out on unknown keywords because they may * represent additions to the .pc file format from future * versions of pkg-config. We do make a note of them in the * debug spew though, in order to help catch mistakes in .pc * files. */ debug_spew ("Unknown keyword '%s' in '%s'\n", tag, path); } } else if (*p == '=') { /* variable */ char *varname; char *varval; ++p; while (*p && isspace ((guchar)*p)) ++p; if (pkg->vars == NULL) pkg->vars = g_hash_table_new (g_str_hash, g_str_equal); #ifdef G_OS_WIN32 if (!dont_define_prefix && strcmp (tag, prefix_variable) == 0) { /* This is the prefix variable. Try to guesstimate a value for it * for this package from the location of the .pc file. */ gchar *prefix = pkg->pcfiledir; const int prefix_len = strlen (prefix); const char *const lib_pkgconfig = "\\lib\\pkgconfig"; const char *const share_pkgconfig = "\\share\\pkgconfig"; const int lib_pkgconfig_len = strlen (lib_pkgconfig); const int share_pkgconfig_len = strlen (share_pkgconfig); if ((strlen (prefix) > lib_pkgconfig_len && pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0) || (strlen (prefix) > share_pkgconfig_len && pathnamecmp (prefix + prefix_len - share_pkgconfig_len, share_pkgconfig) == 0)) { /* It ends in lib\pkgconfig or share\pkgconfig. Good. */ gchar *q; orig_prefix = g_strdup (p); prefix = g_strdup (prefix); if (strlen (prefix) > lib_pkgconfig_len && pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0) prefix[prefix_len - lib_pkgconfig_len] = '\0'; else prefix[prefix_len - share_pkgconfig_len] = '\0'; /* Turn backslashes into slashes or * poptParseArgvString() will eat them when ${prefix} * has been expanded in parse_libs(). */ q = prefix; while (*q) { if (*q == '\\') *q = '/'; q++; } varname = g_strdup (tag); debug_spew (" Variable declaration, '%s' overridden with '%s'\n", tag, prefix); g_hash_table_insert (pkg->vars, varname, prefix); goto cleanup; } } else if (!dont_define_prefix && orig_prefix != NULL && strncmp (p, orig_prefix, strlen (orig_prefix)) == 0 && G_IS_DIR_SEPARATOR (p[strlen (orig_prefix)])) { char *oldstr = str; p = str = g_strconcat (g_hash_table_lookup (pkg->vars, prefix_variable), p + strlen (orig_prefix), NULL); g_free (oldstr); } #endif 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); } cleanup: g_free (str); g_free (tag); }
int main (int argc, char **argv) { GString *str; GList *packages = NULL; char *search_path; char *pcbuilddir; gboolean need_newline; FILE *log = NULL; GError *error = NULL; GOptionContext *opt_context; /* 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; debug_spew ("PKG_CONFIG_DEBUG_SPEW variable enabling debug spew\n"); } /* Get the built-in search path */ init_pc_path (); if (pkg_config_pc_path == NULL) { /* Even when we override the built-in search path, we still use it later * to add pc_path to the virtual pkg-config package. */ verbose_error ("Failed to get default search path\n"); exit (1); } search_path = getenv ("PKG_CONFIG_PATH"); if (search_path) { add_search_dirs(search_path, G_SEARCHPATH_SEPARATOR_S); } if (getenv("PKG_CONFIG_LIBDIR") != NULL) { add_search_dirs(getenv("PKG_CONFIG_LIBDIR"), G_SEARCHPATH_SEPARATOR_S); } else { add_search_dirs(pkg_config_pc_path, G_SEARCHPATH_SEPARATOR_S); } pcsysrootdir = getenv ("PKG_CONFIG_SYSROOT_DIR"); if (pcsysrootdir) { define_global_variable ("pc_sysrootdir", pcsysrootdir); } else { define_global_variable ("pc_sysrootdir", "/"); } 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; } /* Parse options */ opt_context = g_option_context_new (NULL); g_option_context_add_main_entries (opt_context, options_table, NULL); if (!g_option_context_parse(opt_context, &argc, &argv, &error)) { fprintf (stderr, "%s\n", error->message); return 1; } /* If no output option was set, then --exists is the default. */ if (!output_opt_set) { debug_spew ("no output option set, defaulting to --exists\n"); want_exists = TRUE; } /* Error printing is determined as follows: * - for --exists, --*-version, --list-all and no options at all, * it's off by default and --print-errors will turn it on * - for all other output options, it's on by default and * --silence-errors can turn it off */ if (want_exists || want_list) { debug_spew ("Error printing disabled by default due to use of output " "options --exists, --atleast/exact/max-version, " "--list-all or no output option at all. Value of " "--print-errors: %d\n", want_verbose_errors); /* Leave want_verbose_errors unchanged, reflecting --print-errors */ } else { debug_spew ("Error printing enabled by default due to use of output " "options besides --exists, --atleast/exact/max-version or " "--list-all. Value of --silence-errors: %d\n", want_silence_errors); if (want_silence_errors && getenv ("PKG_CONFIG_DEBUG_SPEW") == NULL) want_verbose_errors = FALSE; else want_verbose_errors = TRUE; } if (want_verbose_errors) debug_spew ("Error printing enabled\n"); else debug_spew ("Error printing disabled\n"); if (want_static_lib_list) enable_private_libs(); else disable_private_libs(); /* honor Requires.private if any Cflags are requested or any static * libs are requested */ if (pkg_flags & CFLAGS_ANY || want_requires_private || want_exists || (want_static_lib_list && (pkg_flags & LIBS_ANY))) enable_requires_private(); /* ignore Requires if no Cflags or Libs are requested */ 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); 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; } /* Collect packages from remaining args */ str = g_string_new (""); while (argc > 1) { argc--; argv++; g_string_append (str, *argv); g_string_append (str, " "); } g_option_context_free (opt_context); g_strstrip (str->str); if (getenv("PKG_CONFIG_LOG") != NULL) { log = fopen (getenv ("PKG_CONFIG_LOG"), "a"); if (log == NULL) { fprintf (stderr, "Cannot open log file: %s\n", getenv ("PKG_CONFIG_LOG")); exit (1); } } /* find and parse each of the packages specified */ if (!process_package_args (str->str, &packages, log)) return 1; if (log != NULL) fclose (log); g_string_free (str, TRUE); if (want_exists) return 0; /* if we got here, all the packages existed. */ if (want_variable_list) { GList *tmp; tmp = packages; while (tmp != NULL) { Package *pkg = tmp->data; if (pkg->vars != NULL) g_hash_table_foreach(pkg->vars, &print_hashtable_key, NULL); tmp = g_list_next (tmp); if (tmp) printf ("\n"); } need_newline = FALSE; } if (want_uninstalled) { /* See if > 0 pkgs (including dependencies recursively) were uninstalled */ GList *tmp; tmp = packages; while (tmp != NULL) { Package *pkg = tmp->data; if (pkg_uninstalled (pkg)) return 0; tmp = g_list_next (tmp); } return 1; } if (want_version) { GList *tmp; tmp = packages; while (tmp != NULL) { Package *pkg = tmp->data; printf ("%s\n", pkg->version); tmp = g_list_next (tmp); } } if (want_provides) { GList *tmp; tmp = packages; while (tmp != NULL) { Package *pkg = tmp->data; char *key; key = pkg->key; while (*key == '/') key++; if (strlen(key) > 0) printf ("%s = %s\n", key, pkg->version); tmp = g_list_next (tmp); } } if (want_requires) { GList *pkgtmp; for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp)) { Package *pkg = pkgtmp->data; GList *reqtmp; /* process Requires: */ for (reqtmp = pkg->requires; reqtmp != NULL; reqtmp = g_list_next (reqtmp)) { Package *deppkg = reqtmp->data; RequiredVersion *req; req = g_hash_table_lookup(pkg->required_versions, deppkg->key); if ((req == NULL) || (req->comparison == ALWAYS_MATCH)) printf ("%s\n", deppkg->key); else printf ("%s %s %s\n", deppkg->key, comparison_to_str(req->comparison), req->version); } } } if (want_requires_private) { GList *pkgtmp; for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp)) { Package *pkg = pkgtmp->data; GList *reqtmp; /* process Requires.private: */ for (reqtmp = pkg->requires_private; reqtmp != NULL; reqtmp = g_list_next (reqtmp)) { Package *deppkg = reqtmp->data; RequiredVersion *req; if (g_list_find (pkg->requires, reqtmp->data)) continue; req = g_hash_table_lookup(pkg->required_versions, deppkg->key); if ((req == NULL) || (req->comparison == ALWAYS_MATCH)) printf ("%s\n", deppkg->key); else printf ("%s %s %s\n", deppkg->key, comparison_to_str(req->comparison), req->version); } } } /* 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 (pkg_flags != 0) { char *str = packages_get_flags (packages, pkg_flags); printf ("%s", str); g_free (str); need_newline = TRUE; } if (need_newline) printf ("\n"); return 0; }
static void parse_cflags (Package *pkg, const char *str, const char *path) { /* Strip out -I flags, put them in a separate list. */ char *trimmed; char **argv = NULL; int argc = 0; 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); if (trimmed && *trimmed) { 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); } } i = 0; while (i < argc) { char *tmp = trim_string (argv[i]); char *arg = strdup_escape_shell(tmp); char *p = arg; g_free(tmp); if (p[0] == '-' && p[1] == 'I') { p += 2; while (*p && isspace ((guchar)*p)) ++p; pkg->I_cflags = g_slist_prepend (pkg->I_cflags, g_strconcat ("-I", p, NULL)); } else { if (*arg != '\0') pkg->other_cflags = g_slist_prepend (pkg->other_cflags, g_strdup (arg)); if (strcmp("-idirafter", arg) == 0) { char *n; tmp = trim_string(argv[++i]); n = strdup_escape_shell(tmp); pkg->other_cflags = g_slist_prepend(pkg->other_cflags, n); g_free(tmp); } } g_free (arg); ++i; } g_free (argv); g_free (trimmed); }
Package* parse_package_file (const char *path, gboolean ignore_requires, gboolean ignore_private_libs, gboolean ignore_requires_private) { 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, ignore_requires, ignore_private_libs, ignore_requires_private); g_string_truncate (str, 0); } if (!one_line) verbose_error ("Package file '%s' appears to be empty\n", path); g_string_free (str, TRUE); fclose(f); /* make ->requires_private include a copy of the public requires too */ pkg->requires_private = g_slist_concat(g_slist_copy (pkg->requires), pkg->requires_private); pkg->requires = g_slist_reverse (pkg->requires); pkg->requires_private = g_slist_reverse (pkg->requires_private); pkg->I_cflags = g_slist_reverse (pkg->I_cflags); pkg->other_cflags = g_slist_reverse (pkg->other_cflags); pkg->l_libs = g_slist_reverse (pkg->l_libs); pkg->L_libs = g_slist_reverse (pkg->L_libs); pkg->other_libs = g_slist_reverse (pkg->other_libs); return pkg; }
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_other_libs = 0; static int want_I_cflags = 0; static int want_other_cflags = 0; static int want_list = 0; static int want_static_lib_list = ENABLE_INDIRECT_DEPS; static int want_short_errors = 0; static int want_uninstalled = 0; static char *variable_name = NULL; static int want_exists = 0; static int want_provides = 0; static int want_requires = 0; static int want_requires_private = 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; static int want_variable_list = 0; GString *str; GSList *packages = NULL; char *search_path; char *pcbuilddir; gboolean need_newline; FILE *log = NULL; GError *error = NULL; GOptionContext *opt_context; GOptionEntry options_table[] = { { "version", 0, 0, G_OPTION_ARG_NONE, &want_my_version, "output version of pkg-config", NULL }, { "modversion", 0, 0, G_OPTION_ARG_NONE, &want_version, "output version for package", NULL }, { "atleast-pkgconfig-version", 0, 0, G_OPTION_ARG_STRING, &required_pkgconfig_version, "require given version of pkg-config", "VERSION" }, { "libs", 0, 0, G_OPTION_ARG_NONE, &want_libs, "output all linker flags", NULL }, { "static", 0, 0, G_OPTION_ARG_NONE, &want_static_lib_list, "output linker flags for static linking", NULL }, { "short-errors", 0, 0, G_OPTION_ARG_NONE, &want_short_errors, "print short errors", NULL }, { "libs-only-l", 0, 0, G_OPTION_ARG_NONE, &want_l_libs, "output -l flags", NULL }, { "libs-only-other", 0, 0, G_OPTION_ARG_NONE, &want_other_libs, "output other libs (e.g. -pthread)", NULL }, { "libs-only-L", 0, 0, G_OPTION_ARG_NONE, &want_L_libs, "output -L flags", NULL }, { "cflags", 0, 0, G_OPTION_ARG_NONE, &want_cflags, "output all pre-processor and compiler flags", NULL }, { "cflags-only-I", 0, 0, G_OPTION_ARG_NONE, &want_I_cflags, "output -I flags", NULL }, { "cflags-only-other", 0, 0, G_OPTION_ARG_NONE, &want_other_cflags, "output cflags not covered by the cflags-only-I option", NULL }, { "variable", 0, 0, G_OPTION_ARG_STRING, &variable_name, "get the value of variable named NAME", "NAME" }, { "define-variable", 0, 0, G_OPTION_ARG_CALLBACK, &define_variable_cb, "set variable NAME to VALUE", "NAME=VALUE" }, { "exists", 0, 0, G_OPTION_ARG_NONE, &want_exists, "return 0 if the module(s) exist", NULL }, { "print-variables", 0, 0, G_OPTION_ARG_NONE, &want_variable_list, "output list of variables defined by the module", NULL }, { "uninstalled", 0, 0, G_OPTION_ARG_NONE, &want_uninstalled, "return 0 if the uninstalled version of one or more module(s) " "or their dependencies will be used", NULL }, { "atleast-version", 0, 0, G_OPTION_ARG_STRING, &required_atleast_version, "return 0 if the module is at least version VERSION", "VERSION" }, { "exact-version", 0, 0, G_OPTION_ARG_STRING, &required_exact_version, "return 0 if the module is at exactly version VERSION", "VERSION" }, { "max-version", 0, 0, G_OPTION_ARG_STRING, &required_max_version, "return 0 if the module is at no newer than version VERSION", "VERSION" }, { "list-all", 0, 0, G_OPTION_ARG_NONE, &want_list, "list all known packages", NULL }, { "debug", 0, 0, G_OPTION_ARG_NONE, &want_debug_spew, "show verbose debug information", NULL }, { "print-errors", 0, 0, G_OPTION_ARG_NONE, &want_verbose_errors, "show verbose information about missing or conflicting packages," "default if --cflags or --libs given on the command line", NULL }, { "silence-errors", 0, 0, G_OPTION_ARG_NONE, &want_silence_errors, "be silent about errors (default unless --cflags or --libs" "given on the command line)", NULL }, { "errors-to-stdout", 0, 0, G_OPTION_ARG_NONE, &want_stdout_errors, "print errors from --print-errors to stdout not stderr", NULL }, { "print-provides", 0, 0, G_OPTION_ARG_NONE, &want_provides, "print which packages the package provides", NULL }, { "print-requires", 0, 0, G_OPTION_ARG_NONE, &want_requires, "print which packages the package requires", NULL }, { "print-requires-private", 0, 0, G_OPTION_ARG_NONE, &want_requires_private, "print which packages the package requires for static linking", NULL }, #ifdef G_OS_WIN32 { "dont-define-prefix", 0, 0, G_OPTION_ARG_NONE, &dont_define_prefix, "don't try to override the value of prefix for each .pc file found with " "a guesstimated value based on the location of the .pc file", NULL }, { "prefix-variable", 0, 0, G_OPTION_ARG_STRING, &prefix_variable, "set the name of the variable that pkg-config automatically sets", "PREFIX" }, { "msvc-syntax", 0, 0, G_OPTION_ARG_NONE, &msvc_syntax, "output -l and -L flags for the Microsoft compiler (cl)", NULL }, #endif { NULL, 0, 0, 0, NULL, NULL, NULL } }; /* 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; debug_spew ("PKG_CONFIG_DEBUG_SPEW variable enabling debug spew\n"); } /* Get the built-in search path */ init_pc_path (); if (pkg_config_pc_path == NULL) { /* Even when we override the built-in search path, we still use it later * to add pc_path to the virtual pkg-config package. */ verbose_error ("Failed to get default search path\n"); exit (1); } search_path = getenv ("PKG_CONFIG_PATH"); if (search_path) { add_search_dirs(search_path, G_SEARCHPATH_SEPARATOR_S); } if (getenv("PKG_CONFIG_LIBDIR") != NULL) { add_search_dirs(getenv("PKG_CONFIG_LIBDIR"), G_SEARCHPATH_SEPARATOR_S); } else { add_search_dirs(pkg_config_pc_path, G_SEARCHPATH_SEPARATOR_S); } pcsysrootdir = getenv ("PKG_CONFIG_SYSROOT_DIR"); if (pcsysrootdir) { define_global_variable ("pc_sysrootdir", pcsysrootdir); } else { define_global_variable ("pc_sysrootdir", "/"); } 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; } /* Parse options */ opt_context = g_option_context_new (NULL); g_option_context_add_main_entries (opt_context, options_table, NULL); if (!g_option_context_parse(opt_context, &argc, &argv, &error)) { fprintf (stderr, "%s\n", error->message); 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_other_libs || want_I_cflags || want_other_cflags || want_list || want_variable_list) { debug_spew ("Error printing enabled by default due to use of --version, --libs, --cflags, --libs-only-l, --libs-only-L, --libs-only-other, --cflags-only-I, --cflags-only-other or --list. Value of --silence-errors: %d\n", want_silence_errors); if (want_silence_errors && getenv ("PKG_CONFIG_DEBUG_SPEW") == NULL) want_verbose_errors = FALSE; else want_verbose_errors = TRUE; } else { debug_spew ("Error printing disabled by default, value of --print-errors: %d\n", want_verbose_errors); /* Leave want_verbose_errors unchanged, reflecting --print-errors */ } if (want_verbose_errors) debug_spew ("Error printing enabled\n"); else debug_spew ("Error printing disabled\n"); if (want_static_lib_list) enable_private_libs(); else disable_private_libs(); /* honor Requires.private if any Cflags are requested or any static * libs are requested */ if (want_I_cflags || want_other_cflags || want_cflags || want_requires_private || want_exists || (want_static_lib_list && (want_libs || want_l_libs || want_L_libs))) enable_requires_private(); /* ignore Requires if no Cflags or Libs are requested */ if (!want_I_cflags && !want_other_cflags && !want_cflags && !want_libs && !want_l_libs && !want_L_libs && !want_requires && !want_exists) disable_requires(); 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; } /* Collect packages from remaining args */ str = g_string_new (""); while (argc > 1) { argc--; argv++; g_string_append (str, *argv); g_string_append (str, " "); } g_option_context_free (opt_context); g_strstrip (str->str); if (getenv("PKG_CONFIG_LOG") != NULL) { log = fopen (getenv ("PKG_CONFIG_LOG"), "a"); if (log == NULL) { fprintf (stderr, "Cannot open log file: %s\n", getenv ("PKG_CONFIG_LOG")); exit (1); } } { gboolean failed = FALSE; 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; /* override requested versions with cmdline options */ if (required_exact_version) { g_free (ver->version); ver->comparison = EQUAL; ver->version = g_strdup (required_exact_version); } else if (required_atleast_version) { g_free (ver->version); ver->comparison = GREATER_THAN_EQUAL; ver->version = g_strdup (required_atleast_version); } else if (required_max_version) { g_free (ver->version); ver->comparison = LESS_THAN_EQUAL; ver->version = g_strdup (required_max_version); } if (want_short_errors) req = get_package_quiet (ver->name); else req = get_package (ver->name); if (log != NULL) { if (req == NULL) fprintf (log, "%s NOT-FOUND", ver->name); else fprintf (log, "%s %s %s", ver->name, comparison_to_str (ver->comparison), (ver->version == NULL) ? "(null)" : ver->version); fprintf (log, "\n"); } if (req == NULL) { failed = TRUE; verbose_error ("No package '%s' found\n", ver->name); goto nextiter; } if (!version_test (ver->comparison, req->version, ver->version)) { failed = TRUE; 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); if (req->url) verbose_error ("You may find new versions of %s at %s\n", req->name, req->url); goto nextiter; } packages = g_slist_prepend (packages, req); nextiter: iter = g_slist_next (iter); } if (log != NULL) { fclose (log); } if (failed) { return 1; } if (want_variable_list) { GSList *tmp; tmp = packages; while (tmp != NULL) { Package *pkg = tmp->data; g_hash_table_foreach(pkg->vars, &print_hashtable_key, NULL); tmp = g_slist_next (tmp); if (tmp) printf ("\n"); } need_newline = FALSE; } } 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 (want_provides) { GSList *tmp; tmp = packages; while (tmp != NULL) { Package *pkg = tmp->data; char *key; key = pkg->key; while (*key == '/') key++; if (strlen(key) > 0) printf ("%s = %s\n", key, pkg->version); tmp = g_slist_next (tmp); } } if (want_requires) { GSList *pkgtmp; for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_slist_next (pkgtmp)) { Package *pkg = pkgtmp->data; GSList *reqtmp; /* process Requires: */ for (reqtmp = pkg->requires; reqtmp != NULL; reqtmp = g_slist_next (reqtmp)) { Package *deppkg = reqtmp->data; RequiredVersion *req; req = g_hash_table_lookup(pkg->required_versions, deppkg->key); if ((req == NULL) || (req->comparison == ALWAYS_MATCH)) printf ("%s\n", deppkg->key); else printf ("%s %s %s\n", deppkg->key, comparison_to_str(req->comparison), req->version); } } } if (want_requires_private) { GSList *pkgtmp; for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_slist_next (pkgtmp)) { Package *pkg = pkgtmp->data; GSList *reqtmp; /* process Requires.private: */ for (reqtmp = pkg->requires_private; reqtmp != NULL; reqtmp = g_slist_next (reqtmp)) { Package *deppkg = reqtmp->data; RequiredVersion *req; if (g_slist_find (pkg->requires, reqtmp->data)) continue; req = g_hash_table_lookup(pkg->required_versions, deppkg->key); if ((req == NULL) || (req->comparison == ALWAYS_MATCH)) printf ("%s\n", deppkg->key); else printf ("%s %s %s\n", deppkg->key, comparison_to_str(req->comparison), req->version); } } } /* 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_other_cflags) { char *str = packages_get_other_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_other_libs) { char *str = packages_get_other_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; }
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); g_free (varval); } else { g_string_append_c (subst, *p); ++p; } } g_free (trimmed); p = subst->str; g_string_free (subst, FALSE); return p; }
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 ((guchar)*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 ((guchar)*p)) ++p; while (*p && isspace ((guchar)*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; }