⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 config_file.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * config_file.c :  parsing configuration files * * ==================================================================== * 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/. * ==================================================================== */#include <apr_lib.h>#include <apr_md5.h>#include <apr_env.h>#include "config_impl.h"#include "svn_io.h"#include "svn_types.h"#include "svn_path.h"#include "svn_auth.h"#include "svn_subst.h"#include "svn_utf.h"#include "svn_pools.h"#include "svn_user.h"#include "svn_private_config.h"/* File parsing context */typedef struct parse_context_t{  /* This config struct and file */  svn_config_t *cfg;  const char *file;  /* The file descriptor */  svn_stream_t *stream;  /* The current line in the file */  int line;  /* Cached ungotten character  - streams don't support ungetc()     [emulate it] */  int ungotten_char;  svn_boolean_t have_ungotten_char;  /* Temporary strings, allocated from the temp pool */  svn_stringbuf_t *section;  svn_stringbuf_t *option;  svn_stringbuf_t *value;} parse_context_t;/* Emulate getc() because streams don't support it. * * In order to be able to ungetc(), use the CXT instead of the stream * to be able to store the 'ungotton' character. * */static APR_INLINE svn_error_t *parser_getc(parse_context_t *ctx, int *c){  if (ctx->have_ungotten_char)    {      *c = ctx->ungotten_char;      ctx->have_ungotten_char = FALSE;    }  else    {      char char_buf;      apr_size_t readlen = 1;      SVN_ERR(svn_stream_read(ctx->stream, &char_buf, &readlen));      if (readlen == 1)        *c = char_buf;      else        *c = EOF;    }  return SVN_NO_ERROR;}/* Emulate ungetc() because streams don't support it. * * Use CTX to store the ungotten character C. */static APR_INLINE svn_error_t *parser_ungetc(parse_context_t *ctx, int c){  ctx->ungotten_char = c;  ctx->have_ungotten_char = TRUE;  return SVN_NO_ERROR;}/* Eat chars from STREAM until encounter non-whitespace, newline, or EOF.   Set *PCOUNT to the number of characters eaten, not counting the   last one, and return the last char read (the one that caused the   break).  */static APR_INLINE svn_error_t *skip_whitespace(parse_context_t *ctx, int *c, int *pcount){  int ch;  int count = 0;  SVN_ERR(parser_getc(ctx, &ch));  while (ch != EOF && ch != '\n' && apr_isspace(ch))    {      ++count;      SVN_ERR(parser_getc(ctx, &ch));    }  *pcount = count;  *c = ch;  return SVN_NO_ERROR;}/* Skip to the end of the line (or file).  Returns the char that ended   the line; the char is either EOF or newline. */static APR_INLINE svn_error_t *skip_to_eoln(parse_context_t *ctx, int *c){  int ch;  SVN_ERR(parser_getc(ctx, &ch));  while (ch != EOF && ch != '\n')    SVN_ERR(parser_getc(ctx, &ch));  *c = ch;  return SVN_NO_ERROR;}/* Parse a single option value */static svn_error_t *parse_value(int *pch, parse_context_t *ctx){  svn_boolean_t end_of_val = FALSE;  int ch;  /* Read the first line of the value */  svn_stringbuf_setempty(ctx->value);  SVN_ERR(parser_getc(ctx, &ch));  while (ch != EOF && ch != '\n')    /* last ch seen was ':' or '=' in parse_option. */    {      const char char_from_int = ch;      svn_stringbuf_appendbytes(ctx->value, &char_from_int, 1);      SVN_ERR(parser_getc(ctx, &ch));    }  /* Leading and trailing whitespace is ignored. */  svn_stringbuf_strip_whitespace(ctx->value);  /* Look for any continuation lines. */  for (;;)    {      if (ch == EOF || end_of_val)        {          /* At end of file. The value is complete, there can't be             any continuation lines. */          svn_config_set(ctx->cfg, ctx->section->data,                         ctx->option->data, ctx->value->data);          break;        }      else        {          int count;          ++ctx->line;          SVN_ERR(skip_whitespace(ctx, &ch, &count));          switch (ch)            {            case '\n':              /* The next line was empty. Ergo, it can't be a                 continuation line. */              ++ctx->line;              end_of_val = TRUE;              continue;            case EOF:              /* This is also an empty line. */              end_of_val = TRUE;              continue;            default:              if (count == 0)                {                  /* This line starts in the first column.  That means                     it's either a section, option or comment.  Put                     the char back into the stream, because it doesn't                     belong to us. */                  SVN_ERR(parser_ungetc(ctx, ch));                  end_of_val = TRUE;                }              else                {                  /* This is a continuation line. Read it. */                  svn_stringbuf_appendbytes(ctx->value, " ", 1);                  while (ch != EOF && ch != '\n')                    {                      const char char_from_int = ch;                      svn_stringbuf_appendbytes(ctx->value,                                                &char_from_int, 1);                      SVN_ERR(parser_getc(ctx, &ch));                    }                  /* Trailing whitespace is ignored. */                  svn_stringbuf_strip_whitespace(ctx->value);                }            }        }    }  *pch = ch;  return SVN_NO_ERROR;}/* Parse a single option */static svn_error_t *parse_option(int *pch, parse_context_t *ctx, apr_pool_t *pool){  svn_error_t *err = SVN_NO_ERROR;  int ch;  svn_stringbuf_setempty(ctx->option);  ch = *pch;   /* Yes, the first char is relevant. */  while (ch != EOF && ch != ':' && ch != '=' && ch != '\n')    {      const char char_from_int = ch;      svn_stringbuf_appendbytes(ctx->option, &char_from_int, 1);      SVN_ERR(parser_getc(ctx, &ch));    }  if (ch != ':' && ch != '=')    {      ch = EOF;      err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,                              "%s:%d: Option must end with ':' or '='",                              svn_path_local_style(ctx->file, pool),                              ctx->line);    }  else    {      /* Whitespace around the name separator is ignored. */      svn_stringbuf_strip_whitespace(ctx->option);      err = parse_value(&ch, ctx);    }  *pch = ch;  return err;}/* Read chars until enounter ']', then skip everything to the end of * the line.  Set *PCH to the character that ended the line (either * newline or EOF), and set CTX->section to the string of characters * seen before ']'. *  * This is meant to be called immediately after reading the '[' that * starts a section name. */static svn_error_t *parse_section_name(int *pch, parse_context_t *ctx, apr_pool_t *pool){  svn_error_t *err = SVN_NO_ERROR;  int ch;  svn_stringbuf_setempty(ctx->section);  SVN_ERR(parser_getc(ctx, &ch));  while (ch != EOF && ch != ']' && ch != '\n')    {      const char char_from_int = ch;      svn_stringbuf_appendbytes(ctx->section, &char_from_int, 1);      SVN_ERR(parser_getc(ctx, &ch));    }  if (ch != ']')    {      ch = EOF;      err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL,                              "%s:%d: Section header must end with ']'",                              svn_path_local_style(ctx->file, pool),                              ctx->line);    }  else    {      /* Everything from the ']' to the end of the line is ignored. */      SVN_ERR(skip_to_eoln(ctx, &ch));      if (ch != EOF)        ++ctx->line;    }  *pch = ch;  return err;}svn_error_t *svn_config__sys_config_path(const char **path_p,                            const char *fname,                            apr_pool_t *pool){  /* ### This never actually returns error in practice.  Perhaps the     prototype should change? */  *path_p = NULL;  /* Note that even if fname is null, svn_path_join_many will DTRT. */#ifdef WIN32  {    const char *folder;    SVN_ERR(svn_config__win_config_path(&folder, TRUE, pool));    *path_p = svn_path_join_many(pool, folder,                                 SVN_CONFIG__SUBDIRECTORY, fname, NULL);  }#else  /* ! WIN32 */  *path_p = svn_path_join_many(pool, SVN_CONFIG__SYS_DIRECTORY, fname, NULL);#endif /* WIN32 */  return SVN_NO_ERROR;}svn_error_t *svn_config__user_config_path(const char *config_dir,                             const char **path_p,                             const char *fname,                             apr_pool_t *pool){  /* ### This never actually returns error in practice.  Perhaps the     prototype should change? */  *path_p = NULL;  /* Note that even if fname is null, svn_path_join_many will DTRT. */  if (config_dir)    {      *path_p = svn_path_join_many(pool, config_dir, fname, NULL);      return SVN_NO_ERROR;    }  #ifdef WIN32  {    const char *folder;    SVN_ERR(svn_config__win_config_path(&folder, FALSE, pool));    *path_p = svn_path_join_many(pool, folder,                                 SVN_CONFIG__SUBDIRECTORY, fname, NULL);  }#else  /* ! WIN32 */  {    const char *homedir = svn_user_get_homedir(pool);     if (! homedir)      return SVN_NO_ERROR;    *path_p = svn_path_join_many(pool,                                 svn_path_canonicalize(homedir, pool),                                 SVN_CONFIG__USR_DIRECTORY, fname, NULL);  }#endif /* WIN32 */  return SVN_NO_ERROR;}/*** Exported interfaces. ***/svn_error_t *svn_config__parse_file(svn_config_t *cfg, const char *file,                       svn_boolean_t must_exist, apr_pool_t *pool){  svn_error_t *err = SVN_NO_ERROR;  parse_context_t ctx;  int ch, count;  apr_file_t *f;  /* No need for buffering; a translated stream buffers */  err = svn_io_file_open(&f, file, APR_BINARY | APR_READ,                         APR_OS_DEFAULT, pool);  if (! must_exist && err && APR_STATUS_IS_ENOENT(err->apr_err))    {      svn_error_clear(err);      return SVN_NO_ERROR;    }  else    SVN_ERR(err);  ctx.cfg = cfg;  ctx.file = file;  ctx.stream = svn_subst_stream_translated(svn_stream_from_aprfile(f, pool),                                           "\n", TRUE, NULL, FALSE, pool);  ctx.line = 1;  ctx.have_ungotten_char = FALSE;  ctx.section = svn_stringbuf_create("", pool);  ctx.option = svn_stringbuf_create("", pool);  ctx.value = svn_stringbuf_create("", pool);  do    {      SVN_ERR(skip_whitespace(&ctx, &ch, &count));      switch (ch)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -