]> err.no Git - pkg-config/blob - pkg.c
Print out \r\n on windows, not just \n
[pkg-config] / pkg.c
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
28 #ifdef HAVE_ALLOCA_H
29 # include <alloca.h>
30 #else
31 # ifdef _AIX
32 #  pragma alloca
33 # endif
34 #endif
35
36 #ifdef HAVE_MALLOC_H
37 # include <malloc.h>
38 #endif
39
40 #include <sys/types.h>
41 #include <dirent.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <stdio.h>
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48 #include <stdlib.h>
49 #include <ctype.h>
50
51 static void verify_package (Package *pkg);
52
53 static GHashTable *packages = NULL;
54 static GHashTable *locations = NULL;
55 static GHashTable *path_positions = NULL;
56 static GHashTable *globals = NULL;
57 static GSList *search_dirs = NULL;
58 static int scanned_dir_count = 0;
59
60 gboolean disable_uninstalled = FALSE;
61 gboolean ignore_requires = FALSE;
62 gboolean ignore_requires_private = TRUE;
63 gboolean ignore_private_libs = TRUE;
64
65 void
66 add_search_dir (const char *path)
67 {
68   search_dirs = g_slist_append (search_dirs, g_strdup (path));
69 }
70
71 void
72 add_search_dirs (const char *path, const char *separator)
73 {
74       char **search_dirs;
75       char **iter;
76
77       search_dirs = g_strsplit (path, separator, -1);
78     
79       iter = search_dirs;
80       while (*iter)
81         {
82           debug_spew ("Adding directory '%s' from PKG_CONFIG_PATH\n",
83                       *iter);
84           add_search_dir (*iter);
85           
86           ++iter;
87         }
88       
89       g_strfreev (search_dirs);
90 }
91
92 #ifdef G_OS_WIN32
93 /* Guard against .pc file being installed with UPPER CASE name */
94 # define FOLD(x) tolower(x)
95 # define FOLDCMP(a, b) g_ascii_strcasecmp (a, b)
96 #else
97 # define FOLD(x) (x)
98 # define FOLDCMP(a, b) strcmp (a, b)
99 #endif
100
101 #define EXT_LEN 3
102
103 static gboolean
104 ends_in_dotpc (const char *str)
105 {
106   int len = strlen (str);
107   
108   if (len > EXT_LEN &&
109       str[len - 3] == '.' &&
110       FOLD (str[len - 2]) == 'p' &&
111       FOLD (str[len - 1]) == 'c')
112     return TRUE;
113   else
114     return FALSE;
115 }
116
117 /* strlen ("uninstalled") */
118 #define UNINSTALLED_LEN 11
119
120 gboolean
121 name_ends_in_uninstalled (const char *str)
122 {
123   int len = strlen (str);
124   
125   if (len > UNINSTALLED_LEN &&
126       FOLDCMP ((str + len - UNINSTALLED_LEN), "uninstalled") == 0)
127     return TRUE;
128   else
129     return FALSE;
130 }
131
132
133 /* Look for .pc files in the given directory and add them into
134  * locations, ignoring duplicates
135  */
136 static void
137 scan_dir (const char *dirname)
138 {
139   DIR *dir;
140   struct dirent *dent;
141   int dirnamelen = strlen (dirname);
142   /* Use a copy of dirname cause Win32 opendir doesn't like
143    * superfluous trailing (back)slashes in the directory name.
144    */
145   char *dirname_copy = g_strdup (dirname);
146
147   if (dirnamelen > 1 && dirname[dirnamelen-1] == G_DIR_SEPARATOR)
148     {
149       dirnamelen--;
150       dirname_copy[dirnamelen] = '\0';
151     }
152 #ifdef G_OS_WIN32
153     {
154       gchar *p;
155       /* Turn backslashes into slashes or
156        * poptParseArgvString() will eat them when ${prefix}
157        * has been expanded in parse_libs().
158        */
159       p = dirname;
160       while (*p)
161         {
162           if (*p == '\\')
163             *p = '/';
164           p++;
165         }
166     }
167 #endif
168   dir = opendir (dirname_copy);
169   g_free (dirname_copy);
170   if (!dir)
171     {
172       debug_spew ("Cannot open directory '%s' in package search path: %s\n",
173                   dirname, g_strerror (errno));
174       return;
175     }
176
177   debug_spew ("Scanning directory '%s'\n", dirname);
178
179   scanned_dir_count += 1;
180   
181   while ((dent = readdir (dir)))
182     {
183       int len = strlen (dent->d_name);
184
185       if (ends_in_dotpc (dent->d_name))
186         {
187           char *pkgname = g_malloc (len - 2);
188
189           debug_spew ("File '%s' appears to be a .pc file\n", dent->d_name);
190           
191           strncpy (pkgname, dent->d_name, len - EXT_LEN);
192           pkgname[len-EXT_LEN] = '\0';
193
194           if (g_hash_table_lookup (locations, pkgname))
195             {
196               debug_spew ("File '%s' ignored, we already know about package '%s'\n", dent->d_name, pkgname);
197               g_free (pkgname);
198             }
199           else
200             {
201               char *filename = g_malloc (dirnamelen + 1 + len + 1);
202               strncpy (filename, dirname, dirnamelen);
203               filename[dirnamelen] = G_DIR_SEPARATOR;
204               strcpy (filename + dirnamelen + 1, dent->d_name);
205               
206               g_hash_table_insert (locations, pkgname, filename);
207               g_hash_table_insert (path_positions, pkgname,
208                                    GINT_TO_POINTER (scanned_dir_count));
209               
210               debug_spew ("Will find package '%s' in file '%s'\n",
211                           pkgname, filename);
212             }
213         }
214       else
215         {
216           debug_spew ("Ignoring file '%s' in search directory; not a .pc file\n",
217                       dent->d_name);
218         }
219     }
220   closedir(dir);
221 }
222
223 static Package *
224 add_virtual_pkgconfig_package (void)
225 {
226   Package *pkg = NULL;
227
228   pkg = g_new0 (Package, 1);
229
230   pkg->key = g_strdup ("pkg-config");
231   pkg->version = g_strdup (VERSION);
232   pkg->name = g_strdup ("pkg-config");
233   pkg->description = g_strdup ("pkg-config is a system for managing "
234                                "compile/link flags for libraries");
235   pkg->url = g_strdup ("http://pkg-config.freedesktop.org/");
236
237   if (pkg->vars == NULL)
238     pkg->vars = g_hash_table_new (g_str_hash, g_str_equal);
239   g_hash_table_insert (pkg->vars, "pc_path", PKG_CONFIG_PC_PATH);
240
241   debug_spew ("Adding virtual 'pkg-config' package to list of known packages\n");
242   g_hash_table_insert (packages, pkg->key, pkg);
243
244   return pkg;
245 }
246
247 void
248 package_init ()
249 {
250   static gboolean initted = FALSE;
251
252   if (!initted)
253     {
254       initted = TRUE;
255       
256       packages = g_hash_table_new (g_str_hash, g_str_equal);
257       locations = g_hash_table_new (g_str_hash, g_str_equal);
258       path_positions = g_hash_table_new (g_str_hash, g_str_equal);
259       
260       add_virtual_pkgconfig_package ();
261
262       g_slist_foreach (search_dirs, (GFunc)scan_dir, NULL);
263     }
264 }
265
266 static gboolean
267 file_readable (const char *path)
268 {
269   FILE *f = fopen (path, "r");
270
271   if (f != NULL)
272     {
273       fclose (f);
274       return TRUE;
275     }
276   else
277     return FALSE;
278 }
279
280
281 static Package *
282 internal_get_package (const char *name, gboolean warn, gboolean check_compat)
283 {
284   Package *pkg = NULL;
285   const char *location;
286   
287   pkg = g_hash_table_lookup (packages, name);
288
289   if (pkg)
290     return pkg;
291
292   debug_spew ("Looking for package '%s'\n", name);
293   
294   /* treat "name" as a filename if it ends in .pc and exists */
295   if ( ends_in_dotpc (name) )
296     {
297       debug_spew ("Considering '%s' to be a filename rather than a package name\n", name);
298       location = name;
299     }
300   else
301     {
302       /* See if we should auto-prefer the uninstalled version */
303       if (!disable_uninstalled &&
304           !name_ends_in_uninstalled (name))
305         {
306           char *un;
307
308           un = g_strconcat (name, "-uninstalled", NULL);
309
310           pkg = internal_get_package (un, FALSE, FALSE);
311
312           g_free (un);
313           
314           if (pkg)
315             {
316               debug_spew ("Preferring uninstalled version of package '%s'\n", name);
317               return pkg;
318             }
319         }
320       
321       location = g_hash_table_lookup (locations, name);
322     }
323   
324   if (location == NULL && check_compat)
325     {
326       pkg = get_compat_package (name);
327
328       if (pkg)
329         {
330           debug_spew ("Returning values for '%s' from a legacy -config script\n",
331                       name);
332           
333           return pkg;
334         }
335     }
336       
337   if (location == NULL)
338     {
339       if (warn)
340         verbose_error ("Package %s was not found in the pkg-config search path.\n"
341                        "Perhaps you should add the directory containing `%s.pc'\n"
342                        "to the PKG_CONFIG_PATH environment variable\n",
343                        name, name);
344
345       return NULL;
346     }
347
348   debug_spew ("Reading '%s' from file '%s'\n", name, location);
349   pkg = parse_package_file (location, ignore_requires, ignore_private_libs, 
350                             ignore_requires_private);
351   
352   if (pkg == NULL)
353     {
354       debug_spew ("Failed to parse '%s'\n", location);
355       return NULL;
356     }
357   
358   if (strstr (location, "uninstalled.pc"))
359     pkg->uninstalled = TRUE;
360   
361   if (location != name)
362     pkg->key = g_strdup (name);
363   else
364     {
365       /* need to strip package name out of the filename */
366       int len = strlen (name);
367       const char *end = name + (len - EXT_LEN);
368       const char *start = end;
369
370       while (start != name && *start != G_DIR_SEPARATOR)
371         --start;
372
373       g_assert (end >= start);
374       
375       pkg->key = g_strndup (start, end - start);
376     }
377
378   pkg->path_position =
379     GPOINTER_TO_INT (g_hash_table_lookup (path_positions, pkg->key));
380
381   debug_spew ("Path position of '%s' is %d\n",
382               pkg->name, pkg->path_position);
383   
384   verify_package (pkg);
385
386   debug_spew ("Adding '%s' to list of known packages, returning as package '%s'\n",
387               pkg->key, name);
388   
389   g_hash_table_insert (packages, pkg->key, pkg);
390
391   return pkg;
392 }
393
394 Package *
395 get_package (const char *name)
396 {
397   return internal_get_package (name, TRUE, TRUE);
398 }
399
400 Package *
401 get_package_quiet (const char *name)
402 {
403   return internal_get_package (name, FALSE, TRUE);
404 }
405
406 static GSList*
407 string_list_strip_duplicates (GSList *list)
408 {
409   GHashTable *table;
410   GSList *tmp;
411   GSList *nodups = NULL;
412   
413   table = g_hash_table_new (g_str_hash, g_str_equal);
414
415   tmp = list;
416   while (tmp != NULL)
417     {
418       if (g_hash_table_lookup (table, tmp->data) == NULL)
419         {
420           nodups = g_slist_prepend (nodups, tmp->data);
421           g_hash_table_insert (table, tmp->data, tmp->data);
422         }
423       else
424         {
425           debug_spew (" removing duplicate \"%s\"\n", tmp->data);
426         }
427
428       tmp = g_slist_next (tmp);
429     }
430
431   nodups = g_slist_reverse (nodups);
432   
433   g_hash_table_destroy (table);
434   
435   return nodups;
436 }
437
438 static GSList*
439 string_list_strip_duplicates_from_back (GSList *list)
440 {
441   GHashTable *table;
442   GSList *tmp;
443   GSList *nodups = NULL;
444   GSList *reversed;
445   
446   table = g_hash_table_new (g_str_hash, g_str_equal);
447
448   reversed = g_slist_reverse (g_slist_copy (list));
449   
450   tmp = reversed;
451   while (tmp != NULL)
452     {
453       if (g_hash_table_lookup (table, tmp->data) == NULL)
454         {
455           /* This unreverses the reversed list */
456           nodups = g_slist_prepend (nodups, tmp->data);
457           g_hash_table_insert (table, tmp->data, tmp->data);
458         }
459       else
460         {
461           debug_spew (" removing duplicate (from back) \"%s\"\n", tmp->data);
462         }
463       
464       tmp = g_slist_next (tmp);
465     }
466
467   g_slist_free (reversed);
468   
469   g_hash_table_destroy (table);
470   
471   return nodups;
472 }
473
474 static char *
475 string_list_to_string (GSList *list)
476 {
477   GSList *tmp;
478   GString *str = g_string_new ("");
479   char *retval;
480   
481   tmp = list;
482   while (tmp != NULL)
483     {
484       char *tmpstr = (char*) tmp->data;
485       if (pcsysrootdir != NULL)
486         {
487           if (tmpstr[0] == '-' &&
488               (tmpstr[1] == 'I' ||
489                tmpstr[1] == 'L'))
490             {
491               g_string_append_c (str, '-');
492               g_string_append_c (str, tmpstr[1]);
493               g_string_append (str, pcsysrootdir);
494               g_string_append (str, tmpstr+2);
495             }
496           else
497             {
498               g_string_append (str, tmpstr);
499             }
500         }
501       else
502         {
503           g_string_append (str, tmpstr);
504         }
505       g_string_append_c (str, ' ');
506       
507       tmp = g_slist_next (tmp);
508     }
509
510   retval = str->str;
511   g_string_free (str, FALSE);
512
513   return retval;
514 }
515
516 typedef GSList *(* GetListFunc) (Package *pkg);
517
518 static GSList *
519 get_l_libs (Package *pkg)
520 {
521   return pkg->l_libs;
522 }
523
524 static GSList *
525 get_L_libs (Package *pkg)
526 {
527   return pkg->L_libs;
528 }
529
530 static GSList*
531 get_other_libs (Package *pkg)
532 {  
533   return pkg->other_libs;
534 }
535
536 static GSList *
537 get_I_cflags (Package *pkg)
538 {
539   return pkg->I_cflags;
540 }
541
542 static GSList *
543 get_other_cflags (Package *pkg)
544 {
545   return pkg->other_cflags;
546 }
547
548 static GSList *
549 get_conflicts (Package *pkg)
550 {
551   return pkg->conflicts;
552 }
553
554 static GSList *
555 get_requires (Package *pkg)
556 {
557   return pkg->requires;
558 }
559
560 static GSList *
561 get_requires_private (Package *pkg)
562 {
563   return pkg->requires_private;
564 }
565
566 static int
567 pathposcmp (gconstpointer a, gconstpointer b)
568 {
569   const Package *pa = a;
570   const Package *pb = b;
571   
572   if (pa->path_position < pb->path_position)
573     return -1;
574   else if (pa->path_position > pb->path_position)
575     return 1;
576   else
577     return 0;
578 }
579
580 static void
581 spew_package_list (const char *name,
582                    GSList     *list)
583 {
584   GSList *tmp;
585
586   debug_spew (" %s: ", name);
587   
588   tmp = list;
589   while (tmp != NULL)
590     {
591       Package *pkg = tmp->data;
592       debug_spew (" %s ", pkg->name);
593       tmp = tmp->next;
594     }
595   debug_spew ("\n");
596 }
597
598 static void
599 spew_string_list (const char *name,
600                   GSList     *list)
601 {
602   GSList *tmp;
603
604   debug_spew (" %s: ", name);
605   
606   tmp = list;
607   while (tmp != NULL)
608     {
609       debug_spew (" %s ", tmp->data);
610       tmp = tmp->next;
611     }
612   debug_spew ("\n");
613 }
614
615 static GSList*
616 packages_sort_by_path_position (GSList *list)
617 {
618   return g_slist_sort (list, pathposcmp);
619 }
620
621 static void
622 fill_one_level (Package *pkg, GetListFunc func, GSList **listp)
623 {
624   GSList *copy;
625
626   copy = g_slist_copy ((*func)(pkg));
627
628   *listp = g_slist_concat (*listp, copy);
629 }
630
631 static void
632 recursive_fill_list (Package *pkg, GetListFunc func, GSList **listp)
633 {
634   GSList *tmp;
635
636   fill_one_level (pkg, func, listp);
637   
638   tmp = (*func) (pkg);
639
640   while (tmp != NULL)
641     {
642       recursive_fill_list (tmp->data, func, listp);
643
644       tmp = g_slist_next (tmp);
645     }
646 }
647
648 static void
649 fill_list_single_package (Package *pkg, GetListFunc func,
650                           GSList **listp, gboolean in_path_order,
651                           gboolean include_private)
652 {
653   /* First we get the list in natural/recursive order, then
654    * stable sort by path position
655    */
656   GSList *packages;
657   GSList *tmp;
658
659   /* Get list of packages */
660   packages = NULL;
661   packages = g_slist_append (packages, pkg);
662   recursive_fill_list (pkg,
663                        include_private ? get_requires_private : get_requires,
664                        &packages);
665   
666   if (in_path_order)
667     {
668       spew_package_list ("original", packages);
669       
670       packages = packages_sort_by_path_position (packages);
671       
672       spew_package_list ("sorted", packages);
673     }
674   
675   /* Convert package list to string list */
676   tmp = packages;
677   while (tmp != NULL)
678     {
679       fill_one_level (tmp->data, func, listp);
680       
681       tmp = tmp->next;
682     }
683
684   g_slist_free (packages);
685 }
686
687 static void
688 fill_list (GSList *packages, GetListFunc func,
689            GSList **listp, gboolean in_path_order, gboolean include_private)
690 {
691   GSList *tmp;
692   GSList *expanded;
693
694   expanded = NULL;
695   tmp = packages;
696   while (tmp != NULL)
697     {
698       expanded = g_slist_append (expanded, tmp->data);
699       recursive_fill_list (tmp->data,
700                            include_private ? get_requires_private : get_requires,
701                            &expanded);
702
703       tmp = tmp->next;
704     }
705
706   if (in_path_order)
707     {
708       spew_package_list ("original", expanded);
709       
710       expanded = packages_sort_by_path_position (expanded);
711       
712       spew_package_list ("sorted", expanded);
713     }
714   
715   tmp = expanded;
716   while (tmp != NULL)
717     {
718       fill_one_level (tmp->data, func, listp);
719       
720       tmp = tmp->next;
721     }
722
723   g_slist_free (expanded);
724 }
725
726 static gint
727 compare_req_version_names (gconstpointer a, gconstpointer b)
728 {
729   const RequiredVersion *ver_a = a;
730   const RequiredVersion *ver_b = b;
731
732   return strcmp (ver_a->name, ver_b->name);
733 }
734
735 static gint
736 compare_package_keys (gconstpointer a, gconstpointer b)
737 {
738   const Package *pkg_a = a;
739   const Package *pkg_b = b;
740
741   return strcmp (pkg_a->key, pkg_b->key);
742 }
743
744 static GSList *
745 add_env_variable_to_list (GSList *list, const gchar *env)
746 {
747   gchar **values;
748   gint i;
749
750   values = g_strsplit (env, G_SEARCHPATH_SEPARATOR_S, 0);
751   for (i = 0; values[i] != NULL; i++)
752     {
753       list = g_slist_append (list, g_strdup (values[i]));
754     }
755   g_strfreev (values);
756
757   return list;
758 }
759
760 static void
761 verify_package (Package *pkg)
762 {
763   GSList *requires = NULL;
764   GSList *conflicts = NULL;
765   GSList *system_directories = NULL;
766   GSList *iter;
767   GSList *requires_iter;
768   GSList *conflicts_iter;
769   GSList *system_dir_iter = NULL;
770   int count;
771   const gchar *c_include_path;
772
773   /* Be sure we have the required fields */
774
775   if (pkg->key == NULL)
776     {
777       fprintf (stderr,
778                "Internal pkg-config error, package with no key, please file a bug report\n");
779       exit (1);
780     }
781   
782   if (pkg->name == NULL)
783     {
784       verbose_error ("Package '%s' has no Name: field\n",
785                      pkg->key);
786       exit (1);
787     }
788
789   if (pkg->version == NULL)
790     {
791       verbose_error ("Package '%s' has no Version: field\n",
792                      pkg->key);
793       exit (1);
794     }
795
796   if (pkg->description == NULL)
797     {
798       verbose_error ("Package '%s' has no Description: field\n",
799                      pkg->key);
800       exit (1);
801     }
802   
803   /* Make sure we have the right version for all requirements */
804
805   iter = pkg->requires_private;
806
807   while (iter != NULL)
808     {
809       Package *req = iter->data;
810       RequiredVersion *ver = NULL;
811
812       if (pkg->required_versions)
813         ver = g_hash_table_lookup (pkg->required_versions,
814                                    req->key);
815
816       if (ver)
817         {
818           if (!version_test (ver->comparison, req->version, ver->version))
819             {
820               verbose_error ("Package '%s' requires '%s %s %s' but version of %s is %s\n",
821                              pkg->name, req->key,
822                              comparison_to_str (ver->comparison),
823                              ver->version,
824                              req->name,
825                              req->version);
826               if (req->url)
827                 verbose_error ("You may find new versions of %s at %s\n",
828                                req->name, req->url);
829
830               exit (1);
831             }
832         }
833                                    
834       iter = g_slist_next (iter);
835     }
836
837   /* Make sure we didn't drag in any conflicts via Requires
838    * (inefficient algorithm, who cares)
839    */
840   
841   recursive_fill_list (pkg, get_requires_private, &requires);
842   conflicts = get_conflicts (pkg);
843
844   requires_iter = requires;
845   while (requires_iter != NULL)
846     {
847       Package *req = requires_iter->data;
848       
849       conflicts_iter = conflicts;
850
851       while (conflicts_iter != NULL)
852         {
853           RequiredVersion *ver = conflicts_iter->data;
854
855           if (strcmp (ver->name, req->key) == 0 &&
856               version_test (ver->comparison,
857                             req->version,
858                             ver->version))
859             {
860               verbose_error ("Version %s of %s creates a conflict.\n"
861                              "(%s %s %s conflicts with %s %s)\n",
862                              req->version, req->name,
863                              ver->name,
864                              comparison_to_str (ver->comparison),
865                              ver->version ? ver->version : "(any)",
866                              ver->owner->name,
867                              ver->owner->version);
868
869               exit (1);
870             }
871
872           conflicts_iter = g_slist_next (conflicts_iter);
873         }
874       
875       requires_iter = g_slist_next (requires_iter);
876     }
877   
878   g_slist_free (requires);
879
880   /* We make a list of system directories that gcc expects so we can remove
881    * them.
882    */
883 #ifndef G_OS_WIN32
884   system_directories = g_slist_append (NULL, g_strdup ("/usr/include"));
885 #endif
886
887   c_include_path = g_getenv ("C_INCLUDE_PATH");
888   if (c_include_path != NULL)
889     {
890       system_directories = add_env_variable_to_list (system_directories, c_include_path);
891     }
892   
893   c_include_path = g_getenv ("CPLUS_INCLUDE_PATH");
894   if (c_include_path != NULL)
895     {
896       system_directories = add_env_variable_to_list (system_directories, c_include_path);
897     }
898
899   count = 0;
900   iter = pkg->I_cflags;
901   while (iter != NULL)
902     {
903       gint offset = 0;
904       /* we put things in canonical -I/usr/include (vs. -I /usr/include) format,
905        * but if someone changes it later we may as well be robust
906        */
907       if (((strncmp (iter->data, "-I", 2) == 0) && (offset = 2))||
908           ((strncmp (iter->data, "-I ", 3) == 0) && (offset = 3)))
909         {
910           if (offset == 0)
911             {
912               iter = iter->next;
913               continue;
914             }
915
916           system_dir_iter = system_directories;
917           while (system_dir_iter != NULL)
918             {
919               if (strcmp (system_dir_iter->data,
920                           ((char*)iter->data) + offset) == 0)
921                 {
922                   debug_spew ("Package %s has %s in Cflags\n",
923                               pkg->name, (gchar *)iter->data);
924                   if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") == NULL)
925                     {
926                       debug_spew ("Removing %s from cflags for %s\n", iter->data, pkg->key);
927                       ++count;
928                       iter->data = NULL;
929                       
930                       break;
931                     }
932                 }
933               system_dir_iter = system_dir_iter->next;
934             }
935         }
936
937       iter = iter->next;
938     }
939
940   while (count)
941     {
942       pkg->I_cflags = g_slist_remove (pkg->I_cflags, NULL);
943       --count;
944     }
945
946   g_slist_foreach (system_directories, (GFunc) g_free, NULL);
947   g_slist_free (system_directories);
948
949 #ifdef PREFER_LIB64
950 #define SYSTEM_LIBDIR "/usr/lib64"
951 #else
952 #define SYSTEM_LIBDIR "/usr/lib"
953 #endif
954   count = 0;
955   iter = pkg->L_libs;
956   while (iter != NULL)
957     {
958       if (strcmp (iter->data, "-L" SYSTEM_LIBDIR) == 0 ||
959           strcmp (iter->data, "-L " SYSTEM_LIBDIR) == 0)
960         {
961           debug_spew ("Package %s has -L" SYSTEM_LIBDIR " in Libs\n",
962                       pkg->name);
963           if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_LIBS") == NULL)
964             {              
965               iter->data = NULL;
966               ++count;
967               debug_spew ("Removing -L" SYSTEM_LIBDIR " from libs for %s\n", pkg->key);
968             }
969         }
970
971       iter = iter->next;
972     }
973 #undef SYSTEM_LIBDIR
974
975   while (count)
976     {
977       pkg->L_libs = g_slist_remove (pkg->L_libs, NULL);
978       --count;
979     }
980 }
981
982 static char*
983 get_merged (Package *pkg, GetListFunc func, gboolean in_path_order,
984             gboolean include_private)
985 {
986   GSList *list;
987   GSList *dups_list = NULL;
988   char *retval;
989   
990   fill_list_single_package (pkg, func, &dups_list, in_path_order,
991                             include_private);
992   
993   list = string_list_strip_duplicates (dups_list);
994
995   g_slist_free (dups_list);
996   
997   retval = string_list_to_string (list);
998
999   g_slist_free (list);
1000   
1001   return retval;
1002 }
1003
1004 static char*
1005 get_merged_from_back (Package *pkg, GetListFunc func, gboolean in_path_order,
1006                       gboolean include_private)
1007 {
1008   GSList *list;
1009   GSList *dups_list = NULL;
1010   char *retval;
1011   
1012   fill_list_single_package (pkg, func, &dups_list, in_path_order,
1013                             include_private);
1014   
1015   list = string_list_strip_duplicates_from_back (dups_list);
1016
1017   g_slist_free (dups_list);
1018   
1019   retval = string_list_to_string (list);
1020
1021   g_slist_free (list);
1022   
1023   return retval;
1024 }
1025
1026 static char*
1027 get_multi_merged (GSList *pkgs, GetListFunc func, gboolean in_path_order,
1028                   gboolean include_private)
1029 {
1030   GSList *tmp;
1031   GSList *dups_list = NULL;
1032   GSList *list;
1033   char *retval;
1034
1035   fill_list (pkgs, func, &dups_list, in_path_order, include_private);
1036   
1037   list = string_list_strip_duplicates (dups_list);
1038
1039   g_slist_free (dups_list);
1040   
1041   retval = string_list_to_string (list);
1042
1043   g_slist_free (list);
1044   
1045   return retval;
1046 }
1047
1048 static char*
1049 get_multi_merged_from_back (GSList *pkgs, GetListFunc func,
1050                             gboolean in_path_order, gboolean include_private)
1051 {
1052   GSList *tmp;
1053   GSList *dups_list = NULL;
1054   GSList *list;
1055   char *retval;
1056
1057   fill_list (pkgs, func, &dups_list, in_path_order, include_private);
1058   
1059   list = string_list_strip_duplicates_from_back (dups_list);
1060
1061   g_slist_free (dups_list);
1062   
1063   retval = string_list_to_string (list);
1064
1065   g_slist_free (list);
1066   
1067   return retval;
1068 }
1069
1070 char *
1071 package_get_l_libs (Package *pkg)
1072 {
1073   /* We don't want these in search path order, rather in dependency
1074    * order, so static linking works.
1075    */
1076   if (pkg->l_libs_merged == NULL)
1077     pkg->l_libs_merged = get_merged_from_back (pkg, get_l_libs, FALSE,
1078                                                !ignore_private_libs);
1079
1080   return pkg->l_libs_merged;
1081 }
1082
1083 char *
1084 packages_get_l_libs (GSList     *pkgs)
1085 {
1086   return get_multi_merged_from_back (pkgs, get_l_libs, FALSE,
1087                                      !ignore_private_libs);
1088 }
1089
1090 char *
1091 package_get_L_libs (Package *pkg)
1092 {
1093   /* We want these in search path order so the -L flags don't override PKG_CONFIG_PATH */
1094   if (pkg->L_libs_merged == NULL)
1095     pkg->L_libs_merged = get_merged (pkg, get_L_libs, TRUE,
1096                                      !ignore_private_libs);
1097
1098   return pkg->L_libs_merged;
1099 }
1100
1101 char *
1102 packages_get_L_libs (GSList     *pkgs)
1103 {
1104   return get_multi_merged (pkgs, get_L_libs, TRUE, !ignore_private_libs);
1105 }
1106
1107 char *
1108 package_get_other_libs (Package *pkg)
1109 {
1110   if (pkg->other_libs_merged == NULL)
1111     pkg->other_libs_merged = get_merged (pkg, get_other_libs, TRUE,
1112                                          !ignore_private_libs);
1113
1114   return pkg->other_libs_merged;
1115 }
1116
1117 char *
1118 packages_get_other_libs (GSList   *pkgs)
1119 {
1120   return get_multi_merged (pkgs, get_other_libs, TRUE, !ignore_private_libs);
1121 }
1122
1123 char *
1124 packages_get_all_libs (GSList *pkgs)
1125 {
1126   char *l_libs;
1127   char *L_libs;
1128   char *other_libs;
1129   GString *str;
1130   char *retval;
1131   
1132   str = g_string_new ("");  
1133
1134   other_libs = packages_get_other_libs (pkgs);
1135   L_libs = packages_get_L_libs (pkgs);
1136   l_libs = packages_get_l_libs (pkgs);
1137
1138   if (other_libs)
1139     g_string_append (str, other_libs);
1140   
1141  if (L_libs)
1142     g_string_append (str, L_libs);
1143   
1144   if (l_libs)
1145     g_string_append (str, l_libs); 
1146
1147   g_free (l_libs);
1148   g_free (L_libs);
1149   g_free (other_libs);
1150
1151   retval = str->str;
1152
1153   g_string_free (str, FALSE);
1154
1155   return retval;
1156 }
1157
1158 char *
1159 package_get_I_cflags (Package *pkg)
1160 {
1161   /* sort by path position so PKG_CONFIG_PATH affects -I flag order */
1162   if (pkg->I_cflags_merged == NULL)
1163     pkg->I_cflags_merged = get_merged (pkg, get_I_cflags, TRUE, FALSE);
1164
1165   return pkg->I_cflags_merged;
1166 }
1167
1168 char *
1169 packages_get_I_cflags (GSList     *pkgs)
1170 {
1171   /* sort by path position so PKG_CONFIG_PATH affects -I flag order */
1172   return get_multi_merged (pkgs, get_I_cflags, TRUE, TRUE);
1173 }
1174
1175 char *
1176 package_get_other_cflags (Package *pkg)
1177 {
1178   if (pkg->other_cflags_merged == NULL)
1179     pkg->other_cflags_merged = get_merged (pkg, get_other_cflags, TRUE, TRUE);
1180
1181   return pkg->other_cflags_merged;
1182 }
1183
1184 char *
1185 packages_get_other_cflags (GSList *pkgs)
1186 {
1187   return get_multi_merged (pkgs, get_other_cflags, TRUE, TRUE);
1188 }
1189
1190 char *
1191 package_get_cflags (Package *pkg)
1192 {
1193
1194   g_assert_not_reached ();
1195   return NULL;
1196 }
1197
1198 char *
1199 packages_get_all_cflags (GSList     *pkgs)
1200 {
1201   char *I_cflags;
1202   char *other_cflags;
1203   GString *str;
1204   char *retval;
1205   
1206   str = g_string_new ("");  
1207
1208   other_cflags = packages_get_other_cflags (pkgs);
1209   I_cflags = packages_get_I_cflags (pkgs);
1210
1211   if (other_cflags)
1212     g_string_append (str, other_cflags);
1213   
1214  if (I_cflags)
1215     g_string_append (str, I_cflags);
1216
1217   g_free (I_cflags);
1218   g_free (other_cflags);
1219
1220   retval = str->str;
1221
1222   g_string_free (str, FALSE);
1223
1224   return retval;
1225 }
1226
1227
1228 void
1229 define_global_variable (const char *varname,
1230                         const char *varval)
1231 {
1232   if (globals == NULL)
1233     globals = g_hash_table_new (g_str_hash, g_str_equal);
1234
1235   if (g_hash_table_lookup (globals, varname))
1236     {
1237       verbose_error ("Variable '%s' defined twice globally\n", varname);
1238       exit (1);
1239     }
1240   
1241   g_hash_table_insert (globals, g_strdup (varname), g_strdup (varval));
1242       
1243   debug_spew ("Global variable definition '%s' = '%s'\n",
1244               varname, varval);
1245 }
1246
1247 char *
1248 package_get_var (Package *pkg,
1249                  const char *var)
1250 {
1251   char *varval = NULL;
1252
1253   if (globals)
1254     varval = g_strdup (g_hash_table_lookup (globals, var));
1255   
1256   if (varval == NULL && pkg->vars)
1257     varval = g_strdup (g_hash_table_lookup (pkg->vars, var));
1258
1259   /* Magic "pcfiledir" variable */
1260   if (varval == NULL && pkg->pcfiledir && strcmp (var, "pcfiledir") == 0)
1261     varval = g_strdup (pkg->pcfiledir);
1262
1263   return varval;
1264 }
1265
1266 char *
1267 packages_get_var (GSList     *pkgs,
1268                   const char *varname)
1269 {
1270   GSList *tmp;
1271   GString *str;
1272   char *retval;
1273   
1274   str = g_string_new ("");
1275   
1276   tmp = pkgs;
1277   while (tmp != NULL)
1278     {
1279       Package *pkg = tmp->data;
1280       char *var;
1281
1282       var = package_get_var (pkg, varname);
1283       
1284       if (var)
1285         {
1286           g_string_append (str, var);
1287           g_string_append_c (str, ' ');                
1288           g_free (var);
1289         }
1290
1291       tmp = g_slist_next (tmp);
1292     }
1293
1294   /* chop last space */
1295   if (str->len > 0)
1296       str->str[str->len - 1] = '\0';
1297   retval = str->str;
1298   g_string_free (str, FALSE);
1299
1300   return retval;
1301 }
1302
1303
1304
1305 /* Stolen verbatim from rpm/lib/misc.c 
1306    RPM is Copyright (c) 1998 by Red Hat Software, Inc.,
1307    and may be distributed under the terms of the GPL and LGPL.
1308 */
1309 /* compare alpha and numeric segments of two versions */
1310 /* return 1: a is newer than b */
1311 /*        0: a and b are the same version */
1312 /*       -1: b is newer than a */
1313 static int rpmvercmp(const char * a, const char * b) {
1314     char oldch1, oldch2;
1315     char * str1, * str2;
1316     char * one, * two;
1317     int rc;
1318     int isnum;
1319     
1320     /* easy comparison to see if versions are identical */
1321     if (!strcmp(a, b)) return 0;
1322
1323     str1 = alloca(strlen(a) + 1);
1324     str2 = alloca(strlen(b) + 1);
1325
1326     strcpy(str1, a);
1327     strcpy(str2, b);
1328
1329     one = str1;
1330     two = str2;
1331
1332     /* loop through each version segment of str1 and str2 and compare them */
1333     while (*one && *two) {
1334         while (*one && !isalnum((guchar)*one)) one++;
1335         while (*two && !isalnum((guchar)*two)) two++;
1336
1337         str1 = one;
1338         str2 = two;
1339
1340         /* grab first completely alpha or completely numeric segment */
1341         /* leave one and two pointing to the start of the alpha or numeric */
1342         /* segment and walk str1 and str2 to end of segment */
1343         if (isdigit((guchar)*str1)) {
1344             while (*str1 && isdigit((guchar)*str1)) str1++;
1345             while (*str2 && isdigit((guchar)*str2)) str2++;
1346             isnum = 1;
1347         } else {
1348             while (*str1 && isalpha((guchar)*str1)) str1++;
1349             while (*str2 && isalpha((guchar)*str2)) str2++;
1350             isnum = 0;
1351         }
1352                 
1353         /* save character at the end of the alpha or numeric segment */
1354         /* so that they can be restored after the comparison */
1355         oldch1 = *str1;
1356         *str1 = '\0';
1357         oldch2 = *str2;
1358         *str2 = '\0';
1359
1360         /* take care of the case where the two version segments are */
1361         /* different types: one numeric and one alpha */
1362         if (one == str1) return -1;     /* arbitrary */
1363         if (two == str2) return -1;
1364
1365         if (isnum) {
1366             /* this used to be done by converting the digit segments */
1367             /* to ints using atoi() - it's changed because long  */
1368             /* digit segments can overflow an int - this should fix that. */
1369           
1370             /* throw away any leading zeros - it's a number, right? */
1371             while (*one == '0') one++;
1372             while (*two == '0') two++;
1373
1374             /* whichever number has more digits wins */
1375             if (strlen(one) > strlen(two)) return 1;
1376             if (strlen(two) > strlen(one)) return -1;
1377         }
1378
1379         /* strcmp will return which one is greater - even if the two */
1380         /* segments are alpha or if they are numeric.  don't return  */
1381         /* if they are equal because there might be more segments to */
1382         /* compare */
1383         rc = strcmp(one, two);
1384         if (rc) return rc;
1385         
1386         /* restore character that was replaced by null above */
1387         *str1 = oldch1;
1388         one = str1;
1389         *str2 = oldch2;
1390         two = str2;
1391     }
1392
1393     /* this catches the case where all numeric and alpha segments have */
1394     /* compared identically but the segment sepparating characters were */
1395     /* different */
1396     if ((!*one) && (!*two)) return 0;
1397
1398     /* whichever version still has characters left over wins */
1399     if (!*one) return -1; else return 1;
1400 }
1401
1402 int
1403 compare_versions (const char * a, const char *b)
1404 {
1405   return rpmvercmp (a, b);
1406 }
1407
1408 gboolean
1409 version_test (ComparisonType comparison,
1410               const char *a,
1411               const char *b)
1412 {
1413   switch (comparison)
1414     {
1415     case LESS_THAN:
1416       return compare_versions (a, b) < 0;
1417       break;
1418
1419     case GREATER_THAN:
1420       return compare_versions (a, b) > 0;
1421       break;
1422
1423     case LESS_THAN_EQUAL:
1424       return compare_versions (a, b) <= 0;
1425       break;
1426
1427     case GREATER_THAN_EQUAL:
1428       return compare_versions (a, b) >= 0;
1429       break;
1430
1431     case EQUAL:
1432       return compare_versions (a, b) == 0;
1433       break;
1434
1435     case NOT_EQUAL:
1436       return compare_versions (a, b) != 0;
1437       break;
1438
1439     case ALWAYS_MATCH:
1440       return TRUE;
1441       break;
1442       
1443     default:
1444       g_assert_not_reached ();
1445       break;
1446     }
1447
1448   return FALSE;
1449 }
1450
1451 const char *
1452 comparison_to_str (ComparisonType comparison)
1453 {
1454   switch (comparison)
1455     {
1456     case LESS_THAN:
1457       return "<";
1458       break;
1459
1460     case GREATER_THAN:
1461       return ">";
1462       break;
1463
1464     case LESS_THAN_EQUAL:
1465       return "<=";
1466       break;
1467
1468     case GREATER_THAN_EQUAL:
1469       return ">=";
1470       break;
1471
1472     case EQUAL:
1473       return "=";
1474       break;
1475
1476     case NOT_EQUAL:
1477       return "!=";
1478       break;
1479
1480     case ALWAYS_MATCH:
1481       return "(any)";
1482       break;
1483       
1484     default:
1485       g_assert_not_reached ();
1486       break;
1487     }
1488
1489   return "???";
1490 }
1491
1492 static void
1493 max_len_foreach (gpointer key, gpointer value, gpointer data)
1494 {
1495   int *mlen = data;
1496
1497   *mlen = MAX (*mlen, strlen (key));
1498 }
1499
1500 static void
1501 packages_foreach (gpointer key, gpointer value, gpointer data)
1502 {
1503   Package *pkg = get_package (key);
1504
1505   if (pkg != NULL)
1506     {
1507       char *pad;
1508
1509       pad = g_strnfill (GPOINTER_TO_INT (data) - strlen (pkg->key), ' ');
1510       
1511       printf ("%s%s%s - %s\n",
1512               pkg->key, pad, pkg->name, pkg->description);
1513
1514       g_free (pad);
1515     }
1516 }
1517
1518 void
1519 print_package_list (void)
1520 {
1521   int mlen = 0;
1522
1523   ignore_requires = TRUE;
1524   ignore_requires_private = TRUE;
1525
1526   g_hash_table_foreach (locations, max_len_foreach, &mlen);
1527   g_hash_table_foreach (locations, packages_foreach, GINT_TO_POINTER (mlen + 1));
1528 }
1529
1530 void
1531 enable_private_libs(void)
1532 {
1533   ignore_private_libs = FALSE;
1534 }
1535
1536 void
1537 disable_private_libs(void)
1538 {
1539   ignore_private_libs = TRUE;
1540 }
1541
1542 void
1543 enable_requires(void)
1544 {
1545   ignore_requires = FALSE;
1546 }
1547
1548 void
1549 disable_requires(void)
1550 {
1551   ignore_requires = TRUE;
1552 }
1553
1554 void
1555 enable_requires_private(void)
1556 {
1557   ignore_requires_private = FALSE;
1558 }
1559
1560 void
1561 disable_requires_private(void)
1562 {
1563   ignore_requires_private = TRUE;
1564 }