struct sparse_file *sparse_file_import(int fd, bool verbose, bool crc)
{
	int ret;
	sparse_header_t sparse_header;
	int64_t len;
	struct sparse_file *s;

	ret = read_all(fd, &sparse_header, sizeof(sparse_header));
	if (ret < 0) {
		verbose_error(verbose, ret, "header");
		return NULL;
	}

	if (sparse_header.magic != SPARSE_HEADER_MAGIC) {
		verbose_error(verbose, -EINVAL, "header magic");
		return NULL;
	}

	if (sparse_header.major_version != SPARSE_HEADER_MAJOR_VER) {
		verbose_error(verbose, -EINVAL, "header major version");
		return NULL;
	}

	if (sparse_header.file_hdr_sz < SPARSE_HEADER_LEN) {
		return NULL;
	}

	if (sparse_header.chunk_hdr_sz < sizeof(chunk_header_t)) {
		return NULL;
	}

	len = (int64_t)sparse_header.total_blks * sparse_header.blk_sz;
	s = sparse_file_new(sparse_header.blk_sz, len);
	if (!s) {
		verbose_error(verbose, -EINVAL, NULL);
		return NULL;
	}

	ret = lseek64(fd, 0, SEEK_SET);
	if (ret < 0) {
		verbose_error(verbose, ret, "seeking");
		sparse_file_destroy(s);
		return NULL;
	}

	s->verbose = verbose;

	ret = sparse_file_read(s, fd, true, crc);
	if (ret < 0) {
		sparse_file_destroy(s);
		return NULL;
	}

	return s;
}
static int process_chunk(struct sparse_file *s, int fd, off64_t offset,
		unsigned int chunk_hdr_sz, chunk_header_t *chunk_header,
		unsigned int cur_block, uint32_t *crc_ptr)
{
	int ret;
	unsigned int chunk_data_size;

	chunk_data_size = chunk_header->total_sz - chunk_hdr_sz;

	switch (chunk_header->chunk_type) {
		case CHUNK_TYPE_RAW:
			ret = process_raw_chunk(s, chunk_data_size, fd, offset,
					chunk_header->chunk_sz, cur_block, crc_ptr);
			if (ret < 0) {
				verbose_error(s->verbose, ret, "data block at %" PRId64, offset);
				return ret;
			}
			return chunk_header->chunk_sz;
		case CHUNK_TYPE_FILL:
			ret = process_fill_chunk(s, chunk_data_size, fd,
					chunk_header->chunk_sz, cur_block, crc_ptr);
			if (ret < 0) {
				verbose_error(s->verbose, ret, "fill block at %" PRId64, offset);
				return ret;
			}
			return chunk_header->chunk_sz;
		case CHUNK_TYPE_DONT_CARE:
			ret = process_skip_chunk(s, chunk_data_size, fd,
					chunk_header->chunk_sz, cur_block, crc_ptr);
			if (chunk_data_size != 0) {
				if (ret < 0) {
					verbose_error(s->verbose, ret, "skip block at %" PRId64, offset);
					return ret;
				}
			}
			return chunk_header->chunk_sz;
		case CHUNK_TYPE_CRC32:
			ret = process_crc32_chunk(fd, chunk_data_size, *crc_ptr);
			if (ret < 0) {
				verbose_error(s->verbose, -EINVAL, "crc block at %" PRId64,
						offset);
				return ret;
			}
			return 0;
		default:
			verbose_error(s->verbose, -EINVAL, "unknown block %04X at %" PRId64,
					chunk_header->chunk_type, offset);
	}

	return 0;
}
Beispiel #3
0
static void
parse_libs_private (Package *pkg, const char *str, const char *path)
{
  /*
    List of private libraries.  Private libraries are libraries which
    are needed in the case of static linking or on platforms not
    supporting inter-library dependencies.  They are not supposed to
    be used for libraries which are exposed through the library in
    question.  An example of an exposed library is GTK+ exposing Glib.
    A common example of a private library is libm.
    
    Generally, if include another library's headers in your own, it's
    a public dependency and not a private one.
  */
  
  char *trimmed;
  char **argv = NULL;
  int argc = 0;
  int result;
  
  if (pkg->libs_private_num > 0)
    {
      verbose_error ("Libs.private field occurs twice in '%s'\n", path);

      exit (1);
    }
  
  trimmed = trim_and_sub (pkg, str, path);

  if (trimmed && *trimmed)
    {
      result = poptParseArgvString (trimmed, &argc, &argv);

      if (result < 0)
        {
          verbose_error ("Couldn't parse Libs.private field into an argument vector: %s\n",
                         poptStrerror (result));

          exit (1);
        }
    }

  _do_parse_libs(pkg, argc, argv);

  g_free (argv);
  g_free (trimmed);

  pkg->libs_private_num++;
}
Beispiel #4
0
static void
parse_requires_private (Package *pkg, const char *str, const char *path)
{
  GSList *parsed;
  GSList *iter;
  char *trimmed;
  
  if (pkg->requires_private)
    {
      verbose_error ("Requires.private field occurs twice in '%s'\n", path);

      exit (1);
    }

  trimmed = trim_and_sub (pkg, str, path);
  parsed = parse_module_list (pkg, trimmed, path);
  g_free (trimmed);
  
  iter = parsed;
  while (iter != NULL)
    {
      Package *req;
      RequiredVersion *ver = iter->data;
      
      req = get_package (ver->name);

      if (req == NULL)
        {
          verbose_error ("Package '%s', required by '%s', not found\n",
                         ver->name, pkg->name ? pkg->name : path);
          
          exit (1);
        }

      if (pkg->required_versions == NULL)
        pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal);
      
      g_hash_table_insert (pkg->required_versions, ver->name, ver);
      
      pkg->requires_private = g_slist_prepend (pkg->requires_private, req);

      iter = g_slist_next (iter);
    }

  g_slist_free (parsed);
}
Beispiel #5
0
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);
}
Beispiel #6
0
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);
}
Beispiel #7
0
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);
}
Beispiel #8
0
static void
parse_libs (Package *pkg, const char *str, const char *path)
{
  /* Strip out -l and -L flags, put them in a separate list. */
  
  char *trimmed;
  char **argv = NULL;
  int argc = 0;
  int result;
  
  if (pkg->libs_num > 0)
    {
      verbose_error ("Libs field occurs twice in '%s'\n", path);

      exit (1);
    }
  
  trimmed = trim_and_sub (pkg, str, path);

  if (trimmed && *trimmed)
    {
      result = poptParseArgvString (trimmed, &argc, &argv);

      if (result < 0)
        {
          verbose_error ("Couldn't parse Libs field into an argument vector: %s\n",
                         poptStrerror (result));

          exit (1);
        }
    }

  _do_parse_libs(pkg, argc, argv);

  g_free (trimmed);
  g_free (argv);
  pkg->libs_num++;
}
Beispiel #9
0
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);
}
Beispiel #10
0
void
define_global_variable (const char *varname,
                        const char *varval)
{
  if (globals == NULL)
    globals = g_hash_table_new (g_str_hash, g_str_equal);

  if (g_hash_table_lookup (globals, varname))
    {
      verbose_error ("Variable '%s' defined twice globally\n", varname);
      exit (1);
    }
  
  g_hash_table_insert (globals, g_strdup (varname), g_strdup (varval));
      
  debug_spew ("Global variable definition '%s' = '%s'\n",
              varname, varval);
}
Beispiel #11
0
adlb_data_code xlb_struct_subscript_init(adlb_struct *s, adlb_subscript subscript,
                  bool validate_path, bool *b)
{
  adlb_data_code dc;

  adlb_struct_field *field;
  adlb_struct_field_type field_type;
  size_t sub_pos;

  // Initialize subscripts as a way to validate path
  bool init_nested = validate_path;
  dc = xlb_struct_lookup(s, subscript, init_nested, &field, &field_type, &sub_pos);
  ADLB_DATA_CHECK_CODE(dc);

  if (sub_pos == subscript.length)
  {
    // Entire subscript was consumed
    *b = field->initialized;
  }
  else
  {
    DEBUG("%zu vs %zu", sub_pos, subscript.length);
    if (validate_path)
    {
      verbose_error(ADLB_DATA_ERROR_SUBSCRIPT_NOT_FOUND,
          "Subscript invalid: [%.*s] (tail of [%.*s])",
          (int)(subscript.length - sub_pos),
          &((const char *)subscript.key)[sub_pos],
          (int)subscript.length, (const char*)subscript.key);
    }
    else
    {
      *b = false;
    }
  }

  return ADLB_DATA_SUCCESS;
}
Beispiel #12
0
/*
 * Format and output a call to the JavaScript alert() function.
 * The caller must ensure a JavaScript context.
 */
NSAPI_PUBLIC void output_alert(int type, char *info, char *details, int wait)
{
    char *wrapped=NULL;
    int err;

    if(type >= MAX_ERROR)
        type=DEFAULT_ERROR;

    wrapped=alert_word_wrap(details, WORD_WRAP_WIDTH, "\\n");

    if(!info) info="";
    fprintf(stdout, (wait) ? "confirm(\"" : "alert(\"");
    fprintf(stdout, "%s:%s\\n%s", error_headers[type], info, wrapped);
    if(type==FILE_ERROR || type==SYSTEM_ERROR)  {
        err = get_error();
        if(err != 0)
            fprintf(stdout,
                        "\\n\\nThe system returned error number %d, "
                        "which is %s.", err, verbose_error());
    }
    fprintf(stdout, "\");");

    FREE(wrapped);
}
Beispiel #13
0
static gboolean
process_package_args (const char *cmdline, GList **packages, FILE *log)
{
  gboolean success = TRUE;
  GList *reqs;

  reqs = parse_module_list (NULL, cmdline, "(command line arguments)");
  if (reqs == NULL)
    {
      fprintf (stderr, "Must specify package names on the command line\n");
      fflush (stderr);
      return FALSE;
    }

  for (; reqs != NULL; reqs = g_list_next (reqs))
    {
      Package *req;
      RequiredVersion *ver = reqs->data;

      /* override requested versions with cmdline options */
      if (required_exact_version)
        {
          g_free (ver->version);
          ver->comparison = EQUAL;
          ver->version = g_strdup (required_exact_version);
        }
      else if (required_atleast_version)
        {
          g_free (ver->version);
          ver->comparison = GREATER_THAN_EQUAL;
          ver->version = g_strdup (required_atleast_version);
        }
      else if (required_max_version)
        {
          g_free (ver->version);
          ver->comparison = LESS_THAN_EQUAL;
          ver->version = g_strdup (required_max_version);
        }

      if (want_short_errors)
        req = get_package_quiet (ver->name);
      else
        req = get_package (ver->name);

      if (log != NULL)
        {
          if (req == NULL)
            fprintf (log, "%s NOT-FOUND\n", ver->name);
          else
            fprintf (log, "%s %s %s\n", ver->name,
                     comparison_to_str (ver->comparison),
                     (ver->version == NULL) ? "(null)" : ver->version);
        }

      if (req == NULL)
        {
          success = FALSE;
          verbose_error ("No package '%s' found\n", ver->name);
          continue;
        }

      if (!version_test (ver->comparison, req->version, ver->version))
        {
          success = FALSE;
          verbose_error ("Requested '%s %s %s' but version of %s is %s\n",
                         ver->name,
                         comparison_to_str (ver->comparison),
                         ver->version,
                         req->name,
                         req->version);
          if (req->url)
            verbose_error ("You may find new versions of %s at %s\n",
                           req->name, req->url);
          continue;
        }

      *packages = g_list_prepend (*packages, req);
    }

  *packages = g_list_reverse (*packages);

  return success;
}
Beispiel #14
0
static void
verify_package (Package *pkg)
{
  GSList *requires = NULL;
  GSList *conflicts = NULL;
  GSList *system_directories = NULL;
  GSList *iter;
  GSList *requires_iter;
  GSList *conflicts_iter;
  GSList *system_dir_iter = NULL;
  int count;
  gchar *c_include_path;

  /* Be sure we have the required fields */

  if (pkg->key == NULL)
    {
      fprintf (stderr,
               "Internal pkg-config error, package with no key, please file a bug report\n");
      exit (1);
    }
  
  if (pkg->name == NULL)
    {
      verbose_error ("Package '%s' has no Name: field\n",
                     pkg->key);
      exit (1);
    }

  if (pkg->version == NULL)
    {
      verbose_error ("Package '%s' has no Version: field\n",
                     pkg->key);
      exit (1);
    }

  if (pkg->description == NULL)
    {
      verbose_error ("Package '%s' has no Description: field\n",
                     pkg->key);
      exit (1);
    }
  
  /* Make sure we have the right version for all requirements */

  iter = pkg->requires_private;

  while (iter != NULL)
    {
      Package *req = iter->data;
      RequiredVersion *ver = NULL;

      if (pkg->required_versions)
        ver = g_hash_table_lookup (pkg->required_versions,
                                   req->key);

      if (ver)
        {
          if (!version_test (ver->comparison, req->version, ver->version))
            {
              verbose_error ("Package '%s' requires '%s %s %s' but version of %s is %s\n",
                             pkg->name, req->key,
                             comparison_to_str (ver->comparison),
                             ver->version,
                             req->name,
                             req->version);
              if (req->url)
                verbose_error ("You may find new versions of %s at %s\n",
                               req->name, req->url);

              exit (1);
            }
        }
                                   
      iter = g_slist_next (iter);
    }

  /* Make sure we didn't drag in any conflicts via Requires
   * (inefficient algorithm, who cares)
   */
  
  recursive_fill_list (pkg, get_requires_private, &requires);
  conflicts = get_conflicts (pkg);

  requires_iter = requires;
  while (requires_iter != NULL)
    {
      Package *req = requires_iter->data;
      
      conflicts_iter = conflicts;

      while (conflicts_iter != NULL)
        {
          RequiredVersion *ver = conflicts_iter->data;

          if (version_test (ver->comparison,
                            req->version,
                            ver->version))
            {
              verbose_error ("Version %s of %s creates a conflict.\n"
                             "(%s %s %s conflicts with %s %s)\n",
                             req->version, req->name,
                             ver->name,
                             comparison_to_str (ver->comparison),
                             ver->version ? ver->version : "(any)",
                             ver->owner->name,
                             ver->owner->version);

              exit (1);
            }

          conflicts_iter = g_slist_next (conflicts_iter);
        }
      
      requires_iter = g_slist_next (requires_iter);
    }
  
  g_slist_free (requires);

  /* We make a list of system directories that gcc expects so we can remove
   * them.
   */
#ifndef G_OS_WIN32
  system_directories = g_slist_append (NULL, g_strdup ("/usr/include"));
#endif

  c_include_path = g_getenv ("C_INCLUDE_PATH");
  if (c_include_path != NULL)
    {
      system_directories = add_env_variable_to_list (system_directories, c_include_path);
    }
  
  c_include_path = g_getenv ("CPLUS_INCLUDE_PATH");
  if (c_include_path != NULL)
    {
      system_directories = add_env_variable_to_list (system_directories, c_include_path);
    }

  count = 0;
  iter = pkg->I_cflags;
  while (iter != NULL)
    {
      gint offset = 0;
      /* we put things in canonical -I/usr/include (vs. -I /usr/include) format,
       * but if someone changes it later we may as well be robust
       */
      if (((strncmp (iter->data, "-I", 2) == 0) && (offset = 2))||
          ((strncmp (iter->data, "-I ", 3) == 0) && (offset = 3)))
        {
	  if (offset == 0)
	    {
	      iter = iter->next;
	      continue;
	    }

	  system_dir_iter = system_directories;
	  while (system_dir_iter != NULL)
	    {
	      if (strcmp (system_dir_iter->data,
                          ((char*)iter->data) + offset) == 0)
		{
		  debug_spew ("Package %s has %s in Cflags\n",
			      pkg->name, (gchar *)iter->data);
		  if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") == NULL)
		    {
		      debug_spew ("Removing %s from cflags for %s\n", iter->data, pkg->key);
		      ++count;
		      iter->data = NULL;
		      
		      break;
		    }
		}
	      system_dir_iter = system_dir_iter->next;
	    }
        }

      iter = iter->next;
    }

  while (count)
    {
      pkg->I_cflags = g_slist_remove (pkg->I_cflags, NULL);
      --count;
    }

  g_slist_foreach (system_directories, (GFunc) g_free, NULL);
  g_slist_free (system_directories);

#ifdef PREFER_LIB64
#define SYSTEM_LIBDIR "/usr/lib64"
#else
#define SYSTEM_LIBDIR "/usr/lib"
#endif
  count = 0;
  iter = pkg->L_libs;
  while (iter != NULL)
    {
      if (strcmp (iter->data, "-L" SYSTEM_LIBDIR) == 0 ||
          strcmp (iter->data, "-L " SYSTEM_LIBDIR) == 0)
        {
          debug_spew ("Package %s has -L" SYSTEM_LIBDIR " in Libs\n",
                      pkg->name);
          if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_LIBS") == NULL)
            {              
              iter->data = NULL;
              ++count;
              debug_spew ("Removing -L" SYSTEM_LIBDIR " from libs for %s\n", pkg->key);
            }
        }

      iter = iter->next;
    }
#undef SYSTEM_LIBDIR

  while (count)
    {
      pkg->L_libs = g_slist_remove (pkg->L_libs, NULL);
      --count;
    }
}
Beispiel #15
0
static Package *
internal_get_package (const char *name, gboolean warn, gboolean check_compat)
{
  Package *pkg = NULL;
  const char *location;
  
  pkg = g_hash_table_lookup (packages, name);

  if (pkg)
    return pkg;

  debug_spew ("Looking for package '%s'\n", name);
  
  /* treat "name" as a filename if it ends in .pc and exists */
  if ( ends_in_dotpc (name) )
    {
      debug_spew ("Considering '%s' to be a filename rather than a package name\n", name);
      location = name;
    }
  else
    {
      /* See if we should auto-prefer the uninstalled version */
      if (!disable_uninstalled &&
          !name_ends_in_uninstalled (name))
        {
          char *un;

          un = g_strconcat (name, "-uninstalled", NULL);

          pkg = internal_get_package (un, FALSE, FALSE);

          g_free (un);
          
          if (pkg)
            {
              debug_spew ("Preferring uninstalled version of package '%s'\n", name);
              return pkg;
            }
        }
      
      location = g_hash_table_lookup (locations, name);
    }
  
  if (location == NULL && check_compat)
    {
      pkg = get_compat_package (name);

      if (pkg)
        {
          debug_spew ("Returning values for '%s' from a legacy -config script\n",
                      name);
          
          return pkg;
        }
    }
      
  if (location == NULL)
    {
      if (warn)
        verbose_error ("Package %s was not found in the pkg-config search path.\n"
                       "Perhaps you should add the directory containing `%s.pc'\n"
                       "to the PKG_CONFIG_PATH environment variable\n",
                       name, name);

      return NULL;
    }

  debug_spew ("Reading '%s' from file '%s'\n", name, location);
  pkg = parse_package_file (location, ignore_requires, ignore_private_libs);
  
  if (pkg == NULL)
    {
      debug_spew ("Failed to parse '%s'\n", location);
      return NULL;
    }
  
  if (strstr (location, "uninstalled.pc"))
    pkg->uninstalled = TRUE;
  
  if (location != name)
    pkg->key = g_strdup (name);
  else
    {
      /* need to strip package name out of the filename */
      int len = strlen (name);
      const char *end = name + (len - EXT_LEN);
      const char *start = end;

      while (start != name && *start != G_DIR_SEPARATOR)
        --start;

      g_assert (end >= start);
      
      pkg->key = g_strndup (start, end - start);
    }

  pkg->path_position =
    GPOINTER_TO_INT (g_hash_table_lookup (path_positions, pkg->key));

  debug_spew ("Path position of '%s' is %d\n",
              pkg->name, pkg->path_position);
  
  verify_package (pkg);

  debug_spew ("Adding '%s' to list of known packages, returning as package '%s'\n",
              pkg->key, name);
  
  g_hash_table_insert (packages, pkg->key, pkg);

  return pkg;
}
Beispiel #16
0
static void
parse_line (Package *pkg, const char *untrimmed, const char *path,
	    gboolean ignore_requires, gboolean ignore_private_libs,
	    gboolean ignore_requires_private)
{
  char *str;
  char *p;
  char *tag;

  debug_spew ("  line>%s\n", untrimmed);
  
  str = trim_string (untrimmed);
  
  if (*str == '\0') /* empty line */
    {
      g_free(str);
      return;
    }
  
  p = str;

  /* Get first word */
  while ((*p >= 'A' && *p <= 'Z') ||
	 (*p >= 'a' && *p <= 'z') ||
	 (*p >= '0' && *p <= '9') ||
	 *p == '_' || *p == '.')
    p++;

  tag = g_strndup (str, p - str);
  
  while (*p && isspace ((guchar)*p))
    ++p;

  if (*p == ':')
    {
      /* keyword */
      ++p;
      while (*p && isspace ((guchar)*p))
        ++p;

      if (strcmp (tag, "Name") == 0)
        parse_name (pkg, p, path);
      else if (strcmp (tag, "Description") == 0)
        parse_description (pkg, p, path);
      else if (strcmp (tag, "Version") == 0)
        parse_version (pkg, p, path);
      else if (strcmp (tag, "Requires.private") == 0)
	{
	  if (!ignore_requires_private)
	    parse_requires_private (pkg, p, path);
	}
      else if (strcmp (tag, "Requires") == 0)
	{
          if (ignore_requires == FALSE)
	    parse_requires (pkg, p, path);
          else
	    goto cleanup;
        }
      else if ((strcmp (tag, "Libs.private") == 0) && 
               ignore_private_libs == FALSE)
        parse_libs_private (pkg, p, path);
      else if (strcmp (tag, "Libs") == 0)
        parse_libs (pkg, p, path);
      else if (strcmp (tag, "Cflags") == 0 ||
               strcmp (tag, "CFlags") == 0)
        parse_cflags (pkg, p, path);
      else if (strcmp (tag, "Conflicts") == 0)
        parse_conflicts (pkg, p, path);
      else if (strcmp (tag, "URL") == 0)
        parse_url (pkg, p, path);
      else
        {
	  /* we don't error out on unknown keywords because they may
	   * represent additions to the .pc file format from future
	   * versions of pkg-config.  We do make a note of them in the
	   * debug spew though, in order to help catch mistakes in .pc
	   * files. */
          debug_spew ("Unknown keyword '%s' in '%s'\n",
		      tag, path);
        }
    }
  else if (*p == '=')
    {
      /* variable */
      char *varname;
      char *varval;
      
      ++p;
      while (*p && isspace ((guchar)*p))
        ++p;
      
      if (pkg->vars == NULL)
        pkg->vars = g_hash_table_new (g_str_hash, g_str_equal);

#ifdef G_OS_WIN32
      if (!dont_define_prefix && strcmp (tag, prefix_variable) == 0)
	{
	  /* This is the prefix variable. Try to guesstimate a value for it
	   * for this package from the location of the .pc file.
	   */

	  gchar *prefix = pkg->pcfiledir;
	  const int prefix_len = strlen (prefix);
	  const char *const lib_pkgconfig = "\\lib\\pkgconfig";
	  const char *const share_pkgconfig = "\\share\\pkgconfig";
	  const int lib_pkgconfig_len = strlen (lib_pkgconfig);
	  const int share_pkgconfig_len = strlen (share_pkgconfig);

	  if ((strlen (prefix) > lib_pkgconfig_len &&
	       pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0) ||
	      (strlen (prefix) > share_pkgconfig_len &&
	       pathnamecmp (prefix + prefix_len - share_pkgconfig_len, share_pkgconfig) == 0))
	    {
	      /* It ends in lib\pkgconfig or share\pkgconfig. Good. */
	      
	      gchar *q;
	      
	      orig_prefix = g_strdup (p);

	      prefix = g_strdup (prefix);
	      if (strlen (prefix) > lib_pkgconfig_len &&
		  pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0)
		prefix[prefix_len - lib_pkgconfig_len] = '\0';
	      else
		prefix[prefix_len - share_pkgconfig_len] = '\0';
	      
	      /* Turn backslashes into slashes or
	       * poptParseArgvString() will eat them when ${prefix}
	       * has been expanded in parse_libs().
	       */
	      q = prefix;
	      while (*q)
		{
		  if (*q == '\\')
		    *q = '/';
		  q++;
		}
	      varname = g_strdup (tag);
	      debug_spew (" Variable declaration, '%s' overridden with '%s'\n",
			  tag, prefix);
	      g_hash_table_insert (pkg->vars, varname, prefix);
	      goto cleanup;
	    }
	}
      else if (!dont_define_prefix &&
	       orig_prefix != NULL &&
	       strncmp (p, orig_prefix, strlen (orig_prefix)) == 0 &&
	       G_IS_DIR_SEPARATOR (p[strlen (orig_prefix)]))
	{
	  char *oldstr = str;

	  p = str = g_strconcat (g_hash_table_lookup (pkg->vars, prefix_variable), p + strlen (orig_prefix), NULL);
	  g_free (oldstr);
	}
#endif

      if (g_hash_table_lookup (pkg->vars, tag))
        {
          verbose_error ("Duplicate definition of variable '%s' in '%s'\n",
                         tag, path);

          exit (1);
        }

      varname = g_strdup (tag);
      varval = trim_and_sub (pkg, p, path);     

      debug_spew (" Variable declaration, '%s' has value '%s'\n",
                  varname, varval);
      g_hash_table_insert (pkg->vars, varname, varval);
  
    }

 cleanup:  
  g_free (str);
  g_free (tag);
}
Beispiel #17
0
int
main (int argc, char **argv)
{
  GString *str;
  GList *packages = NULL;
  char *search_path;
  char *pcbuilddir;
  gboolean need_newline;
  FILE *log = NULL;
  GError *error = NULL;
  GOptionContext *opt_context;

  /* This is here so that we get debug spew from the start,
   * during arg parsing
   */
  if (getenv ("PKG_CONFIG_DEBUG_SPEW"))
    {
      want_debug_spew = TRUE;
      want_verbose_errors = TRUE;
      want_silence_errors = FALSE;
      debug_spew ("PKG_CONFIG_DEBUG_SPEW variable enabling debug spew\n");
    }


  /* Get the built-in search path */
  init_pc_path ();
  if (pkg_config_pc_path == NULL)
    {
      /* Even when we override the built-in search path, we still use it later
       * to add pc_path to the virtual pkg-config package.
       */
      verbose_error ("Failed to get default search path\n");
      exit (1);
    }

  search_path = getenv ("PKG_CONFIG_PATH");
  if (search_path) 
    {
      add_search_dirs(search_path, G_SEARCHPATH_SEPARATOR_S);
    }
  if (getenv("PKG_CONFIG_LIBDIR") != NULL) 
    {
      add_search_dirs(getenv("PKG_CONFIG_LIBDIR"), G_SEARCHPATH_SEPARATOR_S);
    }
  else
    {
      add_search_dirs(pkg_config_pc_path, G_SEARCHPATH_SEPARATOR_S);
    }

  pcsysrootdir = getenv ("PKG_CONFIG_SYSROOT_DIR");
  if (pcsysrootdir)
    {
      define_global_variable ("pc_sysrootdir", pcsysrootdir);
    }
  else
    {
      define_global_variable ("pc_sysrootdir", "/");
    }

  pcbuilddir = getenv ("PKG_CONFIG_TOP_BUILD_DIR");
  if (pcbuilddir)
    {
      define_global_variable ("pc_top_builddir", pcbuilddir);
    }
  else
    {
      /* Default appropriate for automake */
      define_global_variable ("pc_top_builddir", "$(top_builddir)");
    }

  if (getenv ("PKG_CONFIG_DISABLE_UNINSTALLED"))
    {
      debug_spew ("disabling auto-preference for uninstalled packages\n");
      disable_uninstalled = TRUE;
    }

  /* Parse options */
  opt_context = g_option_context_new (NULL);
  g_option_context_add_main_entries (opt_context, options_table, NULL);
  if (!g_option_context_parse(opt_context, &argc, &argv, &error))
    {
      fprintf (stderr, "%s\n", error->message);
      return 1;
    }

  /* If no output option was set, then --exists is the default. */
  if (!output_opt_set)
    {
      debug_spew ("no output option set, defaulting to --exists\n");
      want_exists = TRUE;
    }

  /* Error printing is determined as follows:
   *     - for --exists, --*-version, --list-all and no options at all,
   *       it's off by default and --print-errors will turn it on
   *     - for all other output options, it's on by default and
   *       --silence-errors can turn it off
   */
  if (want_exists || want_list)
    {
      debug_spew ("Error printing disabled by default due to use of output "
                  "options --exists, --atleast/exact/max-version, "
                  "--list-all or no output option at all. Value of "
                  "--print-errors: %d\n",
                  want_verbose_errors);

      /* Leave want_verbose_errors unchanged, reflecting --print-errors */
    }
  else
    {
      debug_spew ("Error printing enabled by default due to use of output "
                  "options besides --exists, --atleast/exact/max-version or "
                  "--list-all. Value of --silence-errors: %d\n",
                  want_silence_errors);

      if (want_silence_errors && getenv ("PKG_CONFIG_DEBUG_SPEW") == NULL)
        want_verbose_errors = FALSE;
      else
        want_verbose_errors = TRUE;
    }

  if (want_verbose_errors)
    debug_spew ("Error printing enabled\n");
  else
    debug_spew ("Error printing disabled\n");

  if (want_static_lib_list)
    enable_private_libs();
  else
    disable_private_libs();

  /* honor Requires.private if any Cflags are requested or any static
   * libs are requested */

  if (pkg_flags & CFLAGS_ANY || want_requires_private || want_exists ||
      (want_static_lib_list && (pkg_flags & LIBS_ANY)))
    enable_requires_private();

  /* ignore Requires if no Cflags or Libs are requested */

  if (pkg_flags == 0 && !want_requires && !want_exists)
    disable_requires();

  /* Allow errors in .pc files when listing all. */
  if (want_list)
    parse_strict = FALSE;

  if (want_my_version)
    {
      printf ("%s\n", VERSION);
      return 0;
    }

  if (required_pkgconfig_version)
    {
      if (compare_versions (VERSION, required_pkgconfig_version) >= 0)
        return 0;
      else
        return 1;
    }

  package_init ();

  if (want_list)
    {
      print_package_list ();
      return 0;
    }

  /* Collect packages from remaining args */
  str = g_string_new ("");
  while (argc > 1)
    {
      argc--;
      argv++;

      g_string_append (str, *argv);
      g_string_append (str, " ");
    }

  g_option_context_free (opt_context);

  g_strstrip (str->str);

  if (getenv("PKG_CONFIG_LOG") != NULL)
    {
      log = fopen (getenv ("PKG_CONFIG_LOG"), "a");
      if (log == NULL)
	{
	  fprintf (stderr, "Cannot open log file: %s\n",
		   getenv ("PKG_CONFIG_LOG"));
	  exit (1);
	}
    }

  /* find and parse each of the packages specified */
  if (!process_package_args (str->str, &packages, log))
    return 1;

  if (log != NULL)
    fclose (log);

  g_string_free (str, TRUE);

  if (want_exists)
    return 0; /* if we got here, all the packages existed. */

  if (want_variable_list)
    {
      GList *tmp;
      tmp = packages;
      while (tmp != NULL)
        {
          Package *pkg = tmp->data;
          if (pkg->vars != NULL)
            g_hash_table_foreach(pkg->vars,
                                 &print_hashtable_key,
                                 NULL);
          tmp = g_list_next (tmp);
          if (tmp) printf ("\n");
        }
      need_newline = FALSE;
    }

  if (want_uninstalled)
    {
      /* See if > 0 pkgs (including dependencies recursively) were uninstalled */
      GList *tmp;
      tmp = packages;
      while (tmp != NULL)
        {
          Package *pkg = tmp->data;

          if (pkg_uninstalled (pkg))
            return 0;

          tmp = g_list_next (tmp);
        }

      return 1;
    }

  if (want_version)
    {
      GList *tmp;
      tmp = packages;
      while (tmp != NULL)
        {
          Package *pkg = tmp->data;

          printf ("%s\n", pkg->version);

          tmp = g_list_next (tmp);
        }
    }

 if (want_provides)
   {
     GList *tmp;
     tmp = packages;
     while (tmp != NULL)
       {
         Package *pkg = tmp->data;
         char *key;
         key = pkg->key;
         while (*key == '/')
           key++;
         if (strlen(key) > 0)
           printf ("%s = %s\n", key, pkg->version);
         tmp = g_list_next (tmp);
       }
   }

  if (want_requires)
    {
      GList *pkgtmp;
      for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp))
        {
          Package *pkg = pkgtmp->data;
          GList *reqtmp;

          /* process Requires: */
          for (reqtmp = pkg->requires; reqtmp != NULL; reqtmp = g_list_next (reqtmp))
            {
              Package *deppkg = reqtmp->data;
              RequiredVersion *req;
              req = g_hash_table_lookup(pkg->required_versions, deppkg->key);
              if ((req == NULL) || (req->comparison == ALWAYS_MATCH))
                printf ("%s\n", deppkg->key);
              else
                printf ("%s %s %s\n", deppkg->key,
                  comparison_to_str(req->comparison),
                  req->version);
            }
        }
    }
  if (want_requires_private)
    {
      GList *pkgtmp;
      for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp))
        {
          Package *pkg = pkgtmp->data;
          GList *reqtmp;
          /* process Requires.private: */
          for (reqtmp = pkg->requires_private; reqtmp != NULL; reqtmp = g_list_next (reqtmp))
            {

              Package *deppkg = reqtmp->data;
              RequiredVersion *req;

              if (g_list_find (pkg->requires, reqtmp->data))
                continue;

              req = g_hash_table_lookup(pkg->required_versions, deppkg->key);
              if ((req == NULL) || (req->comparison == ALWAYS_MATCH))
                printf ("%s\n", deppkg->key);
              else
                printf ("%s %s %s\n", deppkg->key,
                  comparison_to_str(req->comparison),
                  req->version);
            }
        }
    }
  
  /* Print all flags; then print a newline at the end. */
  need_newline = FALSE;

  if (variable_name)
    {
      char *str = packages_get_var (packages, variable_name);
      printf ("%s", str);
      g_free (str);
      need_newline = TRUE;
    }

  if (pkg_flags != 0)
    {
      char *str = packages_get_flags (packages, pkg_flags);
      printf ("%s", str);
      g_free (str);
      need_newline = TRUE;
    }

  if (need_newline)
    printf ("\n");

  return 0;
}
Beispiel #18
0
static void
parse_cflags (Package *pkg, const char *str, const char *path)
{
  /* Strip out -I flags, put them in a separate list. */
  
  char *trimmed;
  char **argv = NULL;
  int argc = 0;
  int result;
  int i;
  
  if (pkg->I_cflags || pkg->other_cflags)
    {
      verbose_error ("Cflags field occurs twice in '%s'\n", path);

      exit (1);
    }
  
  trimmed = trim_and_sub (pkg, str, path);

  if (trimmed && *trimmed)
    {
      result = poptParseArgvString (trimmed, &argc, &argv);

      if (result < 0)
        {
          verbose_error ("Couldn't parse Cflags field into an argument vector: %s\n",
                         poptStrerror (result));

          exit (1);
        }
    }

  i = 0;
  while (i < argc)
    {
      char *tmp = trim_string (argv[i]);
      char *arg = strdup_escape_shell(tmp);
      char *p = arg;
      g_free(tmp);

      if (p[0] == '-' &&
          p[1] == 'I')
        {
          p += 2;
          while (*p && isspace ((guchar)*p))
            ++p;

          pkg->I_cflags = g_slist_prepend (pkg->I_cflags,
                                           g_strconcat ("-I", p, NULL));

        } else {
          if (*arg != '\0')
            pkg->other_cflags = g_slist_prepend (pkg->other_cflags,
                                                 g_strdup (arg));
	  if (strcmp("-idirafter", arg) == 0) {
	      char *n;

	      tmp = trim_string(argv[++i]);
	      n = strdup_escape_shell(tmp);
	      pkg->other_cflags = g_slist_prepend(pkg->other_cflags, n);
	      g_free(tmp);
	  }
      }

      g_free (arg);
      
      ++i;
    }

  g_free (argv);
  g_free (trimmed);
}
Beispiel #19
0
Package*
parse_package_file (const char *path, gboolean ignore_requires,
		    gboolean ignore_private_libs,
		    gboolean ignore_requires_private)
{
  FILE *f;
  Package *pkg;
  GString *str;
  gboolean one_line = FALSE;
  
  f = fopen (path, "r");

  if (f == NULL)
    {
      verbose_error ("Failed to open '%s': %s\n",
                     path, strerror (errno));
      
      return NULL;
    }

  debug_spew ("Parsing package file '%s'\n", path);
  
  pkg = g_new0 (Package, 1);

  if (path)
    {
      pkg->pcfiledir = g_dirname (path);
    }
  else
    {
      debug_spew ("No pcfiledir determined for package\n");
      pkg->pcfiledir = g_strdup ("???????");
    }
  
  str = g_string_new ("");

  while (read_one_line (f, str))
    {
      one_line = TRUE;
      
      parse_line (pkg, str->str, path, ignore_requires, ignore_private_libs,
		  ignore_requires_private);

      g_string_truncate (str, 0);
    }

  if (!one_line)
    verbose_error ("Package file '%s' appears to be empty\n",
                   path);
  g_string_free (str, TRUE);
  fclose(f);

  /* make ->requires_private include a copy of the public requires too */
  pkg->requires_private = g_slist_concat(g_slist_copy (pkg->requires),
					 pkg->requires_private);
  
  pkg->requires = g_slist_reverse (pkg->requires);
  
  pkg->requires_private = g_slist_reverse (pkg->requires_private);

  pkg->I_cflags = g_slist_reverse (pkg->I_cflags);
  pkg->other_cflags = g_slist_reverse (pkg->other_cflags);

  pkg->l_libs = g_slist_reverse (pkg->l_libs);
  pkg->L_libs = g_slist_reverse (pkg->L_libs);
  pkg->other_libs = g_slist_reverse (pkg->other_libs);
  
  return pkg;
}
Beispiel #20
0
int
main (int argc, char **argv)
{
  static int want_my_version = 0;
  static int want_version = 0;
  static int want_libs = 0;
  static int want_cflags = 0;
  static int want_l_libs = 0;
  static int want_L_libs = 0;
  static int want_other_libs = 0;
  static int want_I_cflags = 0;
  static int want_other_cflags = 0;
  static int want_list = 0;
  static int want_static_lib_list = ENABLE_INDIRECT_DEPS;
  static int want_short_errors = 0;
  static int want_uninstalled = 0;
  static char *variable_name = NULL;
  static int want_exists = 0;
  static int want_provides = 0;
  static int want_requires = 0;
  static int want_requires_private = 0;
  static char *required_atleast_version = NULL;
  static char *required_exact_version = NULL;
  static char *required_max_version = NULL;
  static char *required_pkgconfig_version = NULL;
  static int want_silence_errors = 0;
  static int want_variable_list = 0;
  GString *str;
  GSList *packages = NULL;
  char *search_path;
  char *pcbuilddir;
  gboolean need_newline;
  FILE *log = NULL;
  GError *error = NULL;
  GOptionContext *opt_context;

  GOptionEntry options_table[] = {
    { "version", 0, 0, G_OPTION_ARG_NONE, &want_my_version,
      "output version of pkg-config", NULL },
    { "modversion", 0, 0, G_OPTION_ARG_NONE, &want_version,
      "output version for package", NULL },
    { "atleast-pkgconfig-version", 0, 0, G_OPTION_ARG_STRING,
      &required_pkgconfig_version,
      "require given version of pkg-config", "VERSION" },
    { "libs", 0, 0, G_OPTION_ARG_NONE, &want_libs,
      "output all linker flags", NULL },
    { "static", 0, 0, G_OPTION_ARG_NONE, &want_static_lib_list,
      "output linker flags for static linking", NULL },
    { "short-errors", 0, 0, G_OPTION_ARG_NONE, &want_short_errors,
      "print short errors", NULL },
    { "libs-only-l", 0, 0, G_OPTION_ARG_NONE, &want_l_libs,
      "output -l flags", NULL },
    { "libs-only-other", 0, 0, G_OPTION_ARG_NONE, &want_other_libs,
      "output other libs (e.g. -pthread)", NULL },
    { "libs-only-L", 0, 0, G_OPTION_ARG_NONE, &want_L_libs,
      "output -L flags", NULL },
    { "cflags", 0, 0, G_OPTION_ARG_NONE, &want_cflags,
      "output all pre-processor and compiler flags", NULL },
    { "cflags-only-I", 0, 0, G_OPTION_ARG_NONE, &want_I_cflags,
      "output -I flags", NULL },
    { "cflags-only-other", 0, 0, G_OPTION_ARG_NONE, &want_other_cflags,
      "output cflags not covered by the cflags-only-I option", NULL },
    { "variable", 0, 0, G_OPTION_ARG_STRING, &variable_name,
      "get the value of variable named NAME", "NAME" },
    { "define-variable", 0, 0, G_OPTION_ARG_CALLBACK, &define_variable_cb,
      "set variable NAME to VALUE", "NAME=VALUE" },
    { "exists", 0, 0, G_OPTION_ARG_NONE, &want_exists,
      "return 0 if the module(s) exist", NULL },
    { "print-variables", 0, 0, G_OPTION_ARG_NONE, &want_variable_list,
      "output list of variables defined by the module", NULL },
    { "uninstalled", 0, 0, G_OPTION_ARG_NONE, &want_uninstalled,
      "return 0 if the uninstalled version of one or more module(s) "
      "or their dependencies will be used", NULL },
    { "atleast-version", 0, 0, G_OPTION_ARG_STRING, &required_atleast_version,
      "return 0 if the module is at least version VERSION", "VERSION" },
    { "exact-version", 0, 0, G_OPTION_ARG_STRING, &required_exact_version,
      "return 0 if the module is at exactly version VERSION", "VERSION" },
    { "max-version", 0, 0, G_OPTION_ARG_STRING, &required_max_version,
      "return 0 if the module is at no newer than version VERSION", "VERSION" },
    { "list-all", 0, 0, G_OPTION_ARG_NONE, &want_list,
      "list all known packages", NULL },
    { "debug", 0, 0, G_OPTION_ARG_NONE, &want_debug_spew,
      "show verbose debug information", NULL },
    { "print-errors", 0, 0, G_OPTION_ARG_NONE, &want_verbose_errors,
      "show verbose information about missing or conflicting packages,"
      "default if --cflags or --libs given on the command line", NULL },
    { "silence-errors", 0, 0, G_OPTION_ARG_NONE, &want_silence_errors,
      "be silent about errors (default unless --cflags or --libs"
      "given on the command line)", NULL },
    { "errors-to-stdout", 0, 0, G_OPTION_ARG_NONE, &want_stdout_errors,
      "print errors from --print-errors to stdout not stderr", NULL },
    { "print-provides", 0, 0, G_OPTION_ARG_NONE, &want_provides,
      "print which packages the package provides", NULL },
    { "print-requires", 0, 0, G_OPTION_ARG_NONE, &want_requires,
      "print which packages the package requires", NULL },
    { "print-requires-private", 0, 0, G_OPTION_ARG_NONE, &want_requires_private,
      "print which packages the package requires for static linking", NULL },
#ifdef G_OS_WIN32
    { "dont-define-prefix", 0, 0, G_OPTION_ARG_NONE, &dont_define_prefix,
      "don't try to override the value of prefix for each .pc file found with "
      "a guesstimated value based on the location of the .pc file", NULL },
    { "prefix-variable", 0, 0, G_OPTION_ARG_STRING, &prefix_variable,
      "set the name of the variable that pkg-config automatically sets",
      "PREFIX" },
    { "msvc-syntax", 0, 0, G_OPTION_ARG_NONE, &msvc_syntax,
      "output -l and -L flags for the Microsoft compiler (cl)", NULL },
#endif
    { NULL, 0, 0, 0, NULL, NULL, NULL }
  };

  /* This is here so that we get debug spew from the start,
   * during arg parsing
   */
  if (getenv ("PKG_CONFIG_DEBUG_SPEW"))
    {
      want_debug_spew = TRUE;
      want_verbose_errors = TRUE;
      want_silence_errors = FALSE;
      debug_spew ("PKG_CONFIG_DEBUG_SPEW variable enabling debug spew\n");
    }


  /* Get the built-in search path */
  init_pc_path ();
  if (pkg_config_pc_path == NULL)
    {
      /* Even when we override the built-in search path, we still use it later
       * to add pc_path to the virtual pkg-config package.
       */
      verbose_error ("Failed to get default search path\n");
      exit (1);
    }

  search_path = getenv ("PKG_CONFIG_PATH");
  if (search_path) 
    {
      add_search_dirs(search_path, G_SEARCHPATH_SEPARATOR_S);
    }
  if (getenv("PKG_CONFIG_LIBDIR") != NULL) 
    {
      add_search_dirs(getenv("PKG_CONFIG_LIBDIR"), G_SEARCHPATH_SEPARATOR_S);
    }
  else
    {
      add_search_dirs(pkg_config_pc_path, G_SEARCHPATH_SEPARATOR_S);
    }

  pcsysrootdir = getenv ("PKG_CONFIG_SYSROOT_DIR");
  if (pcsysrootdir)
    {
      define_global_variable ("pc_sysrootdir", pcsysrootdir);
    }
  else
    {
      define_global_variable ("pc_sysrootdir", "/");
    }

  pcbuilddir = getenv ("PKG_CONFIG_TOP_BUILD_DIR");
  if (pcbuilddir)
    {
      define_global_variable ("pc_top_builddir", pcbuilddir);
    }
  else
    {
      /* Default appropriate for automake */
      define_global_variable ("pc_top_builddir", "$(top_builddir)");
    }

  if (getenv ("PKG_CONFIG_DISABLE_UNINSTALLED"))
    {
      debug_spew ("disabling auto-preference for uninstalled packages\n");
      disable_uninstalled = TRUE;
    }

  /* Parse options */
  opt_context = g_option_context_new (NULL);
  g_option_context_add_main_entries (opt_context, options_table, NULL);
  if (!g_option_context_parse(opt_context, &argc, &argv, &error))
    {
      fprintf (stderr, "%s\n", error->message);
      return 1;
    }


  /* Error printing is determined as follows:
   *     - for --cflags, --libs, etc. it's on by default
   *       and --silence-errors can turn it off
   *     - for --exists, --max-version, etc. and no options
   *       at all, it's off by default and --print-errors
   *       will turn it on
   */

  if (want_my_version ||
      want_version ||
      want_libs ||
      want_cflags ||
      want_l_libs ||
      want_L_libs ||
      want_other_libs ||
      want_I_cflags ||
      want_other_cflags ||
      want_list ||
      want_variable_list)
    {
      debug_spew ("Error printing enabled by default due to use of --version, --libs, --cflags, --libs-only-l, --libs-only-L, --libs-only-other, --cflags-only-I, --cflags-only-other or --list. Value of --silence-errors: %d\n", want_silence_errors);

      if (want_silence_errors && getenv ("PKG_CONFIG_DEBUG_SPEW") == NULL)
        want_verbose_errors = FALSE;
      else
        want_verbose_errors = TRUE;
    }
  else
    {
      debug_spew ("Error printing disabled by default, value of --print-errors: %d\n",
                  want_verbose_errors);

      /* Leave want_verbose_errors unchanged, reflecting --print-errors */
    }

  if (want_verbose_errors)
    debug_spew ("Error printing enabled\n");
  else
    debug_spew ("Error printing disabled\n");

  if (want_static_lib_list)
    enable_private_libs();
  else
    disable_private_libs();

  /* honor Requires.private if any Cflags are requested or any static
   * libs are requested */

  if (want_I_cflags || want_other_cflags || want_cflags ||
      want_requires_private || want_exists ||
      (want_static_lib_list && (want_libs || want_l_libs || want_L_libs)))
    enable_requires_private();

  /* ignore Requires if no Cflags or Libs are requested */

  if (!want_I_cflags && !want_other_cflags && !want_cflags &&
      !want_libs && !want_l_libs && !want_L_libs && !want_requires &&
      !want_exists)
    disable_requires();

  if (want_my_version)
    {
      printf ("%s\n", VERSION);
      return 0;
    }

  if (required_pkgconfig_version)
    {
      if (compare_versions (VERSION, required_pkgconfig_version) >= 0)
        return 0;
      else
        return 1;
    }

  package_init ();

  if (want_list)
    {
      print_package_list ();
      return 0;
    }

  /* Collect packages from remaining args */
  str = g_string_new ("");
  while (argc > 1)
    {
      argc--;
      argv++;

      g_string_append (str, *argv);
      g_string_append (str, " ");
    }

  g_option_context_free (opt_context);

  g_strstrip (str->str);

  if (getenv("PKG_CONFIG_LOG") != NULL)
    {
      log = fopen (getenv ("PKG_CONFIG_LOG"), "a");
      if (log == NULL)
	{
	  fprintf (stderr, "Cannot open log file: %s\n",
		   getenv ("PKG_CONFIG_LOG"));
	  exit (1);
	}
    }

  {
    gboolean failed = FALSE;
    GSList *reqs;
    GSList *iter;

    reqs = parse_module_list (NULL, str->str,
                              "(command line arguments)");

    iter = reqs;

    while (iter != NULL)
      {
        Package *req;
        RequiredVersion *ver = iter->data;

	/* override requested versions with cmdline options */
	if (required_exact_version)
	  {
	    g_free (ver->version);
	    ver->comparison = EQUAL;
	    ver->version = g_strdup (required_exact_version);
	  }
	else if (required_atleast_version)
	  {
	    g_free (ver->version);
	    ver->comparison = GREATER_THAN_EQUAL;
	    ver->version = g_strdup (required_atleast_version);
	  }
	else if (required_max_version)
	  {
	    g_free (ver->version);
	    ver->comparison = LESS_THAN_EQUAL;
	    ver->version = g_strdup (required_max_version);
	  }

        if (want_short_errors)
          req = get_package_quiet (ver->name);
        else
          req = get_package (ver->name);

	if (log != NULL)
	  {
	    if (req == NULL)
	      fprintf (log, "%s NOT-FOUND", ver->name);
	    else
	      fprintf (log, "%s %s %s", ver->name,
		       comparison_to_str (ver->comparison),
		       (ver->version == NULL) ? "(null)" : ver->version);
	    fprintf (log, "\n");
	  }

        if (req == NULL)
          {
            failed = TRUE;
            verbose_error ("No package '%s' found\n", ver->name);
            goto nextiter;
          }

        if (!version_test (ver->comparison, req->version, ver->version))
          {
            failed = TRUE;
            verbose_error ("Requested '%s %s %s' but version of %s is %s\n",
                           ver->name,
                           comparison_to_str (ver->comparison),
                           ver->version,
                           req->name,
                           req->version);

	    if (req->url)
	      verbose_error ("You may find new versions of %s at %s\n",
			     req->name, req->url);

            goto nextiter;
          }

        packages = g_slist_prepend (packages, req);

      nextiter:
        iter = g_slist_next (iter);
      }

    if (log != NULL)
      {
	fclose (log);
      }

    if (failed) {
      return 1;
    }

  if (want_variable_list)
    {
      GSList *tmp;
      tmp = packages;
      while (tmp != NULL)
        {
          Package *pkg = tmp->data;
          g_hash_table_foreach(pkg->vars,
                               &print_hashtable_key,
                               NULL);
          tmp = g_slist_next (tmp);
          if (tmp) printf ("\n");
        }
      need_newline = FALSE;
    }

  }

  g_string_free (str, TRUE);

  packages = g_slist_reverse (packages);

  if (packages == NULL)
    {
      fprintf (stderr, "Must specify package names on the command line\n");

      exit (1);
    }

  if (want_exists)
    return 0; /* if we got here, all the packages existed. */

  if (want_uninstalled)
    {
      /* See if > 0 pkgs (including dependencies recursively) were uninstalled */
      GSList *tmp;
      tmp = packages;
      while (tmp != NULL)
        {
          Package *pkg = tmp->data;

          if (pkg_uninstalled (pkg))
            return 0;

          tmp = g_slist_next (tmp);
        }

      return 1;
    }

  if (want_version)
    {
      GSList *tmp;
      tmp = packages;
      while (tmp != NULL)
        {
          Package *pkg = tmp->data;

          printf ("%s\n", pkg->version);

          tmp = g_slist_next (tmp);
        }
    }

 if (want_provides)
   {
     GSList *tmp;
     tmp = packages;
     while (tmp != NULL)
       {
         Package *pkg = tmp->data;
         char *key;
         key = pkg->key;
         while (*key == '/')
           key++;
         if (strlen(key) > 0)
           printf ("%s = %s\n", key, pkg->version);
         tmp = g_slist_next (tmp);
       }
   }

  if (want_requires)
    {
      GSList *pkgtmp;
      for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_slist_next (pkgtmp))
        {
          Package *pkg = pkgtmp->data;
          GSList *reqtmp;

          /* process Requires: */
          for (reqtmp = pkg->requires; reqtmp != NULL; reqtmp = g_slist_next (reqtmp))
            {
              Package *deppkg = reqtmp->data;
              RequiredVersion *req;
              req = g_hash_table_lookup(pkg->required_versions, deppkg->key);
              if ((req == NULL) || (req->comparison == ALWAYS_MATCH))
                printf ("%s\n", deppkg->key);
              else
                printf ("%s %s %s\n", deppkg->key,
                  comparison_to_str(req->comparison),
                  req->version);
            }
        }
    }
  if (want_requires_private)
    {
      GSList *pkgtmp;
      for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_slist_next (pkgtmp))
        {
          Package *pkg = pkgtmp->data;
          GSList *reqtmp;
          /* process Requires.private: */
          for (reqtmp = pkg->requires_private; reqtmp != NULL; reqtmp = g_slist_next (reqtmp))
            {

              Package *deppkg = reqtmp->data;
              RequiredVersion *req;

              if (g_slist_find (pkg->requires, reqtmp->data))
                continue;

              req = g_hash_table_lookup(pkg->required_versions, deppkg->key);
              if ((req == NULL) || (req->comparison == ALWAYS_MATCH))
                printf ("%s\n", deppkg->key);
              else
                printf ("%s %s %s\n", deppkg->key,
                  comparison_to_str(req->comparison),
                  req->version);
            }
        }
    }
  
  /* Print all flags; then print a newline at the end. */
  need_newline = FALSE;

  if (variable_name)
    {
      char *str = packages_get_var (packages, variable_name);
      printf ("%s", str);
      g_free (str);
      need_newline = TRUE;
    }

  if (want_I_cflags)
    {
      char *str = packages_get_I_cflags (packages);
      printf ("%s ", str);
      g_free (str);
      need_newline = TRUE;
    }
  else if (want_other_cflags)
    {
      char *str = packages_get_other_cflags (packages);
      printf ("%s ", str);
      g_free (str);
      need_newline = TRUE;
    }
  else if (want_cflags)
    {
      char *str = packages_get_all_cflags (packages);
      printf ("%s ", str);
      g_free (str);
      need_newline = TRUE;
    }

  if (want_l_libs)
    {
      char *str = packages_get_l_libs (packages);
      printf ("%s ", str);
      g_free (str);
      need_newline = TRUE;
    }
  else if (want_L_libs)
    {
      char *str = packages_get_L_libs (packages);
      printf ("%s ", str);
      g_free (str);
      need_newline = TRUE;
    }
  else if (want_other_libs)
    {
      char *str = packages_get_other_libs (packages);
      printf ("%s ", str);
      g_free (str);
      need_newline = TRUE;
    }
  else if (want_libs)
    {
      char *str = packages_get_all_libs (packages);
      printf ("%s ", str);
      g_free (str);
      need_newline = TRUE;
    }

  if (need_newline)
    printf ("\n");

  return 0;
}
Beispiel #21
0
static char *
trim_and_sub (Package *pkg, const char *str, const char *path)
{
  char *trimmed;
  GString *subst;
  char *p;
  
  trimmed = trim_string (str);

  subst = g_string_new ("");

  p = trimmed;
  while (*p)
    {
      if (p[0] == '$' &&
          p[1] == '$')
        {
          /* escaped $ */
          g_string_append_c (subst, '$');
          p += 2;
        }
      else if (p[0] == '$' &&
               p[1] == '{')
        {
          /* variable */
          char *var_start;
          char *varname;
          char *varval;
          
          var_start = &p[2];

          /* Get up to close brace. */
          while (*p && *p != '}')
            ++p;

          varname = g_strndup (var_start, p - var_start);

          ++p; /* past brace */
          
          varval = package_get_var (pkg, varname);
          
          if (varval == NULL)
            {
              verbose_error ("Variable '%s' not defined in '%s'\n",
                             varname, path);
              
              exit (1);
            }

          g_free (varname);

          g_string_append (subst, varval);
          g_free (varval);
        }
      else
        {
          g_string_append_c (subst, *p);

          ++p;          
        }
    }

  g_free (trimmed);
  p = subst->str;
  g_string_free (subst, FALSE);

  return p;
}
Beispiel #22
0
GSList*
parse_module_list (Package *pkg, const char *str, const char *path)
{
  GSList *split;
  GSList *iter;
  GSList *retval = NULL;

  split = split_module_list (str, path);
  
  iter = split;
  while (iter != NULL)
    {
      RequiredVersion *ver;
      char *p;
      char *start;
      
      p = iter->data;

      ver = g_new0 (RequiredVersion, 1);
      ver->comparison = ALWAYS_MATCH;
      ver->owner = pkg;
      retval = g_slist_prepend (retval, ver);
      
      while (*p && MODULE_SEPARATOR (*p))
        ++p;
      
      start = p;

      while (*p && !isspace ((guchar)*p))
        ++p;

      while (*p && MODULE_SEPARATOR (*p))
        {
          *p = '\0';
          ++p;
        }

      if (*start == '\0')
        {
          verbose_error ("Empty package name in Requires or Conflicts in file '%s'\n", path);
          
          exit (1);
        }
      
      ver->name = g_strdup (start);

      start = p;

      while (*p && !isspace ((guchar)*p))
        ++p;

      while (*p && isspace ((guchar)*p))
        {
          *p = '\0';
          ++p;
        }
      
      if (*start != '\0')
        {
          if (strcmp (start, "=") == 0)
            ver->comparison = EQUAL;
          else if (strcmp (start, ">=") == 0)
            ver->comparison = GREATER_THAN_EQUAL;
          else if (strcmp (start, "<=") == 0)
            ver->comparison = LESS_THAN_EQUAL;
          else if (strcmp (start, ">") == 0)
            ver->comparison = GREATER_THAN;
          else if (strcmp (start, "<") == 0)
            ver->comparison = LESS_THAN;
          else if (strcmp (start, "!=") == 0)
            ver->comparison = NOT_EQUAL;
          else
            {
              verbose_error ("Unknown version comparison operator '%s' after package name '%s' in file '%s'\n", start, ver->name, path);
              
              exit (1);
            }
        }

      start = p;
      
      while (*p && !MODULE_SEPARATOR (*p))
        ++p;

      while (*p && MODULE_SEPARATOR (*p))
        {
          *p = '\0';
          ++p;
        }
      
      if (ver->comparison != ALWAYS_MATCH && *start == '\0')
        {
          verbose_error ("Comparison operator but no version after package name '%s' in file '%s'\n", ver->name, path);
          
          exit (1);
        }

      if (*start != '\0')
        {
          ver->version = g_strdup (start);
        }

      g_assert (ver->name);
      
      iter = g_slist_next (iter);
    }

  g_slist_foreach (split, (GFunc) g_free, NULL);
  g_slist_free (split);

  retval = g_slist_reverse (retval);

  return retval;
}