diff options
Diffstat (limited to 'lib/libconfig.c')
-rw-r--r-- | lib/libconfig.c | 190 |
1 files changed, 120 insertions, 70 deletions
diff --git a/lib/libconfig.c b/lib/libconfig.c index edf7b8b..6724c2e 100644 --- a/lib/libconfig.c +++ b/lib/libconfig.c @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- libconfig - A library for processing structured configuration files - Copyright (C) 2005-2010 Mark A Lindner + Copyright (C) 2005-2014 Mark A Lindner This file is part of libconfig. @@ -24,41 +24,46 @@ #include "ac_config.h" #endif -#include "libconfig.h" -#include "grammar.h" -#include "scanner.h" -#include "scanctx.h" -#include "parsectx.h" -#include "wincompat.h" - #include <locale.h> #ifdef HAVE_XLOCALE_H #include <xlocale.h> #endif +#include <ctype.h> +#include <float.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <ctype.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "libconfig.h" +#include "parsectx.h" +#include "scanctx.h" +#include "wincompat.h" +#include "grammar.h" +#include "scanner.h" #define PATH_TOKENS ":./" #define CHUNK_SIZE 16 -#define FLOAT_PRECISION 10 +#define FLOAT_PRECISION DBL_DIG -#define _new(T) (T *)calloc(sizeof(T), 1) /* zeroed */ +#define _new(T) (T *)calloc(1, sizeof(T)) /* zeroed */ #define _delete(P) free((void *)(P)) /* ------------------------------------------------------------------------- */ #ifndef LIBCONFIG_STATIC -#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ + || defined(WIN64) || defined(_WIN64)) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { return(TRUE); } -#endif /* WIN32 */ +#endif /* WIN32 || WIN64 */ #endif /* LIBCONFIG_STATIC */ /* ------------------------------------------------------------------------- */ @@ -66,14 +71,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) static const char *__io_error = "file I/O error"; static void __config_list_destroy(config_list_t *list); -static void __config_write_setting(const config_setting_t *setting, - FILE *stream, int depth, - unsigned short tab_width); - -extern int libconfig_yyparse(void *scanner, struct parse_context *ctx, - struct scan_context *scan_ctx); -extern int libconfig_yylex_init_extra(struct scan_context *scan_ctx, - yyscan_t *scanner); +static void __config_write_setting(const config_t *config, + const config_setting_t *setting, + FILE *stream, int depth); /* ------------------------------------------------------------------------- */ @@ -104,6 +104,11 @@ static void __config_locale_override(void) /* ------------------------------------------------------------------------- */ +#define __config_has_option(C, O) \ + (((C)->options & (O)) != 0) + +/* ------------------------------------------------------------------------- */ + static void __config_locale_restore(void) { #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ @@ -165,9 +170,9 @@ static void __config_indent(FILE *stream, int depth, unsigned short w) /* ------------------------------------------------------------------------- */ -static void __config_write_value(const config_value_t *value, int type, - int format, int depth, - unsigned short tab_width, FILE *stream) +static void __config_write_value(const config_t *config, + const config_value_t *value, int type, + int format, int depth, FILE *stream) { char fbuf[64]; @@ -304,9 +309,9 @@ static void __config_write_value(const config_value_t *value, int type, for(s = list->elements; len--; s++) { - __config_write_value(&((*s)->value), (*s)->type, - config_setting_get_format(*s), - depth + 1, tab_width, stream); + __config_write_value(config, &((*s)->value), (*s)->type, + config_setting_get_format(*s), depth + 1, + stream); if(len) fputc(',', stream); @@ -333,9 +338,9 @@ static void __config_write_value(const config_value_t *value, int type, for(s = list->elements; len--; s++) { - __config_write_value(&((*s)->value), (*s)->type, - config_setting_get_format(*s), - depth + 1, tab_width, stream); + __config_write_value(config, &((*s)->value), (*s)->type, + config_setting_get_format(*s), depth + 1, + stream); if(len) fputc(',', stream); @@ -355,14 +360,14 @@ static void __config_write_value(const config_value_t *value, int type, if(depth > 0) { -#ifdef K_AND_R_STYLE /* Horrendous, but many people like it. */ - fputc(' ', stream); -#else - fputc('\n', stream); + if((config->options & CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE) != 0) + { + fputc('\n', stream); + + if(depth > 1) + __config_indent(stream, depth, config->tab_width); + } - if(depth > 1) - __config_indent(stream, depth, tab_width); -#endif fprintf(stream, "{\n"); } @@ -372,11 +377,11 @@ static void __config_write_value(const config_value_t *value, int type, config_setting_t **s; for(s = list->elements; len--; s++) - __config_write_setting(*s, stream, depth + 1, tab_width); + __config_write_setting(config, *s, stream, depth + 1); } if(depth > 1) - __config_indent(stream, depth, tab_width); + __config_indent(stream, depth, config->tab_width); if(depth > 0) fputc('}', stream); @@ -554,14 +559,13 @@ static int __config_read(config_t *config, FILE *stream, const char *filename, yyscan_t scanner; struct scan_context scan_ctx; struct parse_context parse_ctx; - YY_BUFFER_STATE buffer = NULL; int r; /* Reinitialize the config */ void (*destructor)(void *) = config->destructor; const char *include_dir = config->include_dir; unsigned short tab_width = config->tab_width; - unsigned short flags = config->flags; + int options = config->options; config->include_dir = NULL; config_destroy(config); @@ -570,7 +574,7 @@ static int __config_read(config_t *config, FILE *stream, const char *filename, config->destructor = destructor; config->include_dir = include_dir; config->tab_width = tab_width; - config->flags = flags; + config->options = options; parsectx_init(&parse_ctx); parse_ctx.config = config; @@ -580,13 +584,14 @@ static int __config_read(config_t *config, FILE *stream, const char *filename, __config_locale_override(); scanctx_init(&scan_ctx, filename); + config->root->file = scanctx_current_filename(&scan_ctx); scan_ctx.config = config; libconfig_yylex_init_extra(&scan_ctx, &scanner); if(stream) libconfig_yyrestart(stream, scanner); else /* read from string */ - buffer = libconfig_yy_scan_string(str, scanner); + (void)libconfig_yy_scan_string(str, scanner); libconfig_yyset_lineno(1, scanner); r = libconfig_yyparse(scanner, &parse_ctx, &scan_ctx); @@ -628,26 +633,36 @@ int config_read_string(config_t *config, const char *str) /* ------------------------------------------------------------------------- */ -static void __config_write_setting(const config_setting_t *setting, - FILE *stream, int depth, - unsigned short tab_width) +static void __config_write_setting(const config_t *config, + const config_setting_t *setting, + FILE *stream, int depth) { + char group_assign_char = __config_has_option( + config, CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS) ? ':' : '='; + + char nongroup_assign_char = __config_has_option( + config, CONFIG_OPTION_COLON_ASSIGNMENT_FOR_NON_GROUPS) ? ':' : '='; + if(depth > 1) - __config_indent(stream, depth, tab_width); + __config_indent(stream, depth, config->tab_width); + if(setting->name) { fputs(setting->name, stream); - fprintf(stream, " %c ", (setting->type == CONFIG_TYPE_GROUP ? ':' : '=')); + fprintf(stream, " %c ", ((setting->type == CONFIG_TYPE_GROUP) + ? group_assign_char + : nongroup_assign_char)); } - __config_write_value(&(setting->value), setting->type, - config_setting_get_format(setting), - depth, tab_width, stream); + __config_write_value(config, &(setting->value), setting->type, + config_setting_get_format(setting), depth, stream); if(depth > 0) { - fputc(';', stream); + if(__config_has_option(config, CONFIG_OPTION_SEMICOLON_SEPARATORS)) + fputc(';', stream); + fputc('\n', stream); } } @@ -658,7 +673,7 @@ void config_write(const config_t *config, FILE *stream) { __config_locale_override(); - __config_write_setting(config->root, stream, 0, config->tab_width); + __config_write_setting(config, config->root, stream, 0); __config_locale_restore(); } @@ -667,10 +682,28 @@ void config_write(const config_t *config, FILE *stream) int config_read_file(config_t *config, const char *filename) { - int ret; + int ret, ok = 0; + FILE *stream = fopen(filename, "rt"); - if(! stream) + if(stream != NULL) + { + // On some operating systems, fopen() succeeds on a directory. + int fd = fileno(stream); + struct stat statbuf; + + if(fstat(fd, &statbuf) == 0) + { + // Only proceed if this is not a directory. + if(!S_ISDIR(statbuf.st_mode)) + ok = 1; + } + } + + if(!ok) { + if(stream != NULL) + fclose(stream); + config->error_text = __io_error; config->error_type = CONFIG_ERR_FILE_IO; return(CONFIG_FALSE); @@ -686,16 +719,16 @@ int config_read_file(config_t *config, const char *filename) int config_write_file(config_t *config, const char *filename) { - FILE *f = fopen(filename, "wt"); - if(! f) + FILE *stream = fopen(filename, "wt"); + if(stream == NULL) { config->error_text = __io_error; config->error_type = CONFIG_ERR_FILE_IO; return(CONFIG_FALSE); } - config_write(config, f); - fclose(f); + config_write(config, stream); + fclose(stream); config->error_type = CONFIG_ERR_NONE; return(CONFIG_TRUE); } @@ -727,6 +760,9 @@ void config_init(config_t *config) config->root = _new(config_setting_t); config->root->type = CONFIG_TYPE_GROUP; config->root->config = config; + config->options = (CONFIG_OPTION_SEMICOLON_SEPARATORS + | CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS + | CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE); config->tab_width = 2; } @@ -735,16 +771,30 @@ void config_init(config_t *config) void config_set_auto_convert(config_t *config, int flag) { if(flag) - config->flags |= CONFIG_OPTION_AUTOCONVERT; + config->options |= CONFIG_OPTION_AUTOCONVERT; else - config->flags &= ~CONFIG_OPTION_AUTOCONVERT; + config->options &= ~CONFIG_OPTION_AUTOCONVERT; } /* ------------------------------------------------------------------------- */ int config_get_auto_convert(const config_t *config) { - return((config->flags & CONFIG_OPTION_AUTOCONVERT) != 0); + return(__config_has_option(config, CONFIG_OPTION_AUTOCONVERT)); +} + +/* ------------------------------------------------------------------------- */ + +void config_set_options(config_t *config, int options) +{ + config->options = options; +} + +/* ------------------------------------------------------------------------- */ + +int config_get_options(const config_t *config) +{ + return(config->options); } /* ------------------------------------------------------------------------- */ @@ -798,7 +848,7 @@ static int __config_setting_get_int(const config_setting_t *setting, return(CONFIG_TRUE); case CONFIG_TYPE_FLOAT: - if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + if(__config_has_option(setting->config, CONFIG_OPTION_AUTOCONVERT)) { *value = (int)(setting->value.fval); return(CONFIG_TRUE); @@ -836,7 +886,7 @@ static int __config_setting_get_int64(const config_setting_t *setting, return(CONFIG_TRUE); case CONFIG_TYPE_FLOAT: - if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + if(__config_has_option(setting->config, CONFIG_OPTION_AUTOCONVERT)) { *value = (long long)(setting->value.fval); return(CONFIG_TRUE); @@ -1047,7 +1097,7 @@ int config_setting_set_float(config_setting_t *setting, double value) return(CONFIG_TRUE); case CONFIG_TYPE_INT: - if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + if(__config_has_option(setting->config, CONFIG_OPTION_AUTOCONVERT)) { setting->value.ival = (int)value; return(CONFIG_TRUE); @@ -1056,7 +1106,7 @@ int config_setting_set_float(config_setting_t *setting, double value) return(CONFIG_FALSE); case CONFIG_TYPE_INT64: - if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + if(__config_has_option(setting->config, CONFIG_OPTION_AUTOCONVERT)) { setting->value.llval = (long long)value; return(CONFIG_TRUE); @@ -1136,8 +1186,8 @@ short config_setting_get_format(const config_setting_t *setting) /* ------------------------------------------------------------------------- */ -config_setting_t *config_lookup_from(config_setting_t *setting, - const char *path) +config_setting_t *config_setting_lookup(config_setting_t *setting, + const char *path) { const char *p = path; config_setting_t *found; @@ -1171,7 +1221,7 @@ config_setting_t *config_lookup_from(config_setting_t *setting, config_setting_t *config_lookup(const config_t *config, const char *path) { - return(config_lookup_from(config->root, path)); + return(config_setting_lookup(config->root, path)); } /* ------------------------------------------------------------------------- */ @@ -1613,4 +1663,4 @@ int config_setting_index(const config_setting_t *setting) } /* ------------------------------------------------------------------------- */ -/* eof */ + |