"Fossies" - the Fresh Open Source Software Archive

Member "pkg-config-0.29.2/pkg.c" (20 Mar 2017, 30963 Bytes) of package /linux/misc/pkg-config-0.29.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pkg.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.29.1_vs_0.29.2.

    1 /* 
    2  * Copyright (C) 2001, 2002 Red Hat Inc.
    3  * 
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License as
    6  * published by the Free Software Foundation; either version 2 of the
    7  * License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful, but
   10  * WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12  * General Public License for more details.
   13  * 
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   17  * 02111-1307, USA.
   18  */
   19 
   20 
   21 #ifdef HAVE_CONFIG_H
   22 #include "config.h"
   23 #endif
   24 
   25 #include "pkg.h"
   26 #include "parse.h"
   27 #include "rpmvercmp.h"
   28 
   29 #ifdef HAVE_MALLOC_H
   30 # include <malloc.h>
   31 #endif
   32 
   33 #include <sys/types.h>
   34 #include <string.h>
   35 #include <errno.h>
   36 #include <stdio.h>
   37 #ifdef HAVE_UNISTD_H
   38 #include <unistd.h>
   39 #endif
   40 #include <stdlib.h>
   41 #include <ctype.h>
   42 
   43 static void verify_package (Package *pkg);
   44 
   45 static GHashTable *packages = NULL;
   46 static GHashTable *globals = NULL;
   47 static GList *search_dirs = NULL;
   48 
   49 gboolean disable_uninstalled = FALSE;
   50 gboolean ignore_requires = FALSE;
   51 gboolean ignore_requires_private = TRUE;
   52 gboolean ignore_private_libs = TRUE;
   53 
   54 void
   55 add_search_dir (const char *path)
   56 {
   57   search_dirs = g_list_append (search_dirs, g_strdup (path));
   58 }
   59 
   60 void
   61 add_search_dirs (const char *path, const char *separator)
   62 {
   63       char **search_dirs;
   64       char **iter;
   65 
   66       search_dirs = g_strsplit (path, separator, -1);
   67     
   68       iter = search_dirs;
   69       while (*iter)
   70         {
   71           debug_spew ("Adding directory '%s' from PKG_CONFIG_PATH\n",
   72                       *iter);
   73           add_search_dir (*iter);
   74           
   75           ++iter;
   76         }
   77       
   78       g_strfreev (search_dirs);
   79 }
   80 
   81 #ifdef G_OS_WIN32
   82 /* Guard against .pc file being installed with UPPER CASE name */
   83 # define FOLD(x) tolower(x)
   84 # define FOLDCMP(a, b) g_ascii_strcasecmp (a, b)
   85 #else
   86 # define FOLD(x) (x)
   87 # define FOLDCMP(a, b) strcmp (a, b)
   88 #endif
   89 
   90 #define EXT_LEN 3
   91 
   92 static gboolean
   93 ends_in_dotpc (const char *str)
   94 {
   95   int len = strlen (str);
   96   
   97   if (len > EXT_LEN &&
   98       str[len - 3] == '.' &&
   99       FOLD (str[len - 2]) == 'p' &&
  100       FOLD (str[len - 1]) == 'c')
  101     return TRUE;
  102   else
  103     return FALSE;
  104 }
  105 
  106 /* strlen ("-uninstalled") */
  107 #define UNINSTALLED_LEN 12
  108 
  109 gboolean
  110 name_ends_in_uninstalled (const char *str)
  111 {
  112   int len = strlen (str);
  113   
  114   if (len > UNINSTALLED_LEN &&
  115       FOLDCMP ((str + len - UNINSTALLED_LEN), "-uninstalled") == 0)
  116     return TRUE;
  117   else
  118     return FALSE;
  119 }
  120 
  121 static Package *
  122 internal_get_package (const char *name, gboolean warn);
  123 
  124 /* Look for .pc files in the given directory and add them into
  125  * locations, ignoring duplicates
  126  */
  127 static void
  128 scan_dir (char *dirname)
  129 {
  130   GDir *dir;
  131   const gchar *filename;
  132 
  133   int dirnamelen = strlen (dirname);
  134   /* Use a copy of dirname cause Win32 opendir doesn't like
  135    * superfluous trailing (back)slashes in the directory name.
  136    */
  137   char *dirname_copy = g_strdup (dirname);
  138 
  139   if (dirnamelen > 1 && dirname[dirnamelen-1] == G_DIR_SEPARATOR)
  140     {
  141       dirnamelen--;
  142       dirname_copy[dirnamelen] = '\0';
  143     }
  144 #ifdef G_OS_WIN32
  145     {
  146       gchar *p;
  147       /* Turn backslashes into slashes or
  148        * g_shell_parse_argv() will eat them when ${prefix}
  149        * has been expanded in parse_libs().
  150        */
  151       p = dirname;
  152       while (*p)
  153         {
  154           if (*p == '\\')
  155             *p = '/';
  156           p++;
  157         }
  158     }
  159 #endif
  160   dir = g_dir_open (dirname_copy, 0 , NULL);
  161   g_free (dirname_copy);
  162 
  163   if (!dir)
  164     {
  165       debug_spew ("Cannot open directory '%s' in package search path: %s\n",
  166                   dirname, g_strerror (errno));
  167       return;
  168     }
  169 
  170   debug_spew ("Scanning directory '%s'\n", dirname);
  171 
  172   while ((filename = g_dir_read_name(dir)))
  173     {
  174       char *path = g_build_filename (dirname, filename, NULL);
  175       internal_get_package (path, FALSE);
  176       g_free (path);
  177     }
  178   g_dir_close (dir);
  179 }
  180 
  181 static Package *
  182 add_virtual_pkgconfig_package (void)
  183 {
  184   Package *pkg = NULL;
  185 
  186   pkg = g_new0 (Package, 1);
  187 
  188   pkg->key = g_strdup ("pkg-config");
  189   pkg->version = g_strdup (VERSION);
  190   pkg->name = g_strdup ("pkg-config");
  191   pkg->description = g_strdup ("pkg-config is a system for managing "
  192                    "compile/link flags for libraries");
  193   pkg->url = g_strdup ("http://pkg-config.freedesktop.org/");
  194 
  195   if (pkg->vars == NULL)
  196     pkg->vars = g_hash_table_new (g_str_hash, g_str_equal);
  197   g_hash_table_insert (pkg->vars, "pc_path", pkg_config_pc_path);
  198 
  199   debug_spew ("Adding virtual 'pkg-config' package to list of known packages\n");
  200   g_hash_table_insert (packages, pkg->key, pkg);
  201 
  202   return pkg;
  203 }
  204 
  205 void
  206 package_init (gboolean want_list)
  207 {
  208   if (packages)
  209     return;
  210       
  211   packages = g_hash_table_new (g_str_hash, g_str_equal);
  212 
  213   if (want_list)
  214     g_list_foreach (search_dirs, (GFunc)scan_dir, NULL);
  215   else
  216     /* Should not add virtual pkgconfig package when listing to be
  217      * compatible with old code that only listed packages from real
  218      * files */
  219     add_virtual_pkgconfig_package ();
  220 }
  221 
  222 static Package *
  223 internal_get_package (const char *name, gboolean warn)
  224 {
  225   Package *pkg = NULL;
  226   char *key = NULL;
  227   char *location = NULL;
  228   unsigned int path_position = 0;
  229   GList *iter;
  230   GList *dir_iter;
  231   
  232   pkg = g_hash_table_lookup (packages, name);
  233 
  234   if (pkg)
  235     return pkg;
  236 
  237   debug_spew ("Looking for package '%s'\n", name);
  238   
  239   /* treat "name" as a filename if it ends in .pc and exists */
  240   if ( ends_in_dotpc (name) )
  241     {
  242       debug_spew ("Considering '%s' to be a filename rather than a package name\n", name);
  243       location = g_strdup (name);
  244       key = g_strdup (name);
  245     }
  246   else
  247     {
  248       /* See if we should auto-prefer the uninstalled version */
  249       if (!disable_uninstalled &&
  250           !name_ends_in_uninstalled (name))
  251         {
  252           char *un;
  253 
  254           un = g_strconcat (name, "-uninstalled", NULL);
  255 
  256           pkg = internal_get_package (un, FALSE);
  257 
  258           g_free (un);
  259           
  260           if (pkg)
  261             {
  262               debug_spew ("Preferring uninstalled version of package '%s'\n", name);
  263               return pkg;
  264             }
  265         }
  266       
  267       for (dir_iter = search_dirs; dir_iter != NULL;
  268            dir_iter = g_list_next (dir_iter))
  269         {
  270           path_position++;
  271           location = g_strdup_printf ("%s%c%s.pc", (char*)dir_iter->data,
  272                                       G_DIR_SEPARATOR, name);
  273           if (g_file_test (location, G_FILE_TEST_IS_REGULAR))
  274             break;
  275           g_free (location);
  276           location = NULL;
  277         }
  278 
  279     }
  280   
  281   if (location == NULL)
  282     {
  283       if (warn)
  284         verbose_error ("Package %s was not found in the pkg-config search path.\n"
  285                        "Perhaps you should add the directory containing `%s.pc'\n"
  286                        "to the PKG_CONFIG_PATH environment variable\n",
  287                        name, name);
  288 
  289       return NULL;
  290     }
  291 
  292   if (key == NULL)
  293     key = g_strdup (name);
  294   else
  295     {
  296       /* need to strip package name out of the filename */
  297       key = g_path_get_basename (name);
  298       key[strlen (key) - EXT_LEN] = '\0';
  299     }
  300 
  301   debug_spew ("Reading '%s' from file '%s'\n", name, location);
  302   pkg = parse_package_file (key, location, ignore_requires,
  303                             ignore_private_libs, ignore_requires_private);
  304   g_free (key);
  305 
  306   if (pkg != NULL && strstr (location, "uninstalled.pc"))
  307     pkg->uninstalled = TRUE;
  308 
  309   g_free (location);
  310 
  311   if (pkg == NULL)
  312     {
  313       debug_spew ("Failed to parse '%s'\n", location);
  314       return NULL;
  315     }
  316 
  317   pkg->path_position = path_position;
  318 
  319   debug_spew ("Path position of '%s' is %d\n",
  320               pkg->key, pkg->path_position);
  321   
  322   debug_spew ("Adding '%s' to list of known packages\n", pkg->key);
  323   g_hash_table_insert (packages, pkg->key, pkg);
  324 
  325   /* pull in Requires packages */
  326   for (iter = pkg->requires_entries; iter != NULL; iter = g_list_next (iter))
  327     {
  328       Package *req;
  329       RequiredVersion *ver = iter->data;
  330 
  331       debug_spew ("Searching for '%s' requirement '%s'\n",
  332                   pkg->key, ver->name);
  333       req = internal_get_package (ver->name, warn);
  334       if (req == NULL)
  335         {
  336           verbose_error ("Package '%s', required by '%s', not found\n",
  337                          ver->name, pkg->key);
  338           exit (1);
  339         }
  340 
  341       if (pkg->required_versions == NULL)
  342         pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal);
  343 
  344       g_hash_table_insert (pkg->required_versions, ver->name, ver);
  345       pkg->requires = g_list_prepend (pkg->requires, req);
  346     }
  347 
  348   /* pull in Requires.private packages */
  349   for (iter = pkg->requires_private_entries; iter != NULL;
  350        iter = g_list_next (iter))
  351     {
  352       Package *req;
  353       RequiredVersion *ver = iter->data;
  354 
  355       debug_spew ("Searching for '%s' private requirement '%s'\n",
  356                   pkg->key, ver->name);
  357       req = internal_get_package (ver->name, warn);
  358       if (req == NULL)
  359         {
  360           verbose_error ("Package '%s', required by '%s', not found\n",
  361              ver->name, pkg->key);
  362           exit (1);
  363         }
  364 
  365       if (pkg->required_versions == NULL)
  366         pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal);
  367 
  368       g_hash_table_insert (pkg->required_versions, ver->name, ver);
  369       pkg->requires_private = g_list_prepend (pkg->requires_private, req);
  370     }
  371 
  372   /* make requires_private include a copy of the public requires too */
  373   pkg->requires_private = g_list_concat (g_list_copy (pkg->requires),
  374                                          pkg->requires_private);
  375 
  376   pkg->requires = g_list_reverse (pkg->requires);
  377   pkg->requires_private = g_list_reverse (pkg->requires_private);
  378 
  379   verify_package (pkg);
  380 
  381   return pkg;
  382 }
  383 
  384 Package *
  385 get_package (const char *name)
  386 {
  387   return internal_get_package (name, TRUE);
  388 }
  389 
  390 Package *
  391 get_package_quiet (const char *name)
  392 {
  393   return internal_get_package (name, FALSE);
  394 }
  395 
  396 /* Strip consecutive duplicate arguments in the flag list. */
  397 static GList *
  398 flag_list_strip_duplicates (GList *list)
  399 {
  400   GList *tmp;
  401 
  402   /* Start at the 2nd element of the list so we don't have to check for an
  403    * existing previous element. */
  404   for (tmp = g_list_next (list); tmp != NULL; tmp = g_list_next (tmp))
  405     {
  406       Flag *cur = tmp->data;
  407       Flag *prev = tmp->prev->data;
  408 
  409       if (cur->type == prev->type && g_strcmp0 (cur->arg, prev->arg) == 0)
  410         {
  411           /* Remove the duplicate flag from the list and move to the last
  412            * element to prepare for the next iteration. */
  413           GList *dup = tmp;
  414 
  415           debug_spew (" removing duplicate \"%s\"\n", cur->arg);
  416           tmp = g_list_previous (tmp);
  417           list = g_list_remove_link (list, dup);
  418         }
  419     }
  420 
  421   return list;
  422 }
  423 
  424 static char *
  425 flag_list_to_string (GList *list)
  426 {
  427   GList *tmp;
  428   GString *str = g_string_new ("");
  429   char *retval;
  430   
  431   tmp = list;
  432   while (tmp != NULL) {
  433     Flag *flag = tmp->data;
  434     char *tmpstr = flag->arg;
  435 
  436     if (pcsysrootdir != NULL && flag->type & (CFLAGS_I | LIBS_L)) {
  437       /* Handle non-I Cflags like -isystem */
  438       if (flag->type & CFLAGS_I && strncmp (tmpstr, "-I", 2) != 0) {
  439         char *space = strchr (tmpstr, ' ');
  440 
  441         /* Ensure this has a separate arg */
  442         g_assert (space != NULL && space[1] != '\0');
  443         g_string_append_len (str, tmpstr, space - tmpstr + 1);
  444         g_string_append (str, pcsysrootdir);
  445         g_string_append (str, space + 1);
  446       } else {
  447         g_string_append_c (str, '-');
  448         g_string_append_c (str, tmpstr[1]);
  449         g_string_append (str, pcsysrootdir);
  450         g_string_append (str, tmpstr+2);
  451       }
  452     } else {
  453       g_string_append (str, tmpstr);
  454     }
  455     g_string_append_c (str, ' ');
  456     tmp = g_list_next (tmp);
  457   }
  458 
  459   retval = str->str;
  460   g_string_free (str, FALSE);
  461 
  462   return retval;
  463 }
  464 
  465 static int
  466 pathposcmp (gconstpointer a, gconstpointer b)
  467 {
  468   const Package *pa = a;
  469   const Package *pb = b;
  470   
  471   if (pa->path_position < pb->path_position)
  472     return -1;
  473   else if (pa->path_position > pb->path_position)
  474     return 1;
  475   else
  476     return 0;
  477 }
  478 
  479 static void
  480 spew_package_list (const char *name,
  481                    GList     *list)
  482 {
  483   GList *tmp;
  484 
  485   debug_spew (" %s:", name);
  486 
  487   tmp = list;
  488   while (tmp != NULL)
  489     {
  490       Package *pkg = tmp->data;
  491       debug_spew (" %s", pkg->key);
  492       tmp = tmp->next;
  493     }
  494   debug_spew ("\n");
  495 }
  496 
  497 
  498 static GList *
  499 packages_sort_by_path_position (GList *list)
  500 {
  501   return g_list_sort (list, pathposcmp);
  502 }
  503 
  504 /* Construct a topological sort of all required packages.
  505  *
  506  * This is a depth first search starting from the right.  The output 'listp' is
  507  * in reverse order, with the first node reached in the depth first search at
  508  * the end of the list.  Previously visited nodes are skipped.  The result is
  509  * a list of packages such that each packages is listed once and comes before
  510  * any package that it depends on.
  511  */
  512 static void
  513 recursive_fill_list (Package *pkg, gboolean include_private,
  514                      GHashTable *visited, GList **listp)
  515 {
  516   GList *tmp;
  517 
  518   /*
  519    * If the package has already been visited, then it is already in 'listp' and
  520    * we can skip it. Additionally, this allows circular requires loops to be
  521    * broken.
  522    */
  523   if (g_hash_table_lookup_extended (visited, pkg->key, NULL, NULL))
  524     {
  525       debug_spew ("Package %s already in requires chain, skipping\n",
  526                   pkg->key);
  527       return;
  528     }
  529   /* record this package in the dependency chain */
  530   else
  531     {
  532       g_hash_table_replace (visited, pkg->key, pkg->key);
  533     }
  534 
  535   /* Start from the end of the required package list to maintain order since
  536    * the recursive list is built by prepending. */
  537   tmp = include_private ? pkg->requires_private : pkg->requires;
  538   for (tmp = g_list_last (tmp); tmp != NULL; tmp = g_list_previous (tmp))
  539     recursive_fill_list (tmp->data, include_private, visited, listp);
  540 
  541   *listp = g_list_prepend (*listp, pkg);
  542 }
  543 
  544 /* merge the flags from the individual packages */
  545 static GList *
  546 merge_flag_lists (GList *packages, FlagType type)
  547 {
  548   GList *last = NULL;
  549   GList *merged = NULL;
  550 
  551   /* keep track of the last element to avoid traversing the whole list */
  552   for (; packages != NULL; packages = g_list_next (packages))
  553     {
  554       Package *pkg = packages->data;
  555       GList *flags = (type & LIBS_ANY) ? pkg->libs : pkg->cflags;
  556 
  557       /* manually copy the elements so we can keep track of the end */
  558       for (; flags != NULL; flags = g_list_next (flags))
  559         {
  560           Flag *flag = flags->data;
  561 
  562           if (flag->type & type)
  563             {
  564               if (last == NULL)
  565                 {
  566                   merged = g_list_prepend (NULL, flags->data);
  567                   last = merged;
  568                 }
  569               else
  570                 last = g_list_next (g_list_append (last, flags->data));
  571             }
  572         }
  573     }
  574 
  575   return merged;
  576 }
  577 
  578 static GList *
  579 fill_list (GList *packages, FlagType type,
  580            gboolean in_path_order, gboolean include_private)
  581 {
  582   GList *tmp;
  583   GList *expanded = NULL;
  584   GList *flags;
  585   GHashTable *visited;
  586 
  587   /* Start from the end of the requested package list to maintain order since
  588    * the recursive list is built by prepending. */
  589   visited = g_hash_table_new (g_str_hash, g_str_equal);
  590   for (tmp = g_list_last (packages); tmp != NULL; tmp = g_list_previous (tmp))
  591     recursive_fill_list (tmp->data, include_private, visited, &expanded);
  592   g_hash_table_destroy (visited);
  593   spew_package_list ("post-recurse", expanded);
  594 
  595   if (in_path_order)
  596     {
  597       spew_package_list ("original", expanded);
  598       expanded = packages_sort_by_path_position (expanded);
  599       spew_package_list ("  sorted", expanded);
  600     }
  601 
  602   flags = merge_flag_lists (expanded, type);
  603   g_list_free (expanded);
  604 
  605   return flags;
  606 }
  607 
  608 static GList *
  609 add_env_variable_to_list (GList *list, const gchar *env)
  610 {
  611   gchar **values;
  612   gint i;
  613 
  614   values = g_strsplit (env, G_SEARCHPATH_SEPARATOR_S, 0);
  615   for (i = 0; values[i] != NULL; i++)
  616     {
  617       list = g_list_append (list, g_strdup (values[i]));
  618     }
  619   g_strfreev (values);
  620 
  621   return list;
  622 }
  623 
  624 /* Well known compiler include path environment variables. These are
  625  * used to find additional system include paths to remove. See
  626  * https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html. */
  627 static const gchar *gcc_include_envvars[] = {
  628   "CPATH",
  629   "C_INCLUDE_PATH",
  630   "CPP_INCLUDE_PATH",
  631   NULL
  632 };
  633 
  634 #ifdef G_OS_WIN32
  635 /* MSVC include path environment variables. See
  636  * https://msdn.microsoft.com/en-us/library/73f9s62w.aspx. */
  637 static const gchar *msvc_include_envvars[] = {
  638   "INCLUDE",
  639   NULL
  640 };
  641 #endif
  642 
  643 static void
  644 verify_package (Package *pkg)
  645 {
  646   GList *requires = NULL;
  647   GList *conflicts = NULL;
  648   GList *system_directories = NULL;
  649   GList *iter;
  650   GList *requires_iter;
  651   GList *conflicts_iter;
  652   GList *system_dir_iter = NULL;
  653   GHashTable *visited;
  654   int count;
  655   const gchar *search_path;
  656   const gchar **include_envvars;
  657   const gchar **var;
  658 
  659   /* Be sure we have the required fields */
  660 
  661   if (pkg->key == NULL)
  662     {
  663       fprintf (stderr,
  664                "Internal pkg-config error, package with no key, please file a bug report\n");
  665       exit (1);
  666     }
  667   
  668   if (pkg->name == NULL)
  669     {
  670       verbose_error ("Package '%s' has no Name: field\n",
  671                      pkg->key);
  672       exit (1);
  673     }
  674 
  675   if (pkg->version == NULL)
  676     {
  677       verbose_error ("Package '%s' has no Version: field\n",
  678                      pkg->key);
  679       exit (1);
  680     }
  681 
  682   if (pkg->description == NULL)
  683     {
  684       verbose_error ("Package '%s' has no Description: field\n",
  685                      pkg->key);
  686       exit (1);
  687     }
  688   
  689   /* Make sure we have the right version for all requirements */
  690 
  691   iter = pkg->requires_private;
  692 
  693   while (iter != NULL)
  694     {
  695       Package *req = iter->data;
  696       RequiredVersion *ver = NULL;
  697 
  698       if (pkg->required_versions)
  699         ver = g_hash_table_lookup (pkg->required_versions,
  700                                    req->key);
  701 
  702       if (ver)
  703         {
  704           if (!version_test (ver->comparison, req->version, ver->version))
  705             {
  706               verbose_error ("Package '%s' requires '%s %s %s' but version of %s is %s\n",
  707                              pkg->key, req->key,
  708                              comparison_to_str (ver->comparison),
  709                              ver->version,
  710                              req->key,
  711                              req->version);
  712               if (req->url)
  713                 verbose_error ("You may find new versions of %s at %s\n",
  714                                req->name, req->url);
  715 
  716               exit (1);
  717             }
  718         }
  719                                    
  720       iter = g_list_next (iter);
  721     }
  722 
  723   /* Make sure we didn't drag in any conflicts via Requires
  724    * (inefficient algorithm, who cares)
  725    */
  726   visited = g_hash_table_new (g_str_hash, g_str_equal);
  727   recursive_fill_list (pkg, TRUE, visited, &requires);
  728   g_hash_table_destroy (visited);
  729   conflicts = pkg->conflicts;
  730 
  731   requires_iter = requires;
  732   while (requires_iter != NULL)
  733     {
  734       Package *req = requires_iter->data;
  735       
  736       conflicts_iter = conflicts;
  737 
  738       while (conflicts_iter != NULL)
  739         {
  740           RequiredVersion *ver = conflicts_iter->data;
  741 
  742       if (strcmp (ver->name, req->key) == 0 &&
  743           version_test (ver->comparison,
  744                 req->version,
  745                 ver->version))
  746             {
  747               verbose_error ("Version %s of %s creates a conflict.\n"
  748                              "(%s %s %s conflicts with %s %s)\n",
  749                              req->version, req->key,
  750                              ver->name,
  751                              comparison_to_str (ver->comparison),
  752                              ver->version ? ver->version : "(any)",
  753                              ver->owner->key,
  754                              ver->owner->version);
  755 
  756               exit (1);
  757             }
  758 
  759           conflicts_iter = g_list_next (conflicts_iter);
  760         }
  761       
  762       requires_iter = g_list_next (requires_iter);
  763     }
  764   
  765   g_list_free (requires);
  766 
  767   /* We make a list of system directories that compilers expect so we
  768    * can remove them.
  769    */
  770 
  771   search_path = g_getenv ("PKG_CONFIG_SYSTEM_INCLUDE_PATH");
  772 
  773   if (search_path == NULL)
  774     {
  775       search_path = PKG_CONFIG_SYSTEM_INCLUDE_PATH;
  776     }
  777 
  778   system_directories = add_env_variable_to_list (system_directories, search_path);
  779 
  780 #ifdef G_OS_WIN32
  781   include_envvars = msvc_syntax ? msvc_include_envvars : gcc_include_envvars;
  782 #else
  783   include_envvars = gcc_include_envvars;
  784 #endif
  785   for (var = include_envvars; *var != NULL; var++)
  786     {
  787       search_path = g_getenv (*var);
  788       if (search_path != NULL)
  789         system_directories = add_env_variable_to_list (system_directories, search_path);
  790     }
  791 
  792   count = 0;
  793   for (iter = pkg->cflags; iter != NULL; iter = g_list_next (iter))
  794     {
  795       gint offset = 0;
  796       Flag *flag = iter->data;
  797 
  798       if (!(flag->type & CFLAGS_I))
  799         continue;
  800 
  801       /* Handle the system cflags. We put things in canonical
  802        * -I/usr/include (vs. -I /usr/include) format, but if someone
  803        * changes it later we may as well be robust.
  804        *
  805        * Note that the -i* flags are left out of this handling since
  806        * they're intended to adjust the system cflags behavior.
  807        */
  808       if (((strncmp (flag->arg, "-I", 2) == 0) && (offset = 2))||
  809           ((strncmp (flag->arg, "-I ", 3) == 0) && (offset = 3)))
  810         {
  811       if (offset == 0)
  812         {
  813           iter = iter->next;
  814           continue;
  815         }
  816 
  817       system_dir_iter = system_directories;
  818       while (system_dir_iter != NULL)
  819         {
  820           if (strcmp (system_dir_iter->data,
  821                           ((char*)flag->arg) + offset) == 0)
  822         {
  823                   debug_spew ("Package %s has %s in Cflags\n",
  824                   pkg->key, (gchar *)flag->arg);
  825           if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") == NULL)
  826             {
  827                       debug_spew ("Removing %s from cflags for %s\n",
  828                                   flag->arg, pkg->key);
  829               ++count;
  830               iter->data = NULL;
  831 
  832               break;
  833             }
  834         }
  835           system_dir_iter = system_dir_iter->next;
  836         }
  837         }
  838     }
  839 
  840   while (count)
  841     {
  842       pkg->cflags = g_list_remove (pkg->cflags, NULL);
  843       --count;
  844     }
  845 
  846   g_list_foreach (system_directories, (GFunc) g_free, NULL);
  847   g_list_free (system_directories);
  848 
  849   system_directories = NULL;
  850 
  851   search_path = g_getenv ("PKG_CONFIG_SYSTEM_LIBRARY_PATH");
  852 
  853   if (search_path == NULL)
  854     {
  855       search_path = PKG_CONFIG_SYSTEM_LIBRARY_PATH;
  856     }
  857 
  858   system_directories = add_env_variable_to_list (system_directories, search_path);
  859 
  860   count = 0;
  861   for (iter = pkg->libs; iter != NULL; iter = g_list_next (iter))
  862     {
  863       GList *system_dir_iter = system_directories;
  864       Flag *flag = iter->data;
  865 
  866       if (!(flag->type & LIBS_L))
  867         continue;
  868 
  869       while (system_dir_iter != NULL)
  870         {
  871           gboolean is_system = FALSE;
  872           const char *linker_arg = flag->arg;
  873           const char *system_libpath = system_dir_iter->data;
  874 
  875           if (strncmp (linker_arg, "-L ", 3) == 0 &&
  876               strcmp (linker_arg + 3, system_libpath) == 0)
  877             is_system = TRUE;
  878           else if (strncmp (linker_arg, "-L", 2) == 0 &&
  879               strcmp (linker_arg + 2, system_libpath) == 0)
  880             is_system = TRUE;
  881           if (is_system)
  882             {
  883               debug_spew ("Package %s has -L %s in Libs\n",
  884                           pkg->key, system_libpath);
  885               if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_LIBS") == NULL)
  886                 {
  887                   iter->data = NULL;
  888                   ++count;
  889                   debug_spew ("Removing -L %s from libs for %s\n",
  890                               system_libpath, pkg->key);
  891                   break;
  892                 }
  893             }
  894           system_dir_iter = system_dir_iter->next;
  895         }
  896     }
  897   g_list_free (system_directories);
  898 
  899   while (count)
  900     {
  901       pkg->libs = g_list_remove (pkg->libs, NULL);
  902       --count;
  903     }
  904 }
  905 
  906 /* Create a merged list of required packages and retrieve the flags from them.
  907  * Strip the duplicates from the flags list. The sorting and stripping can be
  908  * done in one of two ways: packages sorted by position in the pkg-config path
  909  * and stripping done from the beginning of the list, or packages sorted from
  910  * most dependent to least dependent and stripping from the end of the list.
  911  * The former is done for -I/-L flags, and the latter for all others.
  912  */
  913 static char *
  914 get_multi_merged (GList *pkgs, FlagType type, gboolean in_path_order,
  915                   gboolean include_private)
  916 {
  917   GList *list;
  918   char *retval;
  919 
  920   list = fill_list (pkgs, type, in_path_order, include_private);
  921   list = flag_list_strip_duplicates (list);
  922   retval = flag_list_to_string (list);
  923   g_list_free (list);
  924 
  925   return retval;
  926 }
  927 
  928 char *
  929 packages_get_flags (GList *pkgs, FlagType flags)
  930 {
  931   GString *str;
  932   char *cur;
  933 
  934   str = g_string_new (NULL);
  935 
  936   /* sort packages in path order for -L/-I, dependency order otherwise */
  937   if (flags & CFLAGS_OTHER)
  938     {
  939       cur = get_multi_merged (pkgs, CFLAGS_OTHER, FALSE, TRUE);
  940       debug_spew ("adding CFLAGS_OTHER string \"%s\"\n", cur);
  941       g_string_append (str, cur);
  942       g_free (cur);
  943     }
  944   if (flags & CFLAGS_I)
  945     {
  946       cur = get_multi_merged (pkgs, CFLAGS_I, TRUE, TRUE);
  947       debug_spew ("adding CFLAGS_I string \"%s\"\n", cur);
  948       g_string_append (str, cur);
  949       g_free (cur);
  950     }
  951   if (flags & LIBS_L)
  952     {
  953       cur = get_multi_merged (pkgs, LIBS_L, TRUE, !ignore_private_libs);
  954       debug_spew ("adding LIBS_L string \"%s\"\n", cur);
  955       g_string_append (str, cur);
  956       g_free (cur);
  957     }
  958   if (flags & (LIBS_OTHER | LIBS_l))
  959     {
  960       cur = get_multi_merged (pkgs, flags & (LIBS_OTHER | LIBS_l), FALSE,
  961                               !ignore_private_libs);
  962       debug_spew ("adding LIBS_OTHER | LIBS_l string \"%s\"\n", cur);
  963       g_string_append (str, cur);
  964       g_free (cur);
  965     }
  966 
  967   /* Strip trailing space. */
  968   if (str->len > 0 && str->str[str->len - 1] == ' ')
  969     g_string_truncate (str, str->len - 1);
  970 
  971   debug_spew ("returning flags string \"%s\"\n", str->str);
  972   return g_string_free (str, FALSE);
  973 }
  974 
  975 void
  976 define_global_variable (const char *varname,
  977                         const char *varval)
  978 {
  979   if (globals == NULL)
  980     globals = g_hash_table_new (g_str_hash, g_str_equal);
  981 
  982   if (g_hash_table_lookup (globals, varname))
  983     {
  984       verbose_error ("Variable '%s' defined twice globally\n", varname);
  985       exit (1);
  986     }
  987   
  988   g_hash_table_insert (globals, g_strdup (varname), g_strdup (varval));
  989       
  990   debug_spew ("Global variable definition '%s' = '%s'\n",
  991               varname, varval);
  992 }
  993 
  994 char *
  995 var_to_env_var (const char *pkg, const char *var)
  996 {
  997   char *new = g_strconcat ("PKG_CONFIG_", pkg, "_", var, NULL);
  998   char *p;
  999   for (p = new; *p != 0; p++)
 1000     {
 1001       char c = g_ascii_toupper (*p);
 1002 
 1003       if (!g_ascii_isalnum (c))
 1004         c = '_';
 1005 
 1006       *p = c;
 1007     }
 1008 
 1009   return new;
 1010 }
 1011 
 1012 char *
 1013 package_get_var (Package *pkg,
 1014                  const char *var)
 1015 {
 1016   char *varval = NULL;
 1017 
 1018   if (globals)
 1019     varval = g_strdup (g_hash_table_lookup (globals, var));
 1020 
 1021   /* Allow overriding specific variables using an environment variable of the
 1022    * form PKG_CONFIG_$PACKAGENAME_$VARIABLE
 1023    */
 1024   if (pkg->key)
 1025     {
 1026       char *env_var = var_to_env_var (pkg->key, var);
 1027       const char *env_var_content = g_getenv (env_var);
 1028       g_free (env_var);
 1029       if (env_var_content)
 1030         {
 1031           debug_spew ("Overriding variable '%s' from environment\n", var);
 1032           return g_strdup (env_var_content);
 1033         }
 1034     }
 1035 
 1036 
 1037   if (varval == NULL && pkg->vars)
 1038     varval = g_strdup (g_hash_table_lookup (pkg->vars, var));
 1039 
 1040   return varval;
 1041 }
 1042 
 1043 char *
 1044 packages_get_var (GList      *pkgs,
 1045                   const char *varname)
 1046 {
 1047   GList *tmp;
 1048   GString *str;
 1049 
 1050   str = g_string_new (NULL);
 1051 
 1052   tmp = pkgs;
 1053   while (tmp != NULL)
 1054     {
 1055       Package *pkg = tmp->data;
 1056       char *var;
 1057 
 1058       var = parse_package_variable (pkg, varname);
 1059       if (var)
 1060         {
 1061           if (str->len > 0)
 1062             g_string_append_c (str, ' ');
 1063           g_string_append (str, var);
 1064           g_free (var);
 1065         }
 1066 
 1067       tmp = g_list_next (tmp);
 1068     }
 1069 
 1070   return g_string_free (str, FALSE);
 1071 }
 1072 
 1073 int
 1074 compare_versions (const char * a, const char *b)
 1075 {
 1076   return rpmvercmp (a, b);
 1077 }
 1078 
 1079 gboolean
 1080 version_test (ComparisonType comparison,
 1081               const char *a,
 1082               const char *b)
 1083 {
 1084   switch (comparison)
 1085     {
 1086     case LESS_THAN:
 1087       return compare_versions (a, b) < 0;
 1088       break;
 1089 
 1090     case GREATER_THAN:
 1091       return compare_versions (a, b) > 0;
 1092       break;
 1093 
 1094     case LESS_THAN_EQUAL:
 1095       return compare_versions (a, b) <= 0;
 1096       break;
 1097 
 1098     case GREATER_THAN_EQUAL:
 1099       return compare_versions (a, b) >= 0;
 1100       break;
 1101 
 1102     case EQUAL:
 1103       return compare_versions (a, b) == 0;
 1104       break;
 1105 
 1106     case NOT_EQUAL:
 1107       return compare_versions (a, b) != 0;
 1108       break;
 1109 
 1110     case ALWAYS_MATCH:
 1111       return TRUE;
 1112       break;
 1113       
 1114     default:
 1115       g_assert_not_reached ();
 1116       break;
 1117     }
 1118 
 1119   return FALSE;
 1120 }
 1121 
 1122 const char *
 1123 comparison_to_str (ComparisonType comparison)
 1124 {
 1125   switch (comparison)
 1126     {
 1127     case LESS_THAN:
 1128       return "<";
 1129       break;
 1130 
 1131     case GREATER_THAN:
 1132       return ">";
 1133       break;
 1134 
 1135     case LESS_THAN_EQUAL:
 1136       return "<=";
 1137       break;
 1138 
 1139     case GREATER_THAN_EQUAL:
 1140       return ">=";
 1141       break;
 1142 
 1143     case EQUAL:
 1144       return "=";
 1145       break;
 1146 
 1147     case NOT_EQUAL:
 1148       return "!=";
 1149       break;
 1150 
 1151     case ALWAYS_MATCH:
 1152       return "(any)";
 1153       break;
 1154       
 1155     default:
 1156       g_assert_not_reached ();
 1157       break;
 1158     }
 1159 
 1160   return "???";
 1161 }
 1162 
 1163 static void
 1164 max_len_foreach (gpointer key, gpointer value, gpointer data)
 1165 {
 1166   int *mlen = data;
 1167 
 1168   *mlen = MAX (*mlen, strlen (key));
 1169 }
 1170 
 1171 static void
 1172 packages_foreach (gpointer key, gpointer value, gpointer data)
 1173 {
 1174   Package *pkg = value;
 1175   char *pad;
 1176 
 1177   pad = g_strnfill (GPOINTER_TO_INT (data) - strlen (pkg->key), ' ');
 1178       
 1179   printf ("%s%s%s - %s\n",
 1180           pkg->key, pad, pkg->name, pkg->description);
 1181 
 1182   g_free (pad);
 1183 }
 1184 
 1185 void
 1186 print_package_list (void)
 1187 {
 1188   int mlen = 0;
 1189 
 1190   ignore_requires = TRUE;
 1191   ignore_requires_private = TRUE;
 1192 
 1193   g_hash_table_foreach (packages, max_len_foreach, &mlen);
 1194   g_hash_table_foreach (packages, packages_foreach, GINT_TO_POINTER (mlen + 1));
 1195 }
 1196 
 1197 void
 1198 enable_private_libs(void)
 1199 {
 1200   ignore_private_libs = FALSE;
 1201 }
 1202 
 1203 void
 1204 disable_private_libs(void)
 1205 {
 1206   ignore_private_libs = TRUE;
 1207 }
 1208 
 1209 void
 1210 enable_requires(void)
 1211 {
 1212   ignore_requires = FALSE;
 1213 }
 1214 
 1215 void
 1216 disable_requires(void)
 1217 {
 1218   ignore_requires = TRUE;
 1219 }
 1220 
 1221 void
 1222 enable_requires_private(void)
 1223 {
 1224   ignore_requires_private = FALSE;
 1225 }
 1226 
 1227 void
 1228 disable_requires_private(void)
 1229 {
 1230   ignore_requires_private = TRUE;
 1231 }