Imported Upstream version 0.27.1
[platform/upstream/pkg-config.git] / parse.c
1 /* 
2  * Copyright (C) 2006-2011 Tollef Fog Heen <tfheen@err.no>
3  * Copyright (C) 2001, 2002, 2005-2006 Red Hat Inc.
4  * Copyright (C) 2010 Dan Nicholson <dbn.lists@gmail.com>
5  * 
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19  * 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "parse.h"
27 #include <stdio.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #ifdef HAVE_SYS_WAIT_H
33 #include <sys/wait.h>
34 #endif
35 #include <sys/types.h>
36
37 #ifdef G_OS_WIN32
38 int dont_define_prefix = FALSE;
39 char *prefix_variable = "prefix";
40 int msvc_syntax = FALSE;
41 #endif
42
43 #ifdef G_OS_WIN32
44 #ifndef G_IS_DIR_SEPARATOR
45 #define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/')
46 #endif
47 #endif
48
49 /**
50  * Read an entire line from a file into a buffer. Lines may
51  * be delimited with '\n', '\r', '\n\r', or '\r\n'. The delimiter
52  * is not written into the buffer. Text after a '#' character is treated as
53  * a comment and skipped. '\' can be used to escape a # character.
54  * '\' proceding a line delimiter combines adjacent lines. A '\' proceding
55  * any other character is ignored and written into the output buffer
56  * unmodified.
57  * 
58  * Return value: %FALSE if the stream was already at an EOF character.
59  **/
60 static gboolean
61 read_one_line (FILE *stream, GString *str)
62 {
63   gboolean quoted = FALSE;
64   gboolean comment = FALSE;
65   int n_read = 0;
66
67   g_string_truncate (str, 0);
68   
69   while (1)
70     {
71       int c;
72       
73       c = getc (stream);
74
75       if (c == EOF)
76         {
77           if (quoted)
78             g_string_append_c (str, '\\');
79           
80           goto done;
81         }
82       else
83         n_read++;
84
85       if (quoted)
86         {
87           quoted = FALSE;
88           
89           switch (c)
90             {
91             case '#':
92               g_string_append_c (str, '#');
93               break;
94             case '\r':
95             case '\n':
96               {
97                 int next_c = getc (stream);
98
99                 if (!(c == EOF ||
100                       (c == '\r' && next_c == '\n') ||
101                       (c == '\n' && next_c == '\r')))
102                   ungetc (next_c, stream);
103                 
104                 break;
105               }
106             default:
107               g_string_append_c (str, '\\');          
108               g_string_append_c (str, c);
109             }
110         }
111       else
112         {
113           switch (c)
114             {
115             case '#':
116               comment = TRUE;
117               break;
118             case '\\':
119               if (!comment)
120                 quoted = TRUE;
121               break;
122             case '\n':
123               {
124                 int next_c = getc (stream);
125
126                 if (!(c == EOF ||
127                       (c == '\r' && next_c == '\n') ||
128                       (c == '\n' && next_c == '\r')))
129                   ungetc (next_c, stream);
130
131                 goto done;
132               }
133             default:
134               if (!comment)
135                 g_string_append_c (str, c);
136             }
137         }
138     }
139
140  done:
141
142   return n_read > 0;
143 }
144
145 static char *
146 trim_string (const char *str)
147 {
148   int len;
149
150   g_return_val_if_fail (str != NULL, NULL);
151   
152   while (*str && isspace ((guchar)*str))
153     str++;
154
155   len = strlen (str);
156   while (len > 0 && isspace ((guchar)str[len-1]))
157     len--;
158
159   return g_strndup (str, len);
160 }
161
162 static char *
163 trim_and_sub (Package *pkg, const char *str, const char *path)
164 {
165   char *trimmed;
166   GString *subst;
167   char *p;
168   
169   trimmed = trim_string (str);
170
171   subst = g_string_new ("");
172
173   p = trimmed;
174   while (*p)
175     {
176       if (p[0] == '$' &&
177           p[1] == '$')
178         {
179           /* escaped $ */
180           g_string_append_c (subst, '$');
181           p += 2;
182         }
183       else if (p[0] == '$' &&
184                p[1] == '{')
185         {
186           /* variable */
187           char *var_start;
188           char *varname;
189           char *varval;
190           
191           var_start = &p[2];
192
193           /* Get up to close brace. */
194           while (*p && *p != '}')
195             ++p;
196
197           varname = g_strndup (var_start, p - var_start);
198
199           ++p; /* past brace */
200           
201           varval = package_get_var (pkg, varname);
202           
203           if (varval == NULL)
204             {
205               verbose_error ("Variable '%s' not defined in '%s'\n",
206                              varname, path);
207               
208               exit (1);
209             }
210
211           g_free (varname);
212
213           g_string_append (subst, varval);
214           g_free (varval);
215         }
216       else
217         {
218           g_string_append_c (subst, *p);
219
220           ++p;          
221         }
222     }
223
224   g_free (trimmed);
225   p = subst->str;
226   g_string_free (subst, FALSE);
227
228   return p;
229 }
230
231 static void
232 parse_name (Package *pkg, const char *str, const char *path)
233 {
234   if (pkg->name)
235     {
236       verbose_error ("Name field occurs twice in '%s'\n", path);
237
238       exit (1);
239     }
240   
241   pkg->name = trim_and_sub (pkg, str, path);
242 }
243
244 static void
245 parse_version (Package *pkg, const char *str, const char *path)
246 {
247   if (pkg->version)
248     {
249       verbose_error ("Version field occurs twice in '%s'\n", path);
250
251       exit (1);
252     }
253   
254   pkg->version = trim_and_sub (pkg, str, path);
255 }
256
257 static void
258 parse_description (Package *pkg, const char *str, const char *path)
259 {
260   if (pkg->description)
261     {
262       verbose_error ("Description field occurs twice in '%s'\n", path);
263
264       exit (1);
265     }
266   
267   pkg->description = trim_and_sub (pkg, str, path);
268 }
269
270
271 #define MODULE_SEPARATOR(c) ((c) == ',' || isspace ((guchar)(c)))
272 #define OPERATOR_CHAR(c) ((c) == '<' || (c) == '>' || (c) == '!' || (c) == '=')
273
274 /* A module list is a list of modules with optional version specification,
275  * separated by commas and/or spaces. Commas are treated just like whitespace,
276  * in order to allow stuff like: Requires: @FRIBIDI_PC@, glib, gmodule
277  * where @FRIBIDI_PC@ gets substituted to nothing or to 'fribidi'
278  */
279
280 typedef enum
281 {
282   /* put numbers to help interpret lame debug spew ;-) */
283   OUTSIDE_MODULE = 0,
284   IN_MODULE_NAME = 1,
285   BEFORE_OPERATOR = 2,
286   IN_OPERATOR = 3,
287   AFTER_OPERATOR = 4,
288   IN_MODULE_VERSION = 5  
289 } ModuleSplitState;
290
291 #define PARSE_SPEW 0
292
293 static GSList*
294 split_module_list (const char *str, const char *path)
295 {
296   GSList *retval = NULL;
297   const char *p;
298   const char *start;
299   ModuleSplitState state = OUTSIDE_MODULE;
300   ModuleSplitState last_state = OUTSIDE_MODULE;
301
302   /*   fprintf (stderr, "Parsing: '%s'\n", str); */
303   
304   start = str;
305   p = str;
306
307   while (*p)
308     {
309 #if PARSE_SPEW
310       fprintf (stderr, "p: %c state: %d last_state: %d\n", *p, state, last_state);
311 #endif
312       
313       switch (state)
314         {
315         case OUTSIDE_MODULE:
316           if (!MODULE_SEPARATOR (*p))
317             state = IN_MODULE_NAME;          
318           break;
319
320         case IN_MODULE_NAME:
321           if (isspace ((guchar)*p))
322             {
323               /* Need to look ahead to determine next state */
324               const char *s = p;
325               while (*s && isspace ((guchar)*s))
326                 ++s;
327
328               if (*s == '\0')
329                 state = OUTSIDE_MODULE;
330               else if (MODULE_SEPARATOR (*s))
331                 state = OUTSIDE_MODULE;
332               else if (OPERATOR_CHAR (*s))
333                 state = BEFORE_OPERATOR;
334               else
335                 state = OUTSIDE_MODULE;
336             }
337           else if (MODULE_SEPARATOR (*p))
338             state = OUTSIDE_MODULE; /* comma precludes any operators */
339           break;
340
341         case BEFORE_OPERATOR:
342           /* We know an operator is coming up here due to lookahead from
343            * IN_MODULE_NAME
344            */
345           if (isspace ((guchar)*p))
346             ; /* no change */
347           else if (OPERATOR_CHAR (*p))
348             state = IN_OPERATOR;
349           else
350             g_assert_not_reached ();
351           break;
352
353         case IN_OPERATOR:
354           if (!OPERATOR_CHAR (*p))
355             state = AFTER_OPERATOR;
356           break;
357
358         case AFTER_OPERATOR:
359           if (!isspace ((guchar)*p))
360             state = IN_MODULE_VERSION;
361           break;
362
363         case IN_MODULE_VERSION:
364           if (MODULE_SEPARATOR (*p))
365             state = OUTSIDE_MODULE;
366           break;
367           
368         default:
369           g_assert_not_reached ();
370         }
371
372       if (state == OUTSIDE_MODULE &&
373           last_state != OUTSIDE_MODULE)
374         {
375           /* We left a module */
376           char *module = g_strndup (start, p - start);
377           retval = g_slist_prepend (retval, module);
378
379 #if PARSE_SPEW
380           fprintf (stderr, "found module: '%s'\n", module);
381 #endif
382           
383           /* reset start */
384           start = p;
385         }
386       
387       last_state = state;
388       ++p;
389     }
390
391   if (p != start)
392     {
393       /* get the last module */
394       char *module = g_strndup (start, p - start);
395       retval = g_slist_prepend (retval, module);
396
397 #if PARSE_SPEW
398       fprintf (stderr, "found module: '%s'\n", module);
399 #endif
400       
401     }
402   
403   retval = g_slist_reverse (retval);
404
405   return retval;
406 }
407
408 GSList*
409 parse_module_list (Package *pkg, const char *str, const char *path)
410 {
411   GSList *split;
412   GSList *iter;
413   GSList *retval = NULL;
414
415   split = split_module_list (str, path);
416   
417   iter = split;
418   while (iter != NULL)
419     {
420       RequiredVersion *ver;
421       char *p;
422       char *start;
423       
424       p = iter->data;
425
426       ver = g_new0 (RequiredVersion, 1);
427       ver->comparison = ALWAYS_MATCH;
428       ver->owner = pkg;
429       retval = g_slist_prepend (retval, ver);
430       
431       while (*p && MODULE_SEPARATOR (*p))
432         ++p;
433       
434       start = p;
435
436       while (*p && !isspace ((guchar)*p))
437         ++p;
438
439       while (*p && MODULE_SEPARATOR (*p))
440         {
441           *p = '\0';
442           ++p;
443         }
444
445       if (*start == '\0')
446         {
447           verbose_error ("Empty package name in Requires or Conflicts in file '%s'\n", path);
448           
449           exit (1);
450         }
451       
452       ver->name = g_strdup (start);
453
454       start = p;
455
456       while (*p && !isspace ((guchar)*p))
457         ++p;
458
459       while (*p && isspace ((guchar)*p))
460         {
461           *p = '\0';
462           ++p;
463         }
464       
465       if (*start != '\0')
466         {
467           if (strcmp (start, "=") == 0)
468             ver->comparison = EQUAL;
469           else if (strcmp (start, ">=") == 0)
470             ver->comparison = GREATER_THAN_EQUAL;
471           else if (strcmp (start, "<=") == 0)
472             ver->comparison = LESS_THAN_EQUAL;
473           else if (strcmp (start, ">") == 0)
474             ver->comparison = GREATER_THAN;
475           else if (strcmp (start, "<") == 0)
476             ver->comparison = LESS_THAN;
477           else if (strcmp (start, "!=") == 0)
478             ver->comparison = NOT_EQUAL;
479           else
480             {
481               verbose_error ("Unknown version comparison operator '%s' after package name '%s' in file '%s'\n", start, ver->name, path);
482               
483               exit (1);
484             }
485         }
486
487       start = p;
488       
489       while (*p && !MODULE_SEPARATOR (*p))
490         ++p;
491
492       while (*p && MODULE_SEPARATOR (*p))
493         {
494           *p = '\0';
495           ++p;
496         }
497       
498       if (ver->comparison != ALWAYS_MATCH && *start == '\0')
499         {
500           verbose_error ("Comparison operator but no version after package name '%s' in file '%s'\n", ver->name, path);
501           
502           exit (1);
503         }
504
505       if (*start != '\0')
506         {
507           ver->version = g_strdup (start);
508         }
509
510       g_assert (ver->name);
511       
512       iter = g_slist_next (iter);
513     }
514
515   g_slist_foreach (split, (GFunc) g_free, NULL);
516   g_slist_free (split);
517
518   retval = g_slist_reverse (retval);
519
520   return retval;
521 }
522
523 static void
524 parse_requires (Package *pkg, const char *str, const char *path)
525 {
526   GSList *parsed;
527   GSList *iter;
528   char *trimmed;
529   
530   if (pkg->requires)
531     {
532       verbose_error ("Requires field occurs twice in '%s'\n", path);
533
534       exit (1);
535     }
536
537   trimmed = trim_and_sub (pkg, str, path);
538   parsed = parse_module_list (pkg, trimmed, path);
539   g_free (trimmed);
540   
541   iter = parsed;
542   while (iter != NULL)
543     {
544       Package *req;
545       RequiredVersion *ver = iter->data;
546       
547       req = get_package (ver->name);
548
549       if (req == NULL)
550         {
551           verbose_error ("Package '%s', required by '%s', not found\n",
552                          ver->name, pkg->name ? pkg->name : path);
553           
554           exit (1);
555         }
556
557       if (pkg->required_versions == NULL)
558         pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal);
559       
560       g_hash_table_insert (pkg->required_versions, ver->name, ver);
561       
562       pkg->requires = g_slist_prepend (pkg->requires, req);
563
564       iter = g_slist_next (iter);
565     }
566
567   g_slist_free (parsed);
568 }
569
570 static void
571 parse_requires_private (Package *pkg, const char *str, const char *path)
572 {
573   GSList *parsed;
574   GSList *iter;
575   char *trimmed;
576   
577   if (pkg->requires_private)
578     {
579       verbose_error ("Requires.private field occurs twice in '%s'\n", path);
580
581       exit (1);
582     }
583
584   trimmed = trim_and_sub (pkg, str, path);
585   parsed = parse_module_list (pkg, trimmed, path);
586   g_free (trimmed);
587   
588   iter = parsed;
589   while (iter != NULL)
590     {
591       Package *req;
592       RequiredVersion *ver = iter->data;
593       
594       req = get_package (ver->name);
595
596       if (req == NULL)
597         {
598           verbose_error ("Package '%s', required by '%s', not found\n",
599                          ver->name, pkg->name ? pkg->name : path);
600           
601           exit (1);
602         }
603
604       if (pkg->required_versions == NULL)
605         pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal);
606       
607       g_hash_table_insert (pkg->required_versions, ver->name, ver);
608       
609       pkg->requires_private = g_slist_prepend (pkg->requires_private, req);
610
611       iter = g_slist_next (iter);
612     }
613
614   g_slist_free (parsed);
615 }
616
617 static void
618 parse_conflicts (Package *pkg, const char *str, const char *path)
619 {
620   char *trimmed;
621   
622   if (pkg->conflicts)
623     {
624       verbose_error ("Conflicts field occurs twice in '%s'\n", path);
625
626       exit (1);
627     }
628
629   trimmed = trim_and_sub (pkg, str, path);
630   pkg->conflicts = parse_module_list (pkg, trimmed, path);
631   g_free (trimmed);
632 }
633
634 static char *strdup_escape_shell(const char *s)
635 {
636         size_t r_s = strlen(s)+10, c = 0;
637         char *r = g_malloc(r_s);
638         while (s[0]) {
639                 if ((s[0] < '$') ||
640                     (s[0] > '$' && s[0] < '(') ||
641                     (s[0] > ')' && s[0] < '+') ||
642                     (s[0] > ':' && s[0] < '=') ||
643                     (s[0] > '=' && s[0] < '@') ||
644                     (s[0] > 'Z' && s[0] < '^') ||
645                     (s[0] == '`') ||
646                     (s[0] > 'z')) {
647                         r[c] = '\\';
648                         c++;
649                 }
650                 r[c] = *s;
651                 c++;
652                 if (c+2 >= r_s) {
653                         r_s *= 2;
654                         r = g_realloc(r, r_s);
655                 }
656                 s++;
657         }
658         r[c] = 0;
659         return r;
660 }
661
662 static void _do_parse_libs (Package *pkg, int argc, char **argv)
663 {
664   int i;
665 #ifdef G_OS_WIN32
666   char *L_flag = (msvc_syntax ? "/libpath:" : "-L");
667   char *l_flag = (msvc_syntax ? "" : "-l");
668   char *lib_suffix = (msvc_syntax ? ".lib" : "");
669 #else
670   char *L_flag = "-L";
671   char *l_flag = "-l";
672   char *lib_suffix = "";
673 #endif
674
675   i = 0;
676   while (i < argc)
677     {
678       char *tmp = trim_string (argv[i]);
679       char *arg = strdup_escape_shell(tmp);
680       char *p;
681       p = arg;
682       g_free(tmp);
683
684       if (p[0] == '-' &&
685           p[1] == 'l' &&
686           /* -lib: is used by the C# compiler for libs; it's not an -l
687               flag. */
688           (strncmp(p, "-lib:", 5) != 0))
689         {
690           p += 2;
691           while (*p && isspace ((guchar)*p))
692             ++p;
693
694           pkg->l_libs = g_slist_prepend (pkg->l_libs,
695                                          g_strconcat (l_flag, p, lib_suffix, NULL));
696
697         }
698       else if (p[0] == '-' &&
699                p[1] == 'L')
700         {
701           p += 2;
702           while (*p && isspace ((guchar)*p))
703             ++p;
704           pkg->L_libs = g_slist_prepend (pkg->L_libs,
705                                          g_strconcat (L_flag, p, NULL));
706         }
707       else if (strcmp("-framework",p) == 0 && i+1 < argc)
708         {
709           /* Mac OS X has a -framework Foo which is really one option,
710            * so we join those to avoid having -framework Foo
711            * -framework Bar being changed into -framework Foo Bar
712            * later
713           */
714           gchar *framework, *tmp = trim_string (argv[i+1]);
715
716           framework = strdup_escape_shell(tmp);
717           pkg->other_libs = g_slist_prepend (pkg->other_libs,
718                                              g_strconcat(arg, " ", framework, NULL));
719           i++;
720           g_free(framework);
721           g_free(tmp);
722         }
723       else
724         {
725           if (*arg != '\0')
726             pkg->other_libs = g_slist_prepend (pkg->other_libs,
727                                                g_strdup (arg));
728         }
729
730       g_free (arg);
731
732       ++i;
733     }
734
735 }
736
737
738 static void
739 parse_libs (Package *pkg, const char *str, const char *path)
740 {
741   /* Strip out -l and -L flags, put them in a separate list. */
742   
743   char *trimmed;
744   char **argv = NULL;
745   int argc = 0;
746   GError *error = NULL;
747   
748   if (pkg->libs_num > 0)
749     {
750       verbose_error ("Libs field occurs twice in '%s'\n", path);
751
752       exit (1);
753     }
754   
755   trimmed = trim_and_sub (pkg, str, path);
756
757   if (trimmed && *trimmed &&
758       !g_shell_parse_argv (trimmed, &argc, &argv, &error))
759     {
760       verbose_error ("Couldn't parse Libs field into an argument vector: %s\n",
761                      error ? error->message : "unknown");
762       exit (1);
763     }
764
765   _do_parse_libs(pkg, argc, argv);
766
767   g_free (trimmed);
768   g_strfreev (argv);
769   pkg->libs_num++;
770 }
771
772 static void
773 parse_libs_private (Package *pkg, const char *str, const char *path)
774 {
775   /*
776     List of private libraries.  Private libraries are libraries which
777     are needed in the case of static linking or on platforms not
778     supporting inter-library dependencies.  They are not supposed to
779     be used for libraries which are exposed through the library in
780     question.  An example of an exposed library is GTK+ exposing Glib.
781     A common example of a private library is libm.
782     
783     Generally, if include another library's headers in your own, it's
784     a public dependency and not a private one.
785   */
786   
787   char *trimmed;
788   char **argv = NULL;
789   int argc = 0;
790   GError *error = NULL;
791   
792   if (pkg->libs_private_num > 0)
793     {
794       verbose_error ("Libs.private field occurs twice in '%s'\n", path);
795
796       exit (1);
797     }
798   
799   trimmed = trim_and_sub (pkg, str, path);
800
801   if (trimmed && *trimmed &&
802       !g_shell_parse_argv (trimmed, &argc, &argv, &error))
803     {
804       verbose_error ("Couldn't parse Libs.private field into an argument vector: %s\n",
805                      error ? error->message : "unknown");
806       exit (1);
807     }
808
809   _do_parse_libs(pkg, argc, argv);
810
811   g_strfreev (argv);
812   g_free (trimmed);
813
814   pkg->libs_private_num++;
815 }
816
817 static void
818 parse_cflags (Package *pkg, const char *str, const char *path)
819 {
820   /* Strip out -I flags, put them in a separate list. */
821   
822   char *trimmed;
823   char **argv = NULL;
824   int argc = 0;
825   GError *error = NULL;
826   int i;
827   
828   if (pkg->I_cflags || pkg->other_cflags)
829     {
830       verbose_error ("Cflags field occurs twice in '%s'\n", path);
831
832       exit (1);
833     }
834   
835   trimmed = trim_and_sub (pkg, str, path);
836
837   if (trimmed && *trimmed &&
838       !g_shell_parse_argv (trimmed, &argc, &argv, &error))
839     {
840       verbose_error ("Couldn't parse Cflags field into an argument vector: %s\n",
841                      error ? error->message : "unknown");
842       exit (1);
843     }
844
845   i = 0;
846   while (i < argc)
847     {
848       char *tmp = trim_string (argv[i]);
849       char *arg = strdup_escape_shell(tmp);
850       char *p = arg;
851       g_free(tmp);
852
853       if (p[0] == '-' &&
854           p[1] == 'I')
855         {
856           p += 2;
857           while (*p && isspace ((guchar)*p))
858             ++p;
859
860           pkg->I_cflags = g_slist_prepend (pkg->I_cflags,
861                                            g_strconcat ("-I", p, NULL));
862
863         } else {
864           if (*arg != '\0')
865             pkg->other_cflags = g_slist_prepend (pkg->other_cflags,
866                                                  g_strdup (arg));
867           if (strcmp("-idirafter", arg) == 0) {
868               char *n;
869
870               tmp = trim_string(argv[++i]);
871               n = strdup_escape_shell(tmp);
872               pkg->other_cflags = g_slist_prepend(pkg->other_cflags, n);
873               g_free(tmp);
874           }
875       }
876
877       g_free (arg);
878       
879       ++i;
880     }
881
882   g_strfreev (argv);
883   g_free (trimmed);
884 }
885
886 static void
887 parse_url (Package *pkg, const char *str, const char *path)
888 {
889   if (pkg->url != NULL)
890     {
891       verbose_error ("URL field occurs twice in '%s'\n", path);
892
893       exit (1);
894     }
895
896   pkg->url = trim_and_sub (pkg, str, path);
897 }
898
899 #ifdef G_OS_WIN32
900 static char *orig_prefix = NULL;
901
902 static int
903 pathnamecmp (const char *a,
904              const char *b)
905 {
906   while (*a && *b &&
907          ((G_IS_DIR_SEPARATOR (*a) && G_IS_DIR_SEPARATOR (*b)) ||
908           g_ascii_toupper (*a) == g_ascii_toupper (*b)))
909     {
910       a++;
911       b++;
912     }
913   return g_ascii_toupper (*a) - g_ascii_toupper (*b);
914 }
915 #endif
916
917 static void
918 parse_line (Package *pkg, const char *untrimmed, const char *path,
919             gboolean ignore_requires, gboolean ignore_private_libs,
920             gboolean ignore_requires_private)
921 {
922   char *str;
923   char *p;
924   char *tag;
925
926   debug_spew ("  line>%s\n", untrimmed);
927   
928   str = trim_string (untrimmed);
929   
930   if (*str == '\0') /* empty line */
931     {
932       g_free(str);
933       return;
934     }
935   
936   p = str;
937
938   /* Get first word */
939   while ((*p >= 'A' && *p <= 'Z') ||
940          (*p >= 'a' && *p <= 'z') ||
941          (*p >= '0' && *p <= '9') ||
942          *p == '_' || *p == '.')
943     p++;
944
945   tag = g_strndup (str, p - str);
946   
947   while (*p && isspace ((guchar)*p))
948     ++p;
949
950   if (*p == ':')
951     {
952       /* keyword */
953       ++p;
954       while (*p && isspace ((guchar)*p))
955         ++p;
956
957       if (strcmp (tag, "Name") == 0)
958         parse_name (pkg, p, path);
959       else if (strcmp (tag, "Description") == 0)
960         parse_description (pkg, p, path);
961       else if (strcmp (tag, "Version") == 0)
962         parse_version (pkg, p, path);
963       else if (strcmp (tag, "Requires.private") == 0)
964         {
965           if (!ignore_requires_private)
966             parse_requires_private (pkg, p, path);
967         }
968       else if (strcmp (tag, "Requires") == 0)
969         {
970           if (ignore_requires == FALSE)
971             parse_requires (pkg, p, path);
972           else
973             goto cleanup;
974         }
975       else if ((strcmp (tag, "Libs.private") == 0) && 
976                ignore_private_libs == FALSE)
977         parse_libs_private (pkg, p, path);
978       else if (strcmp (tag, "Libs") == 0)
979         parse_libs (pkg, p, path);
980       else if (strcmp (tag, "Cflags") == 0 ||
981                strcmp (tag, "CFlags") == 0)
982         parse_cflags (pkg, p, path);
983       else if (strcmp (tag, "Conflicts") == 0)
984         parse_conflicts (pkg, p, path);
985       else if (strcmp (tag, "URL") == 0)
986         parse_url (pkg, p, path);
987       else
988         {
989           /* we don't error out on unknown keywords because they may
990            * represent additions to the .pc file format from future
991            * versions of pkg-config.  We do make a note of them in the
992            * debug spew though, in order to help catch mistakes in .pc
993            * files. */
994           debug_spew ("Unknown keyword '%s' in '%s'\n",
995                       tag, path);
996         }
997     }
998   else if (*p == '=')
999     {
1000       /* variable */
1001       char *varname;
1002       char *varval;
1003       
1004       ++p;
1005       while (*p && isspace ((guchar)*p))
1006         ++p;
1007       
1008       if (pkg->vars == NULL)
1009         pkg->vars = g_hash_table_new (g_str_hash, g_str_equal);
1010
1011 #ifdef G_OS_WIN32
1012       if (!dont_define_prefix && strcmp (tag, prefix_variable) == 0)
1013         {
1014           /* This is the prefix variable. Try to guesstimate a value for it
1015            * for this package from the location of the .pc file.
1016            */
1017
1018           gchar *prefix = pkg->pcfiledir;
1019           const int prefix_len = strlen (prefix);
1020           const char *const lib_pkgconfig = "\\lib\\pkgconfig";
1021           const char *const share_pkgconfig = "\\share\\pkgconfig";
1022           const int lib_pkgconfig_len = strlen (lib_pkgconfig);
1023           const int share_pkgconfig_len = strlen (share_pkgconfig);
1024
1025           if ((strlen (prefix) > lib_pkgconfig_len &&
1026                pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0) ||
1027               (strlen (prefix) > share_pkgconfig_len &&
1028                pathnamecmp (prefix + prefix_len - share_pkgconfig_len, share_pkgconfig) == 0))
1029             {
1030               /* It ends in lib\pkgconfig or share\pkgconfig. Good. */
1031               
1032               gchar *q;
1033               
1034               orig_prefix = g_strdup (p);
1035
1036               prefix = g_strdup (prefix);
1037               if (strlen (prefix) > lib_pkgconfig_len &&
1038                   pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0)
1039                 prefix[prefix_len - lib_pkgconfig_len] = '\0';
1040               else
1041                 prefix[prefix_len - share_pkgconfig_len] = '\0';
1042               
1043               /* Turn backslashes into slashes or
1044                * g_shell_parse_argv() will eat them when ${prefix}
1045                * has been expanded in parse_libs().
1046                */
1047               q = prefix;
1048               while (*q)
1049                 {
1050                   if (*q == '\\')
1051                     *q = '/';
1052                   q++;
1053                 }
1054
1055               /* Now escape the special characters so that there's no danger
1056                * of arguments that include the prefix getting split.
1057                */
1058               q = prefix;
1059               prefix = strdup_escape_shell (prefix);
1060               g_free (q);
1061
1062               varname = g_strdup (tag);
1063               debug_spew (" Variable declaration, '%s' overridden with '%s'\n",
1064                           tag, prefix);
1065               g_hash_table_insert (pkg->vars, varname, prefix);
1066               goto cleanup;
1067             }
1068         }
1069       else if (!dont_define_prefix &&
1070                orig_prefix != NULL &&
1071                strncmp (p, orig_prefix, strlen (orig_prefix)) == 0 &&
1072                G_IS_DIR_SEPARATOR (p[strlen (orig_prefix)]))
1073         {
1074           char *oldstr = str;
1075
1076           p = str = g_strconcat (g_hash_table_lookup (pkg->vars, prefix_variable), p + strlen (orig_prefix), NULL);
1077           g_free (oldstr);
1078         }
1079 #endif
1080
1081       if (g_hash_table_lookup (pkg->vars, tag))
1082         {
1083           verbose_error ("Duplicate definition of variable '%s' in '%s'\n",
1084                          tag, path);
1085
1086           exit (1);
1087         }
1088
1089       varname = g_strdup (tag);
1090       varval = trim_and_sub (pkg, p, path);     
1091
1092       debug_spew (" Variable declaration, '%s' has value '%s'\n",
1093                   varname, varval);
1094       g_hash_table_insert (pkg->vars, varname, varval);
1095   
1096     }
1097
1098  cleanup:  
1099   g_free (str);
1100   g_free (tag);
1101 }
1102
1103 Package*
1104 parse_package_file (const char *path, gboolean ignore_requires,
1105                     gboolean ignore_private_libs,
1106                     gboolean ignore_requires_private)
1107 {
1108   FILE *f;
1109   Package *pkg;
1110   GString *str;
1111   gboolean one_line = FALSE;
1112   
1113   f = fopen (path, "r");
1114
1115   if (f == NULL)
1116     {
1117       verbose_error ("Failed to open '%s': %s\n",
1118                      path, strerror (errno));
1119       
1120       return NULL;
1121     }
1122
1123   debug_spew ("Parsing package file '%s'\n", path);
1124   
1125   pkg = g_new0 (Package, 1);
1126
1127   if (path)
1128     {
1129       pkg->pcfiledir = g_dirname (path);
1130     }
1131   else
1132     {
1133       debug_spew ("No pcfiledir determined for package\n");
1134       pkg->pcfiledir = g_strdup ("???????");
1135     }
1136   
1137   str = g_string_new ("");
1138
1139   while (read_one_line (f, str))
1140     {
1141       one_line = TRUE;
1142       
1143       parse_line (pkg, str->str, path, ignore_requires, ignore_private_libs,
1144                   ignore_requires_private);
1145
1146       g_string_truncate (str, 0);
1147     }
1148
1149   if (!one_line)
1150     verbose_error ("Package file '%s' appears to be empty\n",
1151                    path);
1152   g_string_free (str, TRUE);
1153   fclose(f);
1154
1155   /* make ->requires_private include a copy of the public requires too */
1156   pkg->requires_private = g_slist_concat(g_slist_copy (pkg->requires),
1157                                          pkg->requires_private);
1158   
1159   pkg->requires = g_slist_reverse (pkg->requires);
1160   
1161   pkg->requires_private = g_slist_reverse (pkg->requires_private);
1162
1163   pkg->I_cflags = g_slist_reverse (pkg->I_cflags);
1164   pkg->other_cflags = g_slist_reverse (pkg->other_cflags);
1165
1166   pkg->l_libs = g_slist_reverse (pkg->l_libs);
1167   pkg->L_libs = g_slist_reverse (pkg->L_libs);
1168   pkg->other_libs = g_slist_reverse (pkg->other_libs);
1169   
1170   return pkg;
1171 }