<commit_before>/*
 * config.c :  reading configuration information
 *
 * ====================================================================
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 */




#define APR_WANT_STRFUNC
#define APR_WANT_MEMFUNC
#include <apr_want.h>

#include <apr_general.h>
#include <apr_lib.h>
#include "svn_error.h"
#include "svn_pools.h"
#include "config_impl.h"

#include "svn_private_config.h"





/* Section table entries. */
typedef struct cfg_section_t cfg_section_t;
struct cfg_section_t
{
  /* The section name. */
  const char *name;

  /* The section name, converted into a hash key. */
  const char *hash_key;

  /* Table of cfg_option_t's. */
  apr_hash_t *options;
};


/* Option table entries. */
typedef struct cfg_option_t cfg_option_t;
struct cfg_option_t
{
  /* The option name. */
  const char *name;

  /* The option name, converted into a hash key. */
  const char *hash_key;

  /* The unexpanded option value. */
  const char *value;

  /* The expanded option value. */
  const char *x_value;

  /* Expansion flag. If this is TRUE, this value has already been expanded.
     In this case, if x_value is NULL, no expansions were necessary,
     and value should be used directly. */
  svn_boolean_t expanded;
};




svn_error_t *
svn_config_read(svn_config_t **cfgp, const char *file,
                svn_boolean_t must_exist, apr_pool_t *pool)
{
  svn_config_t *cfg = apr_palloc(pool, sizeof(*cfg));
  svn_error_t *err;

  cfg->sections = apr_hash_make(pool);
  cfg->pool = pool;
  cfg->x_pool = svn_pool_create(pool);
  cfg->x_values = FALSE;
  cfg->tmp_key = svn_stringbuf_create("", pool);
  cfg->tmp_value = svn_stringbuf_create("", pool);

  /* Yes, this is platform-specific code in Subversion, but there's no
     practical way to migrate it into APR, as it's simultaneously
     Subversion-specific and Windows-specific.  Even if we eventually
     want to have APR offer a generic config-reading interface, it
     makes sense to test it here first and migrate it later. */
#ifdef WIN32
  if (0 == strncmp(file, SVN_REGISTRY_PREFIX, SVN_REGISTRY_PREFIX_LEN))
    err = svn_config__parse_registry(cfg, file + SVN_REGISTRY_PREFIX_LEN,
                                     must_exist, pool);
  else
#endif /* WIN32 */
    err = svn_config__parse_file(cfg, file, must_exist, pool);

  if (err != SVN_NO_ERROR)
    return err;
  else
    *cfgp = cfg;

  return SVN_NO_ERROR;
}



/* Read various configuration sources into *CFGP, in this order, with
 * later reads overriding the results of earlier ones:
 *
 *    1. SYS_REGISTRY_PATH   (only on Win32, but ignored if NULL)
 *
 *    2. SYS_FILE_PATH       (everywhere, but ignored if NULL)
 *
 *    3. USR_REGISTRY_PATH   (only on Win32, but ignored if NULL)
 *
 *    4. USR_FILE_PATH       (everywhere, but ignored if NULL)
 *
 * Allocate *CFGP in POOL.  Even if no configurations are read,
 * allocate an empty *CFGP.
 */
static svn_error_t *
read_all(svn_config_t **cfgp,
         const char *sys_registry_path,
         const char *usr_registry_path,
         const char *sys_file_path,
         const char *usr_file_path,
         apr_pool_t *pool)
{
  svn_boolean_t red_config = FALSE;  /* "red" is the past tense of "read" */

  /*** Read system-wide configurations first... ***/

#ifdef WIN32
  if (sys_registry_path)
    {
      SVN_ERR(svn_config_read(cfgp, sys_registry_path, FALSE, pool));
      red_config = TRUE;
    }
#endif /* WIN32 */

  if (sys_file_path)
    {
      if (red_config)
        SVN_ERR(svn_config_merge(*cfgp, sys_file_path, FALSE));
      else
        {
          SVN_ERR(svn_config_read(cfgp, sys_file_path, FALSE, pool));
          red_config = TRUE;
        }
    }

  /*** ...followed by per-user configurations. ***/

#ifdef WIN32
  if (usr_registry_path)
    {
      if (red_config)
        SVN_ERR(svn_config_merge(*cfgp, usr_registry_path, FALSE));
      else
        {
          SVN_ERR(svn_config_read(cfgp, usr_registry_path, FALSE, pool));
          red_config = TRUE;
        }
    }
#endif /* WIN32 */

  if (usr_file_path)
    {
      if (red_config)
        SVN_ERR(svn_config_merge(*cfgp, usr_file_path, FALSE));
      else
        {
          SVN_ERR(svn_config_read(cfgp, usr_file_path, FALSE, pool));
          red_config = TRUE;
        }
    }

  if (! red_config)
    *cfgp = NULL;

  return SVN_NO_ERROR;
}


/* CONFIG_DIR provides an override for the default behavior of reading
   the default set of overlay files described by read_all()'s doc
   string. */
static svn_error_t *
get_category_config(svn_config_t **cfg,
                    const char *config_dir,
                    const char *category,
                    apr_pool_t *pool)
{
  const char *usr_reg_path = NULL, *sys_reg_path = NULL;
  const char *usr_cfg_path, *sys_cfg_path;
  svn_error_t *err = NULL;

  *cfg = NULL;

  if (! config_dir)
    {
#ifdef WIN32
      sys_reg_path = apr_pstrcat(pool, SVN_REGISTRY_SYS_CONFIG_PATH,
                                 category, NULL);
      usr_reg_path = apr_pstrcat(pool, SVN_REGISTRY_USR_CONFIG_PATH,
                                 category, NULL);
#endif /* WIN32 */

      error = svn_config__sys_config_path(&sys_cfg_path, category, pool);
      if ((err) && (err->apr_err == SVN_ERR_BAD_FILENAME))
        {
          sys_cfg_path = NULL;
          svn_error_clear(err);
        }<commit_msg>Followup to r38053: fix broken build.<commit_after>/*
 * config.c :  reading configuration information
 *
 * ====================================================================
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 */




#define APR_WANT_STRFUNC
#define APR_WANT_MEMFUNC
#include <apr_want.h>

#include <apr_general.h>
#include <apr_lib.h>
#include "svn_error.h"
#include "svn_pools.h"
#include "config_impl.h"

#include "svn_private_config.h"





/* Section table entries. */
typedef struct cfg_section_t cfg_section_t;
struct cfg_section_t
{
  /* The section name. */
  const char *name;

  /* The section name, converted into a hash key. */
  const char *hash_key;

  /* Table of cfg_option_t's. */
  apr_hash_t *options;
};


/* Option table entries. */
typedef struct cfg_option_t cfg_option_t;
struct cfg_option_t
{
  /* The option name. */
  const char *name;

  /* The option name, converted into a hash key. */
  const char *hash_key;

  /* The unexpanded option value. */
  const char *value;

  /* The expanded option value. */
  const char *x_value;

  /* Expansion flag. If this is TRUE, this value has already been expanded.
     In this case, if x_value is NULL, no expansions were necessary,
     and value should be used directly. */
  svn_boolean_t expanded;
};




svn_error_t *
svn_config_read(svn_config_t **cfgp, const char *file,
                svn_boolean_t must_exist, apr_pool_t *pool)
{
  svn_config_t *cfg = apr_palloc(pool, sizeof(*cfg));
  svn_error_t *err;

  cfg->sections = apr_hash_make(pool);
  cfg->pool = pool;
  cfg->x_pool = svn_pool_create(pool);
  cfg->x_values = FALSE;
  cfg->tmp_key = svn_stringbuf_create("", pool);
  cfg->tmp_value = svn_stringbuf_create("", pool);

  /* Yes, this is platform-specific code in Subversion, but there's no
     practical way to migrate it into APR, as it's simultaneously
     Subversion-specific and Windows-specific.  Even if we eventually
     want to have APR offer a generic config-reading interface, it
     makes sense to test it here first and migrate it later. */
#ifdef WIN32
  if (0 == strncmp(file, SVN_REGISTRY_PREFIX, SVN_REGISTRY_PREFIX_LEN))
    err = svn_config__parse_registry(cfg, file + SVN_REGISTRY_PREFIX_LEN,
                                     must_exist, pool);
  else
#endif /* WIN32 */
    err = svn_config__parse_file(cfg, file, must_exist, pool);

  if (err != SVN_NO_ERROR)
    return err;
  else
    *cfgp = cfg;

  return SVN_NO_ERROR;
}



/* Read various configuration sources into *CFGP, in this order, with
 * later reads overriding the results of earlier ones:
 *
 *    1. SYS_REGISTRY_PATH   (only on Win32, but ignored if NULL)
 *
 *    2. SYS_FILE_PATH       (everywhere, but ignored if NULL)
 *
 *    3. USR_REGISTRY_PATH   (only on Win32, but ignored if NULL)
 *
 *    4. USR_FILE_PATH       (everywhere, but ignored if NULL)
 *
 * Allocate *CFGP in POOL.  Even if no configurations are read,
 * allocate an empty *CFGP.
 */
static svn_error_t *
read_all(svn_config_t **cfgp,
         const char *sys_registry_path,
         const char *usr_registry_path,
         const char *sys_file_path,
         const char *usr_file_path,
         apr_pool_t *pool)
{
  svn_boolean_t red_config = FALSE;  /* "red" is the past tense of "read" */

  /*** Read system-wide configurations first... ***/

#ifdef WIN32
  if (sys_registry_path)
    {
      SVN_ERR(svn_config_read(cfgp, sys_registry_path, FALSE, pool));
      red_config = TRUE;
    }
#endif /* WIN32 */

  if (sys_file_path)
    {
      if (red_config)
        SVN_ERR(svn_config_merge(*cfgp, sys_file_path, FALSE));
      else
        {
          SVN_ERR(svn_config_read(cfgp, sys_file_path, FALSE, pool));
          red_config = TRUE;
        }
    }

  /*** ...followed by per-user configurations. ***/

#ifdef WIN32
  if (usr_registry_path)
    {
      if (red_config)
        SVN_ERR(svn_config_merge(*cfgp, usr_registry_path, FALSE));
      else
        {
          SVN_ERR(svn_config_read(cfgp, usr_registry_path, FALSE, pool));
          red_config = TRUE;
        }
    }
#endif /* WIN32 */

  if (usr_file_path)
    {
      if (red_config)
        SVN_ERR(svn_config_merge(*cfgp, usr_file_path, FALSE));
      else
        {
          SVN_ERR(svn_config_read(cfgp, usr_file_path, FALSE, pool));
          red_config = TRUE;
        }
    }

  if (! red_config)
    *cfgp = NULL;

  return SVN_NO_ERROR;
}


/* CONFIG_DIR provides an override for the default behavior of reading
   the default set of overlay files described by read_all()'s doc
   string. */
static svn_error_t *
get_category_config(svn_config_t **cfg,
                    const char *config_dir,
                    const char *category,
                    apr_pool_t *pool)
{
  const char *usr_reg_path = NULL, *sys_reg_path = NULL;
  const char *usr_cfg_path, *sys_cfg_path;
  svn_error_t *err = NULL;

  *cfg = NULL;

  if (! config_dir)
    {
#ifdef WIN32
      sys_reg_path = apr_pstrcat(pool, SVN_REGISTRY_SYS_CONFIG_PATH,
                                 category, NULL);
      usr_reg_path = apr_pstrcat(pool, SVN_REGISTRY_USR_CONFIG_PATH,
                                 category, NULL);
#endif /* WIN32 */

      err = svn_config__sys_config_path(&sys_cfg_path, category, pool);
      if ((err) && (err->apr_err == SVN_ERR_BAD_FILENAME))
        {
          sys_cfg_path = NULL;
          svn_error_clear(err);
        }
{'fraction_non_alphanumeric': 0.11803005008347245, 'fraction_numerical': 0.006093489148580968, 'mean_word_length': 2.8786014891550664, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4988561', 'n_tokens_mistral': 4081, 'n_tokens_neox': 3908, 'n_words': 1103}