2005-07-14 13:05:14 +00:00
|
|
|
/*
|
2011-04-13 20:29:22 +02:00
|
|
|
* Copyright (C) 2006-2011 Tollef Fog Heen <tfheen@err.no>
|
2006-08-16 20:47:14 +02:00
|
|
|
* Copyright (C) 2001, 2002, 2005-2006 Red Hat Inc.
|
2010-06-13 20:23:45 -07:00
|
|
|
* Copyright (C) 2010 Dan Nicholson <dbn.lists@gmail.com>
|
2005-07-14 13:05:14 +00:00
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
|
* 02111-1307, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
2005-07-14 13:04:01 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "parse.h"
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <ctype.h>
|
2001-09-30 Tor Lillqvist <tml@iki.fi>
Author: tml
Date: 2001-09-29 21:05:25 GMT
2001-09-30 Tor Lillqvist <tml@iki.fi>
Changes for "pure" Win32 (without Cygwin or similar)
support. The most important differences compared to pkg-config
on Unix are:
We don't use hardcoded PKGLIBDIR paths but deduce the
installation prefix at runtime.
Use the normal GLib DLL, not a private copy. Yes, this does
introduce a circular dependency, but that can be worked around.
* README.win32: New file.
* configure.in: Check for Win32. If so, define USE_INSTALLED_GLIB,
and don't configure in the included glib-1.2.8. Set GLIB_CFLAGS
and GLIB_LIBS assuming that GLib is installed in the same location
pkgconfig will be. Check for dirent.h, unistd.h and sys/wait.h
headers.
* Makefile.am: If USE_INSTALLED_GLIB, use the GLIB_* values set
above, and don't make in the glib-1.2.8 subdir.
* autogen.sh: Use perl -p -i.bak, works better on Win32 (and Cygwin).
* *.c: Conditionalize inclusions of unistd.h and sys/wait.h.
* findme.c: Define X_OK on Win32 if necessary.
* parse.c
* popthelp.c: Minor Win32 portability ifdefs.
* parse.c: No need to include <windows.h>.
* pkg.c: Don't hardcode PKGLIBDIR, but use
g_win32_get_package_installation_directory() to deduce it.
(scan_dir): Make a temp copy of dirname with potential superfluous
trailing slash removed. The Win32 opendir implementation doesn't
always like those.
* pkg.h: If USE_INSTALLED_GLIB, include <glib.h> instead of
partial-glib.h.
* popt.c (execCommand): Don't compile on Win32.
* poptconfig.c (configLine): Don't bother with the "exec" stuff on
Win32, too complex to port, at least for now.
(poptReadDefaultConfig) Don't bother compiling on Win32, this
function isn't even called.
2005-07-14 13:04:29 +00:00
|
|
|
#ifdef HAVE_SYS_WAIT_H
|
2005-07-14 13:04:01 +00:00
|
|
|
#include <sys/wait.h>
|
|
|
|
|
#endif
|
2001-09-30 Tor Lillqvist <tml@iki.fi>
Author: tml
Date: 2001-09-29 21:05:25 GMT
2001-09-30 Tor Lillqvist <tml@iki.fi>
Changes for "pure" Win32 (without Cygwin or similar)
support. The most important differences compared to pkg-config
on Unix are:
We don't use hardcoded PKGLIBDIR paths but deduce the
installation prefix at runtime.
Use the normal GLib DLL, not a private copy. Yes, this does
introduce a circular dependency, but that can be worked around.
* README.win32: New file.
* configure.in: Check for Win32. If so, define USE_INSTALLED_GLIB,
and don't configure in the included glib-1.2.8. Set GLIB_CFLAGS
and GLIB_LIBS assuming that GLib is installed in the same location
pkgconfig will be. Check for dirent.h, unistd.h and sys/wait.h
headers.
* Makefile.am: If USE_INSTALLED_GLIB, use the GLIB_* values set
above, and don't make in the glib-1.2.8 subdir.
* autogen.sh: Use perl -p -i.bak, works better on Win32 (and Cygwin).
* *.c: Conditionalize inclusions of unistd.h and sys/wait.h.
* findme.c: Define X_OK on Win32 if necessary.
* parse.c
* popthelp.c: Minor Win32 portability ifdefs.
* parse.c: No need to include <windows.h>.
* pkg.c: Don't hardcode PKGLIBDIR, but use
g_win32_get_package_installation_directory() to deduce it.
(scan_dir): Make a temp copy of dirname with potential superfluous
trailing slash removed. The Win32 opendir implementation doesn't
always like those.
* pkg.h: If USE_INSTALLED_GLIB, include <glib.h> instead of
partial-glib.h.
* popt.c (execCommand): Don't compile on Win32.
* poptconfig.c (configLine): Don't bother with the "exec" stuff on
Win32, too complex to port, at least for now.
(poptReadDefaultConfig) Don't bother compiling on Win32, this
function isn't even called.
2005-07-14 13:04:29 +00:00
|
|
|
#include <sys/types.h>
|
2005-07-14 13:04:01 +00:00
|
|
|
|
2005-07-14 13:04:37 +00:00
|
|
|
#ifdef G_OS_WIN32
|
2012-12-11 07:10:48 -08:00
|
|
|
gboolean dont_define_prefix = FALSE;
|
2005-07-14 13:04:37 +00:00
|
|
|
char *prefix_variable = "prefix";
|
2012-12-11 07:10:48 -08:00
|
|
|
gboolean msvc_syntax = FALSE;
|
2005-07-14 13:04:37 +00:00
|
|
|
#endif
|
|
|
|
|
|
2007-05-30 13:24:42 +02:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
#ifndef G_IS_DIR_SEPARATOR
|
|
|
|
|
#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/')
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-07-14 13:04:01 +00:00
|
|
|
/**
|
|
|
|
|
* Read an entire line from a file into a buffer. Lines may
|
|
|
|
|
* be delimited with '\n', '\r', '\n\r', or '\r\n'. The delimiter
|
|
|
|
|
* is not written into the buffer. Text after a '#' character is treated as
|
|
|
|
|
* a comment and skipped. '\' can be used to escape a # character.
|
|
|
|
|
* '\' proceding a line delimiter combines adjacent lines. A '\' proceding
|
|
|
|
|
* any other character is ignored and written into the output buffer
|
|
|
|
|
* unmodified.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %FALSE if the stream was already at an EOF character.
|
|
|
|
|
**/
|
|
|
|
|
static gboolean
|
|
|
|
|
read_one_line (FILE *stream, GString *str)
|
|
|
|
|
{
|
|
|
|
|
gboolean quoted = FALSE;
|
|
|
|
|
gboolean comment = FALSE;
|
|
|
|
|
int n_read = 0;
|
|
|
|
|
|
|
|
|
|
g_string_truncate (str, 0);
|
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
int c;
|
|
|
|
|
|
2005-07-14 13:04:21 +00:00
|
|
|
c = getc (stream);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
if (c == EOF)
|
|
|
|
|
{
|
|
|
|
|
if (quoted)
|
|
|
|
|
g_string_append_c (str, '\\');
|
|
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
n_read++;
|
|
|
|
|
|
|
|
|
|
if (quoted)
|
|
|
|
|
{
|
|
|
|
|
quoted = FALSE;
|
|
|
|
|
|
|
|
|
|
switch (c)
|
|
|
|
|
{
|
|
|
|
|
case '#':
|
|
|
|
|
g_string_append_c (str, '#');
|
|
|
|
|
break;
|
|
|
|
|
case '\r':
|
|
|
|
|
case '\n':
|
|
|
|
|
{
|
2005-07-14 13:04:21 +00:00
|
|
|
int next_c = getc (stream);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
if (!(c == EOF ||
|
|
|
|
|
(c == '\r' && next_c == '\n') ||
|
|
|
|
|
(c == '\n' && next_c == '\r')))
|
|
|
|
|
ungetc (next_c, stream);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
g_string_append_c (str, '\\');
|
|
|
|
|
g_string_append_c (str, c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
switch (c)
|
|
|
|
|
{
|
|
|
|
|
case '#':
|
|
|
|
|
comment = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case '\\':
|
|
|
|
|
if (!comment)
|
|
|
|
|
quoted = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case '\n':
|
|
|
|
|
{
|
2005-07-14 13:04:21 +00:00
|
|
|
int next_c = getc (stream);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
if (!(c == EOF ||
|
|
|
|
|
(c == '\r' && next_c == '\n') ||
|
|
|
|
|
(c == '\n' && next_c == '\r')))
|
|
|
|
|
ungetc (next_c, stream);
|
|
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
if (!comment)
|
|
|
|
|
g_string_append_c (str, c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
done:
|
|
|
|
|
|
|
|
|
|
return n_read > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
trim_string (const char *str)
|
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (str != NULL, NULL);
|
|
|
|
|
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*str && isspace ((guchar)*str))
|
2005-07-14 13:04:01 +00:00
|
|
|
str++;
|
|
|
|
|
|
|
|
|
|
len = strlen (str);
|
2005-07-14 13:04:51 +00:00
|
|
|
while (len > 0 && isspace ((guchar)str[len-1]))
|
2005-07-14 13:04:01 +00:00
|
|
|
len--;
|
|
|
|
|
|
|
|
|
|
return g_strndup (str, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
trim_and_sub (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
char *trimmed;
|
|
|
|
|
GString *subst;
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
trimmed = trim_string (str);
|
|
|
|
|
|
|
|
|
|
subst = g_string_new ("");
|
|
|
|
|
|
|
|
|
|
p = trimmed;
|
|
|
|
|
while (*p)
|
|
|
|
|
{
|
|
|
|
|
if (p[0] == '$' &&
|
|
|
|
|
p[1] == '$')
|
|
|
|
|
{
|
2006-08-16 20:47:14 +02:00
|
|
|
/* escaped $ */
|
|
|
|
|
g_string_append_c (subst, '$');
|
2005-07-14 13:04:01 +00:00
|
|
|
p += 2;
|
|
|
|
|
}
|
|
|
|
|
else if (p[0] == '$' &&
|
|
|
|
|
p[1] == '{')
|
|
|
|
|
{
|
|
|
|
|
/* variable */
|
|
|
|
|
char *var_start;
|
|
|
|
|
char *varname;
|
|
|
|
|
char *varval;
|
|
|
|
|
|
|
|
|
|
var_start = &p[2];
|
|
|
|
|
|
|
|
|
|
/* Get up to close brace. */
|
|
|
|
|
while (*p && *p != '}')
|
|
|
|
|
++p;
|
|
|
|
|
|
|
|
|
|
varname = g_strndup (var_start, p - var_start);
|
|
|
|
|
|
|
|
|
|
++p; /* past brace */
|
|
|
|
|
|
|
|
|
|
varval = package_get_var (pkg, varname);
|
|
|
|
|
|
|
|
|
|
if (varval == NULL)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Variable '%s' not defined in '%s'\n",
|
|
|
|
|
varname, path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (varname);
|
|
|
|
|
|
|
|
|
|
g_string_append (subst, varval);
|
2005-07-14 13:07:18 +00:00
|
|
|
g_free (varval);
|
2005-07-14 13:04:01 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
g_string_append_c (subst, *p);
|
|
|
|
|
|
|
|
|
|
++p;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (trimmed);
|
|
|
|
|
p = subst->str;
|
|
|
|
|
g_string_free (subst, FALSE);
|
|
|
|
|
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_name (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
if (pkg->name)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Name field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pkg->name = trim_and_sub (pkg, str, path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_version (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
if (pkg->version)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Version field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pkg->version = trim_and_sub (pkg, str, path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_description (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
if (pkg->description)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Description field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pkg->description = trim_and_sub (pkg, str, path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-07-14 13:04:51 +00:00
|
|
|
#define MODULE_SEPARATOR(c) ((c) == ',' || isspace ((guchar)(c)))
|
2005-07-14 13:04:01 +00:00
|
|
|
#define OPERATOR_CHAR(c) ((c) == '<' || (c) == '>' || (c) == '!' || (c) == '=')
|
|
|
|
|
|
|
|
|
|
/* A module list is a list of modules with optional version specification,
|
|
|
|
|
* separated by commas and/or spaces. Commas are treated just like whitespace,
|
|
|
|
|
* in order to allow stuff like: Requires: @FRIBIDI_PC@, glib, gmodule
|
|
|
|
|
* where @FRIBIDI_PC@ gets substituted to nothing or to 'fribidi'
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
|
{
|
|
|
|
|
/* put numbers to help interpret lame debug spew ;-) */
|
|
|
|
|
OUTSIDE_MODULE = 0,
|
|
|
|
|
IN_MODULE_NAME = 1,
|
|
|
|
|
BEFORE_OPERATOR = 2,
|
|
|
|
|
IN_OPERATOR = 3,
|
|
|
|
|
AFTER_OPERATOR = 4,
|
|
|
|
|
IN_MODULE_VERSION = 5
|
|
|
|
|
} ModuleSplitState;
|
|
|
|
|
|
|
|
|
|
#define PARSE_SPEW 0
|
|
|
|
|
|
2012-11-29 05:40:40 -08:00
|
|
|
static GList *
|
2005-07-14 13:04:01 +00:00
|
|
|
split_module_list (const char *str, const char *path)
|
|
|
|
|
{
|
2012-11-29 05:40:40 -08:00
|
|
|
GList *retval = NULL;
|
2005-07-14 13:04:01 +00:00
|
|
|
const char *p;
|
|
|
|
|
const char *start;
|
|
|
|
|
ModuleSplitState state = OUTSIDE_MODULE;
|
|
|
|
|
ModuleSplitState last_state = OUTSIDE_MODULE;
|
|
|
|
|
|
|
|
|
|
/* fprintf (stderr, "Parsing: '%s'\n", str); */
|
|
|
|
|
|
|
|
|
|
start = str;
|
|
|
|
|
p = str;
|
|
|
|
|
|
|
|
|
|
while (*p)
|
|
|
|
|
{
|
|
|
|
|
#if PARSE_SPEW
|
|
|
|
|
fprintf (stderr, "p: %c state: %d last_state: %d\n", *p, state, last_state);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case OUTSIDE_MODULE:
|
|
|
|
|
if (!MODULE_SEPARATOR (*p))
|
|
|
|
|
state = IN_MODULE_NAME;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case IN_MODULE_NAME:
|
2005-07-14 13:04:51 +00:00
|
|
|
if (isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
{
|
|
|
|
|
/* Need to look ahead to determine next state */
|
|
|
|
|
const char *s = p;
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*s && isspace ((guchar)*s))
|
2005-07-14 13:04:01 +00:00
|
|
|
++s;
|
|
|
|
|
|
|
|
|
|
if (*s == '\0')
|
|
|
|
|
state = OUTSIDE_MODULE;
|
|
|
|
|
else if (MODULE_SEPARATOR (*s))
|
|
|
|
|
state = OUTSIDE_MODULE;
|
|
|
|
|
else if (OPERATOR_CHAR (*s))
|
|
|
|
|
state = BEFORE_OPERATOR;
|
|
|
|
|
else
|
|
|
|
|
state = OUTSIDE_MODULE;
|
|
|
|
|
}
|
|
|
|
|
else if (MODULE_SEPARATOR (*p))
|
|
|
|
|
state = OUTSIDE_MODULE; /* comma precludes any operators */
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BEFORE_OPERATOR:
|
|
|
|
|
/* We know an operator is coming up here due to lookahead from
|
|
|
|
|
* IN_MODULE_NAME
|
|
|
|
|
*/
|
2005-07-14 13:04:51 +00:00
|
|
|
if (isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
; /* no change */
|
|
|
|
|
else if (OPERATOR_CHAR (*p))
|
|
|
|
|
state = IN_OPERATOR;
|
|
|
|
|
else
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case IN_OPERATOR:
|
|
|
|
|
if (!OPERATOR_CHAR (*p))
|
|
|
|
|
state = AFTER_OPERATOR;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AFTER_OPERATOR:
|
2005-07-14 13:04:51 +00:00
|
|
|
if (!isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
state = IN_MODULE_VERSION;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case IN_MODULE_VERSION:
|
|
|
|
|
if (MODULE_SEPARATOR (*p))
|
|
|
|
|
state = OUTSIDE_MODULE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (state == OUTSIDE_MODULE &&
|
|
|
|
|
last_state != OUTSIDE_MODULE)
|
|
|
|
|
{
|
|
|
|
|
/* We left a module */
|
|
|
|
|
char *module = g_strndup (start, p - start);
|
2012-11-29 05:40:40 -08:00
|
|
|
retval = g_list_prepend (retval, module);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
#if PARSE_SPEW
|
|
|
|
|
fprintf (stderr, "found module: '%s'\n", module);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* reset start */
|
|
|
|
|
start = p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
last_state = state;
|
|
|
|
|
++p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p != start)
|
|
|
|
|
{
|
|
|
|
|
/* get the last module */
|
|
|
|
|
char *module = g_strndup (start, p - start);
|
2012-11-29 05:40:40 -08:00
|
|
|
retval = g_list_prepend (retval, module);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
#if PARSE_SPEW
|
|
|
|
|
fprintf (stderr, "found module: '%s'\n", module);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-29 05:40:40 -08:00
|
|
|
retval = g_list_reverse (retval);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-29 05:40:40 -08:00
|
|
|
GList *
|
2005-07-14 13:04:01 +00:00
|
|
|
parse_module_list (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
2012-11-29 05:40:40 -08:00
|
|
|
GList *split;
|
|
|
|
|
GList *iter;
|
|
|
|
|
GList *retval = NULL;
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
split = split_module_list (str, path);
|
|
|
|
|
|
|
|
|
|
iter = split;
|
|
|
|
|
while (iter != NULL)
|
|
|
|
|
{
|
|
|
|
|
RequiredVersion *ver;
|
|
|
|
|
char *p;
|
|
|
|
|
char *start;
|
|
|
|
|
|
|
|
|
|
p = iter->data;
|
|
|
|
|
|
|
|
|
|
ver = g_new0 (RequiredVersion, 1);
|
|
|
|
|
ver->comparison = ALWAYS_MATCH;
|
|
|
|
|
ver->owner = pkg;
|
2012-11-29 05:40:40 -08:00
|
|
|
retval = g_list_prepend (retval, ver);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
while (*p && MODULE_SEPARATOR (*p))
|
|
|
|
|
++p;
|
|
|
|
|
|
|
|
|
|
start = p;
|
|
|
|
|
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*p && !isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
++p;
|
|
|
|
|
|
|
|
|
|
while (*p && MODULE_SEPARATOR (*p))
|
|
|
|
|
{
|
|
|
|
|
*p = '\0';
|
|
|
|
|
++p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*start == '\0')
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Empty package name in Requires or Conflicts in file '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ver->name = g_strdup (start);
|
|
|
|
|
|
|
|
|
|
start = p;
|
|
|
|
|
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*p && !isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
++p;
|
|
|
|
|
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*p && isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
{
|
|
|
|
|
*p = '\0';
|
|
|
|
|
++p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*start != '\0')
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (start, "=") == 0)
|
|
|
|
|
ver->comparison = EQUAL;
|
|
|
|
|
else if (strcmp (start, ">=") == 0)
|
|
|
|
|
ver->comparison = GREATER_THAN_EQUAL;
|
|
|
|
|
else if (strcmp (start, "<=") == 0)
|
|
|
|
|
ver->comparison = LESS_THAN_EQUAL;
|
|
|
|
|
else if (strcmp (start, ">") == 0)
|
|
|
|
|
ver->comparison = GREATER_THAN;
|
|
|
|
|
else if (strcmp (start, "<") == 0)
|
|
|
|
|
ver->comparison = LESS_THAN;
|
|
|
|
|
else if (strcmp (start, "!=") == 0)
|
|
|
|
|
ver->comparison = NOT_EQUAL;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Unknown version comparison operator '%s' after package name '%s' in file '%s'\n", start, ver->name, path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
start = p;
|
|
|
|
|
|
|
|
|
|
while (*p && !MODULE_SEPARATOR (*p))
|
|
|
|
|
++p;
|
|
|
|
|
|
|
|
|
|
while (*p && MODULE_SEPARATOR (*p))
|
|
|
|
|
{
|
|
|
|
|
*p = '\0';
|
|
|
|
|
++p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ver->comparison != ALWAYS_MATCH && *start == '\0')
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Comparison operator but no version after package name '%s' in file '%s'\n", ver->name, path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*start != '\0')
|
|
|
|
|
{
|
|
|
|
|
ver->version = g_strdup (start);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert (ver->name);
|
|
|
|
|
|
2012-11-29 05:40:40 -08:00
|
|
|
iter = g_list_next (iter);
|
2005-07-14 13:04:01 +00:00
|
|
|
}
|
|
|
|
|
|
2012-11-29 05:40:40 -08:00
|
|
|
g_list_foreach (split, (GFunc) g_free, NULL);
|
|
|
|
|
g_list_free (split);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
2012-11-29 05:40:40 -08:00
|
|
|
retval = g_list_reverse (retval);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_requires (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
char *trimmed;
|
2012-05-08 05:28:13 -07:00
|
|
|
|
2005-07-14 13:04:01 +00:00
|
|
|
if (pkg->requires)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Requires field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trimmed = trim_and_sub (pkg, str, path);
|
2012-05-08 05:28:13 -07:00
|
|
|
pkg->requires_entries = parse_module_list (pkg, trimmed, path);
|
2005-07-14 13:04:01 +00:00
|
|
|
g_free (trimmed);
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-27 Tollef Fog Heen <tfheen@err.no>
Author: tfheen
Date: 2005-06-27 19:53:05 GMT
2005-06-27 Tollef Fog Heen <tfheen@err.no>
All those Requires.private changes are thanks to James
Henstridge. Thanks!
* check/private-dep.pc, check/public-dep.pc,
check/requires-test.pc: New files, data for the
check-requires-private test.
* check/check-requires-private: New test to check for
Requires.private support.
* check/Makefile.am (EXTRA_DIST, TESTS): Add Requires.private
test.
* pkg.h (struct _Package): Add requires_private
* pkg.c (get_requires_private, fill_list_single_package)
(fill_list, verify_package, verify_package, get_merged)
(get_merged_from_back, get_multi_merged)
(get_multi_merged_from_back, package_get_l_libs)
(packages_get_l_libs, package_get_L_libs, packages_get_L_libs)
(package_get_other_libs, packages_get_other_libs)
(package_get_I_cflags, packages_get_I_cflags)
(package_get_other_cflags, packages_get_other_cflags): Handle
private requires and cascading changes.
* parse.c (parse_requires_private, parse_conflicts)
(parse_package_file): Handle Requires.private
2005-07-14 13:07:31 +00:00
|
|
|
static void
|
|
|
|
|
parse_requires_private (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
char *trimmed;
|
2012-05-08 05:28:13 -07:00
|
|
|
|
2005-06-27 Tollef Fog Heen <tfheen@err.no>
Author: tfheen
Date: 2005-06-27 19:53:05 GMT
2005-06-27 Tollef Fog Heen <tfheen@err.no>
All those Requires.private changes are thanks to James
Henstridge. Thanks!
* check/private-dep.pc, check/public-dep.pc,
check/requires-test.pc: New files, data for the
check-requires-private test.
* check/check-requires-private: New test to check for
Requires.private support.
* check/Makefile.am (EXTRA_DIST, TESTS): Add Requires.private
test.
* pkg.h (struct _Package): Add requires_private
* pkg.c (get_requires_private, fill_list_single_package)
(fill_list, verify_package, verify_package, get_merged)
(get_merged_from_back, get_multi_merged)
(get_multi_merged_from_back, package_get_l_libs)
(packages_get_l_libs, package_get_L_libs, packages_get_L_libs)
(package_get_other_libs, packages_get_other_libs)
(package_get_I_cflags, packages_get_I_cflags)
(package_get_other_cflags, packages_get_other_cflags): Handle
private requires and cascading changes.
* parse.c (parse_requires_private, parse_conflicts)
(parse_package_file): Handle Requires.private
2005-07-14 13:07:31 +00:00
|
|
|
if (pkg->requires_private)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Requires.private field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trimmed = trim_and_sub (pkg, str, path);
|
2012-05-08 05:28:13 -07:00
|
|
|
pkg->requires_private_entries = parse_module_list (pkg, trimmed, path);
|
2005-06-27 Tollef Fog Heen <tfheen@err.no>
Author: tfheen
Date: 2005-06-27 19:53:05 GMT
2005-06-27 Tollef Fog Heen <tfheen@err.no>
All those Requires.private changes are thanks to James
Henstridge. Thanks!
* check/private-dep.pc, check/public-dep.pc,
check/requires-test.pc: New files, data for the
check-requires-private test.
* check/check-requires-private: New test to check for
Requires.private support.
* check/Makefile.am (EXTRA_DIST, TESTS): Add Requires.private
test.
* pkg.h (struct _Package): Add requires_private
* pkg.c (get_requires_private, fill_list_single_package)
(fill_list, verify_package, verify_package, get_merged)
(get_merged_from_back, get_multi_merged)
(get_multi_merged_from_back, package_get_l_libs)
(packages_get_l_libs, package_get_L_libs, packages_get_L_libs)
(package_get_other_libs, packages_get_other_libs)
(package_get_I_cflags, packages_get_I_cflags)
(package_get_other_cflags, packages_get_other_cflags): Handle
private requires and cascading changes.
* parse.c (parse_requires_private, parse_conflicts)
(parse_package_file): Handle Requires.private
2005-07-14 13:07:31 +00:00
|
|
|
g_free (trimmed);
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-14 13:04:01 +00:00
|
|
|
static void
|
|
|
|
|
parse_conflicts (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
char *trimmed;
|
|
|
|
|
|
|
|
|
|
if (pkg->conflicts)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Conflicts field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trimmed = trim_and_sub (pkg, str, path);
|
|
|
|
|
pkg->conflicts = parse_module_list (pkg, trimmed, path);
|
|
|
|
|
g_free (trimmed);
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-23 22:59:46 +02:00
|
|
|
static char *strdup_escape_shell(const char *s)
|
|
|
|
|
{
|
|
|
|
|
size_t r_s = strlen(s)+10, c = 0;
|
|
|
|
|
char *r = g_malloc(r_s);
|
|
|
|
|
while (s[0]) {
|
2011-04-13 22:02:51 +02:00
|
|
|
if ((s[0] < '$') ||
|
|
|
|
|
(s[0] > '$' && s[0] < '(') ||
|
|
|
|
|
(s[0] > ')' && s[0] < '+') ||
|
2010-05-27 21:48:52 +02:00
|
|
|
(s[0] > ':' && s[0] < '=') ||
|
|
|
|
|
(s[0] > '=' && s[0] < '@') ||
|
2010-05-23 22:59:46 +02:00
|
|
|
(s[0] > 'Z' && s[0] < '^') ||
|
|
|
|
|
(s[0] == '`') ||
|
2012-11-13 18:32:03 +00:00
|
|
|
(s[0] > 'z' && s[0] < '~') ||
|
|
|
|
|
(s[0] > '~')) {
|
2010-05-23 22:59:46 +02:00
|
|
|
r[c] = '\\';
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
r[c] = *s;
|
|
|
|
|
c++;
|
|
|
|
|
if (c+2 >= r_s) {
|
|
|
|
|
r_s *= 2;
|
|
|
|
|
r = g_realloc(r, r_s);
|
|
|
|
|
}
|
|
|
|
|
s++;
|
|
|
|
|
}
|
|
|
|
|
r[c] = 0;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-14 13:07:18 +00:00
|
|
|
static void _do_parse_libs (Package *pkg, int argc, char **argv)
|
2005-07-14 13:04:01 +00:00
|
|
|
{
|
|
|
|
|
int i;
|
2005-07-14 13:04:41 +00:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
char *L_flag = (msvc_syntax ? "/libpath:" : "-L");
|
|
|
|
|
char *l_flag = (msvc_syntax ? "" : "-l");
|
|
|
|
|
char *lib_suffix = (msvc_syntax ? ".lib" : "");
|
|
|
|
|
#else
|
|
|
|
|
char *L_flag = "-L";
|
|
|
|
|
char *l_flag = "-l";
|
|
|
|
|
char *lib_suffix = "";
|
|
|
|
|
#endif
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (i < argc)
|
|
|
|
|
{
|
2012-11-19 08:19:48 -08:00
|
|
|
Flag *flag = g_new (Flag, 1);
|
2010-05-23 22:59:46 +02:00
|
|
|
char *tmp = trim_string (argv[i]);
|
|
|
|
|
char *arg = strdup_escape_shell(tmp);
|
2005-07-14 13:04:01 +00:00
|
|
|
char *p;
|
2010-05-23 22:59:46 +02:00
|
|
|
p = arg;
|
|
|
|
|
g_free(tmp);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
if (p[0] == '-' &&
|
2008-04-28 21:19:02 +02:00
|
|
|
p[1] == 'l' &&
|
|
|
|
|
/* -lib: is used by the C# compiler for libs; it's not an -l
|
|
|
|
|
flag. */
|
|
|
|
|
(strncmp(p, "-lib:", 5) != 0))
|
2005-07-14 13:04:01 +00:00
|
|
|
{
|
|
|
|
|
p += 2;
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*p && isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
++p;
|
|
|
|
|
|
2012-11-19 08:19:48 -08:00
|
|
|
flag->type = LIBS_l;
|
|
|
|
|
flag->arg = g_strconcat (l_flag, p, lib_suffix, NULL);
|
|
|
|
|
pkg->libs = g_list_prepend (pkg->libs, flag);
|
2005-07-14 13:04:01 +00:00
|
|
|
}
|
|
|
|
|
else if (p[0] == '-' &&
|
|
|
|
|
p[1] == 'L')
|
|
|
|
|
{
|
|
|
|
|
p += 2;
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*p && isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
++p;
|
2012-11-19 08:19:48 -08:00
|
|
|
|
|
|
|
|
flag->type = LIBS_L;
|
2013-04-17 07:36:39 -07:00
|
|
|
flag->arg = g_strconcat (L_flag, p, NULL);
|
2012-11-19 08:19:48 -08:00
|
|
|
pkg->libs = g_list_prepend (pkg->libs, flag);
|
2010-05-23 22:59:46 +02:00
|
|
|
}
|
2005-07-14 13:06:47 +00:00
|
|
|
else if (strcmp("-framework",p) == 0 && i+1 < argc)
|
|
|
|
|
{
|
|
|
|
|
/* Mac OS X has a -framework Foo which is really one option,
|
|
|
|
|
* so we join those to avoid having -framework Foo
|
|
|
|
|
* -framework Bar being changed into -framework Foo Bar
|
|
|
|
|
* later
|
|
|
|
|
*/
|
2010-05-23 22:59:46 +02:00
|
|
|
gchar *framework, *tmp = trim_string (argv[i+1]);
|
2005-07-14 13:06:47 +00:00
|
|
|
|
2012-11-19 08:19:48 -08:00
|
|
|
framework = strdup_escape_shell(tmp);
|
|
|
|
|
flag->type = LIBS_OTHER;
|
|
|
|
|
flag->arg = g_strconcat (arg, " ", framework, NULL);
|
|
|
|
|
pkg->libs = g_list_prepend (pkg->libs, flag);
|
2005-07-14 13:06:47 +00:00
|
|
|
i++;
|
2012-11-19 08:19:48 -08:00
|
|
|
g_free (framework);
|
|
|
|
|
g_free (tmp);
|
2005-07-14 13:06:47 +00:00
|
|
|
}
|
2012-11-19 08:19:48 -08:00
|
|
|
else if (*arg != '\0')
|
2005-07-14 13:04:01 +00:00
|
|
|
{
|
2012-11-19 08:19:48 -08:00
|
|
|
flag->type = LIBS_OTHER;
|
|
|
|
|
flag->arg = g_strdup (arg);
|
|
|
|
|
pkg->libs = g_list_prepend (pkg->libs, flag);
|
2005-07-14 13:04:01 +00:00
|
|
|
}
|
2012-11-19 08:19:48 -08:00
|
|
|
else
|
|
|
|
|
/* flag wasn't used */
|
|
|
|
|
g_free (flag);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
g_free (arg);
|
2010-05-23 22:59:46 +02:00
|
|
|
|
2005-07-14 13:04:01 +00:00
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2005-07-14 13:07:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_libs (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
/* Strip out -l and -L flags, put them in a separate list. */
|
|
|
|
|
|
|
|
|
|
char *trimmed;
|
|
|
|
|
char **argv = NULL;
|
2010-05-27 22:23:19 +02:00
|
|
|
int argc = 0;
|
2010-06-13 20:23:45 -07:00
|
|
|
GError *error = NULL;
|
2005-07-14 13:07:18 +00:00
|
|
|
|
|
|
|
|
if (pkg->libs_num > 0)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Libs field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trimmed = trim_and_sub (pkg, str, path);
|
|
|
|
|
|
2010-06-13 20:23:45 -07:00
|
|
|
if (trimmed && *trimmed &&
|
|
|
|
|
!g_shell_parse_argv (trimmed, &argc, &argv, &error))
|
2005-07-14 13:07:18 +00:00
|
|
|
{
|
2010-06-13 20:23:45 -07:00
|
|
|
verbose_error ("Couldn't parse Libs field into an argument vector: %s\n",
|
|
|
|
|
error ? error->message : "unknown");
|
|
|
|
|
exit (1);
|
2005-07-14 13:07:18 +00:00
|
|
|
}
|
2010-05-27 22:23:19 +02:00
|
|
|
|
2005-07-14 13:07:18 +00:00
|
|
|
_do_parse_libs(pkg, argc, argv);
|
|
|
|
|
|
|
|
|
|
g_free (trimmed);
|
2010-06-13 20:23:45 -07:00
|
|
|
g_strfreev (argv);
|
2005-07-14 13:07:18 +00:00
|
|
|
pkg->libs_num++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_libs_private (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
List of private libraries. Private libraries are libraries which
|
|
|
|
|
are needed in the case of static linking or on platforms not
|
|
|
|
|
supporting inter-library dependencies. They are not supposed to
|
|
|
|
|
be used for libraries which are exposed through the library in
|
|
|
|
|
question. An example of an exposed library is GTK+ exposing Glib.
|
|
|
|
|
A common example of a private library is libm.
|
|
|
|
|
|
|
|
|
|
Generally, if include another library's headers in your own, it's
|
|
|
|
|
a public dependency and not a private one.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
char *trimmed;
|
|
|
|
|
char **argv = NULL;
|
2010-05-27 22:23:19 +02:00
|
|
|
int argc = 0;
|
2010-06-13 20:23:45 -07:00
|
|
|
GError *error = NULL;
|
2005-07-14 13:07:18 +00:00
|
|
|
|
|
|
|
|
if (pkg->libs_private_num > 0)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Libs.private field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trimmed = trim_and_sub (pkg, str, path);
|
|
|
|
|
|
2010-06-13 20:23:45 -07:00
|
|
|
if (trimmed && *trimmed &&
|
|
|
|
|
!g_shell_parse_argv (trimmed, &argc, &argv, &error))
|
2005-07-14 13:07:18 +00:00
|
|
|
{
|
2010-06-13 20:23:45 -07:00
|
|
|
verbose_error ("Couldn't parse Libs.private field into an argument vector: %s\n",
|
|
|
|
|
error ? error->message : "unknown");
|
|
|
|
|
exit (1);
|
2005-07-14 13:07:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_do_parse_libs(pkg, argc, argv);
|
|
|
|
|
|
2010-06-13 20:23:45 -07:00
|
|
|
g_strfreev (argv);
|
2005-07-14 13:07:18 +00:00
|
|
|
g_free (trimmed);
|
|
|
|
|
|
|
|
|
|
pkg->libs_private_num++;
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-14 13:04:01 +00:00
|
|
|
static void
|
|
|
|
|
parse_cflags (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
/* Strip out -I flags, put them in a separate list. */
|
|
|
|
|
|
|
|
|
|
char *trimmed;
|
|
|
|
|
char **argv = NULL;
|
2010-05-27 22:23:19 +02:00
|
|
|
int argc = 0;
|
2010-06-13 20:23:45 -07:00
|
|
|
GError *error = NULL;
|
2005-07-14 13:04:01 +00:00
|
|
|
int i;
|
|
|
|
|
|
2012-11-19 08:19:48 -08:00
|
|
|
if (pkg->cflags)
|
2005-07-14 13:04:01 +00:00
|
|
|
{
|
|
|
|
|
verbose_error ("Cflags field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trimmed = trim_and_sub (pkg, str, path);
|
|
|
|
|
|
2010-06-13 20:23:45 -07:00
|
|
|
if (trimmed && *trimmed &&
|
|
|
|
|
!g_shell_parse_argv (trimmed, &argc, &argv, &error))
|
2005-07-14 13:04:01 +00:00
|
|
|
{
|
2010-06-13 20:23:45 -07:00
|
|
|
verbose_error ("Couldn't parse Cflags field into an argument vector: %s\n",
|
|
|
|
|
error ? error->message : "unknown");
|
|
|
|
|
exit (1);
|
2005-07-14 13:04:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
while (i < argc)
|
|
|
|
|
{
|
2012-11-19 08:19:48 -08:00
|
|
|
Flag *flag = g_new (Flag, 1);
|
2010-05-23 22:59:46 +02:00
|
|
|
char *tmp = trim_string (argv[i]);
|
|
|
|
|
char *arg = strdup_escape_shell(tmp);
|
|
|
|
|
char *p = arg;
|
|
|
|
|
g_free(tmp);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
if (p[0] == '-' &&
|
|
|
|
|
p[1] == 'I')
|
|
|
|
|
{
|
|
|
|
|
p += 2;
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*p && isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
++p;
|
|
|
|
|
|
2012-11-19 08:19:48 -08:00
|
|
|
flag->type = CFLAGS_I;
|
|
|
|
|
flag->arg = g_strconcat ("-I", p, NULL);
|
|
|
|
|
pkg->cflags = g_list_prepend (pkg->cflags, flag);
|
|
|
|
|
}
|
|
|
|
|
else if (strcmp("-idirafter", arg) == 0 && i+1 < argc)
|
|
|
|
|
{
|
|
|
|
|
char *dirafter, *tmp;
|
2011-04-13 20:29:22 +02:00
|
|
|
|
2012-11-19 08:19:48 -08:00
|
|
|
tmp = trim_string (argv[i+1]);
|
|
|
|
|
dirafter = strdup_escape_shell (tmp);
|
|
|
|
|
flag->type = CFLAGS_OTHER;
|
|
|
|
|
flag->arg = g_strconcat (arg, " ", dirafter, NULL);
|
|
|
|
|
pkg->cflags = g_list_prepend (pkg->cflags, flag);
|
|
|
|
|
i++;
|
|
|
|
|
g_free (dirafter);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
|
|
|
|
else if (*arg != '\0')
|
|
|
|
|
{
|
|
|
|
|
flag->type = CFLAGS_OTHER;
|
|
|
|
|
flag->arg = g_strdup (arg);
|
|
|
|
|
pkg->cflags = g_list_prepend (pkg->cflags, flag);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/* flag wasn't used */
|
|
|
|
|
g_free (flag);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
g_free (arg);
|
|
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-13 20:23:45 -07:00
|
|
|
g_strfreev (argv);
|
2005-07-14 13:04:01 +00:00
|
|
|
g_free (trimmed);
|
|
|
|
|
}
|
2005-07-14 13:05:41 +00:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_url (Package *pkg, const char *str, const char *path)
|
|
|
|
|
{
|
|
|
|
|
if (pkg->url != NULL)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("URL field occurs twice in '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pkg->url = trim_and_sub (pkg, str, path);
|
|
|
|
|
}
|
|
|
|
|
|
2007-05-30 13:24:42 +02:00
|
|
|
#ifdef G_OS_WIN32
|
2009-06-30 03:47:01 +02:00
|
|
|
static char *orig_prefix = NULL;
|
|
|
|
|
|
2007-05-30 13:24:42 +02:00
|
|
|
static int
|
|
|
|
|
pathnamecmp (const char *a,
|
|
|
|
|
const char *b)
|
|
|
|
|
{
|
|
|
|
|
while (*a && *b &&
|
|
|
|
|
((G_IS_DIR_SEPARATOR (*a) && G_IS_DIR_SEPARATOR (*b)) ||
|
|
|
|
|
g_ascii_toupper (*a) == g_ascii_toupper (*b)))
|
|
|
|
|
{
|
|
|
|
|
a++;
|
|
|
|
|
b++;
|
|
|
|
|
}
|
|
|
|
|
return g_ascii_toupper (*a) - g_ascii_toupper (*b);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-07-14 13:04:01 +00:00
|
|
|
static void
|
2009-03-30 20:40:53 +02:00
|
|
|
parse_line (Package *pkg, const char *untrimmed, const char *path,
|
|
|
|
|
gboolean ignore_requires, gboolean ignore_private_libs,
|
|
|
|
|
gboolean ignore_requires_private)
|
2005-07-14 13:04:01 +00:00
|
|
|
{
|
|
|
|
|
char *str;
|
|
|
|
|
char *p;
|
|
|
|
|
char *tag;
|
|
|
|
|
|
|
|
|
|
debug_spew (" line>%s\n", untrimmed);
|
|
|
|
|
|
|
|
|
|
str = trim_string (untrimmed);
|
|
|
|
|
|
2005-07-14 13:07:18 +00:00
|
|
|
if (*str == '\0') /* empty line */
|
|
|
|
|
{
|
|
|
|
|
g_free(str);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
p = str;
|
|
|
|
|
|
|
|
|
|
/* Get first word */
|
|
|
|
|
while ((*p >= 'A' && *p <= 'Z') ||
|
|
|
|
|
(*p >= 'a' && *p <= 'z') ||
|
|
|
|
|
(*p >= '0' && *p <= '9') ||
|
2005-07-14 13:07:18 +00:00
|
|
|
*p == '_' || *p == '.')
|
2005-07-14 13:04:01 +00:00
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
tag = g_strndup (str, p - str);
|
|
|
|
|
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*p && isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
++p;
|
|
|
|
|
|
|
|
|
|
if (*p == ':')
|
|
|
|
|
{
|
|
|
|
|
/* keyword */
|
|
|
|
|
++p;
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*p && isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
++p;
|
|
|
|
|
|
|
|
|
|
if (strcmp (tag, "Name") == 0)
|
|
|
|
|
parse_name (pkg, p, path);
|
|
|
|
|
else if (strcmp (tag, "Description") == 0)
|
|
|
|
|
parse_description (pkg, p, path);
|
|
|
|
|
else if (strcmp (tag, "Version") == 0)
|
|
|
|
|
parse_version (pkg, p, path);
|
2005-06-27 Tollef Fog Heen <tfheen@err.no>
Author: tfheen
Date: 2005-06-27 19:53:05 GMT
2005-06-27 Tollef Fog Heen <tfheen@err.no>
All those Requires.private changes are thanks to James
Henstridge. Thanks!
* check/private-dep.pc, check/public-dep.pc,
check/requires-test.pc: New files, data for the
check-requires-private test.
* check/check-requires-private: New test to check for
Requires.private support.
* check/Makefile.am (EXTRA_DIST, TESTS): Add Requires.private
test.
* pkg.h (struct _Package): Add requires_private
* pkg.c (get_requires_private, fill_list_single_package)
(fill_list, verify_package, verify_package, get_merged)
(get_merged_from_back, get_multi_merged)
(get_multi_merged_from_back, package_get_l_libs)
(packages_get_l_libs, package_get_L_libs, packages_get_L_libs)
(package_get_other_libs, packages_get_other_libs)
(package_get_I_cflags, packages_get_I_cflags)
(package_get_other_cflags, packages_get_other_cflags): Handle
private requires and cascading changes.
* parse.c (parse_requires_private, parse_conflicts)
(parse_package_file): Handle Requires.private
2005-07-14 13:07:31 +00:00
|
|
|
else if (strcmp (tag, "Requires.private") == 0)
|
2009-03-30 20:40:53 +02:00
|
|
|
{
|
|
|
|
|
if (!ignore_requires_private)
|
|
|
|
|
parse_requires_private (pkg, p, path);
|
|
|
|
|
}
|
2005-07-14 13:04:01 +00:00
|
|
|
else if (strcmp (tag, "Requires") == 0)
|
2005-06-27 Tollef Fog Heen <tfheen@err.no>
Author: tfheen
Date: 2005-06-27 19:53:05 GMT
2005-06-27 Tollef Fog Heen <tfheen@err.no>
All those Requires.private changes are thanks to James
Henstridge. Thanks!
* check/private-dep.pc, check/public-dep.pc,
check/requires-test.pc: New files, data for the
check-requires-private test.
* check/check-requires-private: New test to check for
Requires.private support.
* check/Makefile.am (EXTRA_DIST, TESTS): Add Requires.private
test.
* pkg.h (struct _Package): Add requires_private
* pkg.c (get_requires_private, fill_list_single_package)
(fill_list, verify_package, verify_package, get_merged)
(get_merged_from_back, get_multi_merged)
(get_multi_merged_from_back, package_get_l_libs)
(packages_get_l_libs, package_get_L_libs, packages_get_L_libs)
(package_get_other_libs, packages_get_other_libs)
(package_get_I_cflags, packages_get_I_cflags)
(package_get_other_cflags, packages_get_other_cflags): Handle
private requires and cascading changes.
* parse.c (parse_requires_private, parse_conflicts)
(parse_package_file): Handle Requires.private
2005-07-14 13:07:31 +00:00
|
|
|
{
|
2005-07-14 13:06:19 +00:00
|
|
|
if (ignore_requires == FALSE)
|
2005-06-27 Tollef Fog Heen <tfheen@err.no>
Author: tfheen
Date: 2005-06-27 19:53:05 GMT
2005-06-27 Tollef Fog Heen <tfheen@err.no>
All those Requires.private changes are thanks to James
Henstridge. Thanks!
* check/private-dep.pc, check/public-dep.pc,
check/requires-test.pc: New files, data for the
check-requires-private test.
* check/check-requires-private: New test to check for
Requires.private support.
* check/Makefile.am (EXTRA_DIST, TESTS): Add Requires.private
test.
* pkg.h (struct _Package): Add requires_private
* pkg.c (get_requires_private, fill_list_single_package)
(fill_list, verify_package, verify_package, get_merged)
(get_merged_from_back, get_multi_merged)
(get_multi_merged_from_back, package_get_l_libs)
(packages_get_l_libs, package_get_L_libs, packages_get_L_libs)
(package_get_other_libs, packages_get_other_libs)
(package_get_I_cflags, packages_get_I_cflags)
(package_get_other_cflags, packages_get_other_cflags): Handle
private requires and cascading changes.
* parse.c (parse_requires_private, parse_conflicts)
(parse_package_file): Handle Requires.private
2005-07-14 13:07:31 +00:00
|
|
|
parse_requires (pkg, p, path);
|
2005-07-14 13:06:19 +00:00
|
|
|
else
|
2005-07-14 13:07:18 +00:00
|
|
|
goto cleanup;
|
2005-07-14 13:06:19 +00:00
|
|
|
}
|
2005-07-14 13:07:18 +00:00
|
|
|
else if ((strcmp (tag, "Libs.private") == 0) &&
|
|
|
|
|
ignore_private_libs == FALSE)
|
|
|
|
|
parse_libs_private (pkg, p, path);
|
2005-07-14 13:04:01 +00:00
|
|
|
else if (strcmp (tag, "Libs") == 0)
|
|
|
|
|
parse_libs (pkg, p, path);
|
2005-07-14 13:04:19 +00:00
|
|
|
else if (strcmp (tag, "Cflags") == 0 ||
|
|
|
|
|
strcmp (tag, "CFlags") == 0)
|
2005-07-14 13:04:01 +00:00
|
|
|
parse_cflags (pkg, p, path);
|
|
|
|
|
else if (strcmp (tag, "Conflicts") == 0)
|
|
|
|
|
parse_conflicts (pkg, p, path);
|
2005-07-14 13:05:41 +00:00
|
|
|
else if (strcmp (tag, "URL") == 0)
|
|
|
|
|
parse_url (pkg, p, path);
|
2005-07-14 13:04:01 +00:00
|
|
|
else
|
|
|
|
|
{
|
2005-07-14 13:05:55 +00:00
|
|
|
/* we don't error out on unknown keywords because they may
|
|
|
|
|
* represent additions to the .pc file format from future
|
|
|
|
|
* versions of pkg-config. We do make a note of them in the
|
|
|
|
|
* debug spew though, in order to help catch mistakes in .pc
|
|
|
|
|
* files. */
|
|
|
|
|
debug_spew ("Unknown keyword '%s' in '%s'\n",
|
|
|
|
|
tag, path);
|
2005-07-14 13:04:01 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (*p == '=')
|
|
|
|
|
{
|
|
|
|
|
/* variable */
|
|
|
|
|
char *varname;
|
|
|
|
|
char *varval;
|
|
|
|
|
|
|
|
|
|
++p;
|
2005-07-14 13:04:51 +00:00
|
|
|
while (*p && isspace ((guchar)*p))
|
2005-07-14 13:04:01 +00:00
|
|
|
++p;
|
|
|
|
|
|
|
|
|
|
if (pkg->vars == NULL)
|
|
|
|
|
pkg->vars = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
|
|
2005-07-14 13:04:37 +00:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
if (!dont_define_prefix && strcmp (tag, prefix_variable) == 0)
|
|
|
|
|
{
|
|
|
|
|
/* This is the prefix variable. Try to guesstimate a value for it
|
|
|
|
|
* for this package from the location of the .pc file.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
gchar *prefix = pkg->pcfiledir;
|
|
|
|
|
const int prefix_len = strlen (prefix);
|
|
|
|
|
const char *const lib_pkgconfig = "\\lib\\pkgconfig";
|
2008-03-23 20:00:00 +01:00
|
|
|
const char *const share_pkgconfig = "\\share\\pkgconfig";
|
2005-07-14 13:04:37 +00:00
|
|
|
const int lib_pkgconfig_len = strlen (lib_pkgconfig);
|
2008-03-23 20:00:00 +01:00
|
|
|
const int share_pkgconfig_len = strlen (share_pkgconfig);
|
2005-07-14 13:04:37 +00:00
|
|
|
|
2008-03-23 20:00:00 +01:00
|
|
|
if ((strlen (prefix) > lib_pkgconfig_len &&
|
|
|
|
|
pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0) ||
|
|
|
|
|
(strlen (prefix) > share_pkgconfig_len &&
|
|
|
|
|
pathnamecmp (prefix + prefix_len - share_pkgconfig_len, share_pkgconfig) == 0))
|
2005-07-14 13:04:37 +00:00
|
|
|
{
|
2008-03-23 20:00:00 +01:00
|
|
|
/* It ends in lib\pkgconfig or share\pkgconfig. Good. */
|
2005-07-14 13:04:37 +00:00
|
|
|
|
2009-06-30 03:47:01 +02:00
|
|
|
gchar *q;
|
2005-07-14 13:04:37 +00:00
|
|
|
|
2009-06-30 03:47:01 +02:00
|
|
|
orig_prefix = g_strdup (p);
|
|
|
|
|
|
2005-07-14 13:04:37 +00:00
|
|
|
prefix = g_strdup (prefix);
|
2008-03-23 20:00:00 +01:00
|
|
|
if (strlen (prefix) > lib_pkgconfig_len &&
|
|
|
|
|
pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0)
|
|
|
|
|
prefix[prefix_len - lib_pkgconfig_len] = '\0';
|
|
|
|
|
else
|
|
|
|
|
prefix[prefix_len - share_pkgconfig_len] = '\0';
|
2005-07-14 13:04:37 +00:00
|
|
|
|
|
|
|
|
/* Turn backslashes into slashes or
|
2010-06-13 20:23:45 -07:00
|
|
|
* g_shell_parse_argv() will eat them when ${prefix}
|
2005-07-14 13:04:37 +00:00
|
|
|
* has been expanded in parse_libs().
|
|
|
|
|
*/
|
2009-06-30 03:47:01 +02:00
|
|
|
q = prefix;
|
|
|
|
|
while (*q)
|
2005-07-14 13:04:37 +00:00
|
|
|
{
|
2009-06-30 03:47:01 +02:00
|
|
|
if (*q == '\\')
|
|
|
|
|
*q = '/';
|
|
|
|
|
q++;
|
2005-07-14 13:04:37 +00:00
|
|
|
}
|
2012-08-21 05:49:07 -07:00
|
|
|
|
|
|
|
|
/* Now escape the special characters so that there's no danger
|
|
|
|
|
* of arguments that include the prefix getting split.
|
|
|
|
|
*/
|
|
|
|
|
q = prefix;
|
|
|
|
|
prefix = strdup_escape_shell (prefix);
|
|
|
|
|
g_free (q);
|
|
|
|
|
|
2005-07-14 13:04:37 +00:00
|
|
|
varname = g_strdup (tag);
|
|
|
|
|
debug_spew (" Variable declaration, '%s' overridden with '%s'\n",
|
|
|
|
|
tag, prefix);
|
|
|
|
|
g_hash_table_insert (pkg->vars, varname, prefix);
|
2005-07-14 13:07:18 +00:00
|
|
|
goto cleanup;
|
2005-07-14 13:04:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-06-30 03:47:01 +02:00
|
|
|
else if (!dont_define_prefix &&
|
|
|
|
|
orig_prefix != NULL &&
|
|
|
|
|
strncmp (p, orig_prefix, strlen (orig_prefix)) == 0 &&
|
|
|
|
|
G_IS_DIR_SEPARATOR (p[strlen (orig_prefix)]))
|
|
|
|
|
{
|
|
|
|
|
char *oldstr = str;
|
|
|
|
|
|
|
|
|
|
p = str = g_strconcat (g_hash_table_lookup (pkg->vars, prefix_variable), p + strlen (orig_prefix), NULL);
|
|
|
|
|
g_free (oldstr);
|
|
|
|
|
}
|
2005-07-14 13:04:37 +00:00
|
|
|
#endif
|
|
|
|
|
|
2005-07-14 13:04:01 +00:00
|
|
|
if (g_hash_table_lookup (pkg->vars, tag))
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Duplicate definition of variable '%s' in '%s'\n",
|
|
|
|
|
tag, path);
|
|
|
|
|
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
varname = g_strdup (tag);
|
|
|
|
|
varval = trim_and_sub (pkg, p, path);
|
|
|
|
|
|
|
|
|
|
debug_spew (" Variable declaration, '%s' has value '%s'\n",
|
|
|
|
|
varname, varval);
|
|
|
|
|
g_hash_table_insert (pkg->vars, varname, varval);
|
|
|
|
|
|
|
|
|
|
}
|
2005-07-14 13:07:18 +00:00
|
|
|
|
|
|
|
|
cleanup:
|
2005-07-14 13:04:01 +00:00
|
|
|
g_free (str);
|
|
|
|
|
g_free (tag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Package*
|
2009-03-30 20:40:53 +02:00
|
|
|
parse_package_file (const char *path, gboolean ignore_requires,
|
|
|
|
|
gboolean ignore_private_libs,
|
|
|
|
|
gboolean ignore_requires_private)
|
2005-07-14 13:04:01 +00:00
|
|
|
{
|
|
|
|
|
FILE *f;
|
|
|
|
|
Package *pkg;
|
|
|
|
|
GString *str;
|
|
|
|
|
gboolean one_line = FALSE;
|
|
|
|
|
|
|
|
|
|
f = fopen (path, "r");
|
|
|
|
|
|
|
|
|
|
if (f == NULL)
|
|
|
|
|
{
|
|
|
|
|
verbose_error ("Failed to open '%s': %s\n",
|
|
|
|
|
path, strerror (errno));
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug_spew ("Parsing package file '%s'\n", path);
|
|
|
|
|
|
|
|
|
|
pkg = g_new0 (Package, 1);
|
|
|
|
|
|
|
|
|
|
if (path)
|
|
|
|
|
{
|
|
|
|
|
pkg->pcfiledir = g_dirname (path);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
debug_spew ("No pcfiledir determined for package\n");
|
|
|
|
|
pkg->pcfiledir = g_strdup ("???????");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str = g_string_new ("");
|
|
|
|
|
|
|
|
|
|
while (read_one_line (f, str))
|
|
|
|
|
{
|
|
|
|
|
one_line = TRUE;
|
|
|
|
|
|
2009-03-30 20:40:53 +02:00
|
|
|
parse_line (pkg, str->str, path, ignore_requires, ignore_private_libs,
|
|
|
|
|
ignore_requires_private);
|
2005-07-14 13:04:01 +00:00
|
|
|
|
|
|
|
|
g_string_truncate (str, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!one_line)
|
|
|
|
|
verbose_error ("Package file '%s' appears to be empty\n",
|
|
|
|
|
path);
|
2005-07-14 13:07:18 +00:00
|
|
|
g_string_free (str, TRUE);
|
2005-07-14 13:06:15 +00:00
|
|
|
fclose(f);
|
2005-06-27 Tollef Fog Heen <tfheen@err.no>
Author: tfheen
Date: 2005-06-27 19:53:05 GMT
2005-06-27 Tollef Fog Heen <tfheen@err.no>
All those Requires.private changes are thanks to James
Henstridge. Thanks!
* check/private-dep.pc, check/public-dep.pc,
check/requires-test.pc: New files, data for the
check-requires-private test.
* check/check-requires-private: New test to check for
Requires.private support.
* check/Makefile.am (EXTRA_DIST, TESTS): Add Requires.private
test.
* pkg.h (struct _Package): Add requires_private
* pkg.c (get_requires_private, fill_list_single_package)
(fill_list, verify_package, verify_package, get_merged)
(get_merged_from_back, get_multi_merged)
(get_multi_merged_from_back, package_get_l_libs)
(packages_get_l_libs, package_get_L_libs, packages_get_L_libs)
(package_get_other_libs, packages_get_other_libs)
(package_get_I_cflags, packages_get_I_cflags)
(package_get_other_cflags, packages_get_other_cflags): Handle
private requires and cascading changes.
* parse.c (parse_requires_private, parse_conflicts)
(parse_package_file): Handle Requires.private
2005-07-14 13:07:31 +00:00
|
|
|
|
2012-11-19 08:19:48 -08:00
|
|
|
pkg->cflags = g_list_reverse (pkg->cflags);
|
|
|
|
|
pkg->libs = g_list_reverse (pkg->libs);
|
2007-02-21 22:21:14 +01:00
|
|
|
|
2005-07-14 13:04:01 +00:00
|
|
|
return pkg;
|
|
|
|
|
}
|