X-Git-Url: https://git.deb.at/?a=blobdiff_plain;ds=sidebyside;f=options.c;h=82aae49cef02ae9566945f4559608d54e061a2e4;hb=c38bc4bc5254bd5925d8567e7ff1554a7844b8c7;hp=ad0671161abf79e7da0f50fa23c3d1eb2b42c6ec;hpb=22b04d3544adcdcead47127d4de7826d18444ca2;p=pkg%2Fabook.git diff --git a/options.c b/options.c index ad06711..82aae49 100644 --- a/options.c +++ b/options.c @@ -5,163 +5,359 @@ * by JH * * Copyright (C) Jaakko Heinonen + * */ +#include #include #include -#include -#include "abook_curses.h" -#include "abook.h" +#include +#include #include "options.h" -#ifdef HAVE_CONFIG_H -# include "config.h" +#include "abook.h" +#include "misc.h" + +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef TRUE +# define TRUE 1 #endif -struct conff_node *abook_config; +#define UL (unsigned long) -static int rcfile_exist(); -static void default_options(); +/* + * option types + */ -extern char *rcfile; +enum opt_type { + OT_BOOL, + OT_STR, + OT_INT +}; -static char * -abook_opt_conff_get_val(char *key) +struct option { + char *option; + enum opt_type type; + unsigned int data; + unsigned long init; +}; + +static struct option abook_vars[] = { + { "autosave", OT_BOOL, BOOL_AUTOSAVE, TRUE }, + + { "show_all_emails", OT_BOOL, BOOL_SHOW_ALL_EMAILS, TRUE }, + { "emailpos", OT_INT, INT_EMAILPOS, 25 }, + { "extra_column", OT_STR, STR_EXTRA_COLUMN, UL "phone" }, + { "extra_alternative", OT_STR, STR_EXTRA_ALTERNATIVE, UL "-1" }, + { "extrapos", OT_INT, INT_EXTRAPOS, 65 }, + + { "mutt_command", OT_STR, STR_MUTT_COMMAND, UL "mutt" }, + { "mutt_return_all_emails", OT_BOOL, BOOL_MUTT_RETURN_ALL_EMAILS, + TRUE }, + + { "print_command", OT_STR, STR_PRINT_COMMAND, UL "lpr" }, + + { "www_command", OT_STR, STR_WWW_COMMAND, UL "lynx" }, + + { "address_style", OT_STR, STR_ADDRESS_STYLE, UL "eu" }, + + { "use_ascii_only", OT_BOOL, BOOL_USE_ASCII_ONLY, FALSE }, + + { NULL } +}; + +static unsigned char bool_opts[BOOL_MAX]; +static int int_opts[INT_MAX]; +static char *str_opts[STR_MAX]; + +static void +set_int(enum int_opts opt, int value) { - int tried; - char *value = NULL; + assert(opt >= 0 && opt < INT_MAX); + int_opts[opt] = value; +} - for(tried = 0; tried < 2; ) { - if( ( value = conff_get_value(abook_config, key) ) - == 0 ) { - tried ++; - default_options(); /* try with defaults */ - } else - return value; - } - return NULL; +static void +set_bool(enum bool_opts opt, bool value) +{ + assert(opt >= 0 && opt < BOOL_MAX); + + bool_opts[opt] = value; +} + +static void +set_str(enum str_opts opt, char *value) +{ + assert(opt >= 0 && opt < STR_MAX); + + if(str_opts[opt]) + free(str_opts[opt]); + + str_opts[opt] = strdup(value); } int -options_get_int(char *key) +opt_get_int(enum int_opts opt) { - char *value; - int ret; - - if( ( value = abook_opt_conff_get_val(key) ) - == NULL) - return 1; + assert(opt >= 0 && opt < INT_MAX); - if( !strcasecmp(value, "true") ) - ret = 1; - else - if( !strcasecmp(value, "false") ) - ret = 0; - else - ret = safe_atoi(value); - - return ret; + return int_opts[opt]; } - + +bool +opt_get_bool(enum bool_opts opt) +{ + assert(opt >= 0 && opt < STR_MAX); + + return bool_opts[opt]; +} + char * -options_get_str(char *key) +opt_get_str(enum str_opts opt) { - return abook_opt_conff_get_val(key); + assert(opt >= 0 && opt < STR_MAX); + + return str_opts[opt]; } - + +static void +restore_default(struct option *p) +{ + switch(p -> type) { + case OT_BOOL: + set_bool(p -> data, (bool)p -> init); + break; + case OT_INT: + set_int(p -> data, (int)p -> init); + break; + case OT_STR: + if(p -> init) + set_str(p -> data, (char *) p -> init); + break; + default: + assert(0); + } +} + void -init_options() +init_opts() { - abook_config = NULL; + int i; - if( rcfile_exist() ) - load_options(); - else - default_options(); + for(i = 0; abook_vars[i].option; i++) + restore_default(&abook_vars[i]); } +void +free_opts() +{ + int i; -#if 1 -extern bool alternative_rcfile; -#endif + /* + * only strings need to be freed + */ + for(i = 0; i < STR_MAX; i++) { + free(str_opts[i]); + str_opts[i] = NULL; + } +} -void -close_config() +/* + * file parsing + */ + +static void +opt_line_remove_comments(char *p) { -#if 1 - if(!alternative_rcfile) - save_options(); -#endif + bool in_quote = FALSE; + bool escape = FALSE; + + assert(p != NULL); + + for(; *p; p++) { + switch(*p) { + case '\"': + if(!escape) { + in_quote = !in_quote; + escape = FALSE; + } + break; + case '\\': + escape = TRUE; + break; + case '#': + if(!in_quote) { + *p = 0; + return; + } + default: + escape = FALSE; + } + } +} + +static char * +get_token_start(char *p) +{ + assert(p); + + for(; ISSPACE(*p); p++); - conff_free_nodes(abook_config); + return p; } -static int -rcfile_exist() +static char * +get_token_end(char *p) { - return ( (0 == access(SYSWIDE_RCFILE, F_OK)) || - (0 == access(rcfile, F_OK)) ); + assert(p); + + for(p = get_token_start(p); *p; p++) { + if(ISSPACE(*p)) { + break; + } + } + + return p; } -void -load_options() +static char * +opt_set_set_option(char *var, char *p, struct option *opt) { - int ret; + int len; - if( (ret = conff_load_file(&abook_config, rcfile, - REPLACE_KEY)) > 0) { - fprintf(stderr, "%s: parse error at line %d\n", rcfile, ret); - exit(1); + strtrim(p); + + len = strlen(p); + + if(p[len - 1] == '\"' && *p == '\"') { + if(len < 3) + return "invalid value"; + p[len - 1] = 0; + p++; } - if( (ret = conff_load_file(&abook_config, SYSWIDE_RCFILE, - DONT_REPLACE_KEY )) > 0) { - fprintf(stderr, "%s: parse error at line %d\n", - SYSWIDE_RCFILE, ret); - exit(1); + switch(opt -> type) { + case OT_STR: + set_str(opt -> data, p); + break; + case OT_INT: + set_int(opt -> data, safe_atoi(p)); + break; + case OT_BOOL: + if(!strcasecmp(p, "true") && !strcasecmp(p, "on")) + set_bool(opt -> data, TRUE); + else if(!strcasecmp(p, "false") && + !strcasecmp(p, "off")) + set_bool(opt -> data, FALSE); + else + return "invalid value"; + break; } + + return NULL; } -#if 1 -void -save_options() +static char * +opt_parse_set(char *p) { - if( rcfile_exist() ) /* don't overwrite existing config */ - return; + char *var; + int i; - conff_save_file(abook_config, rcfile); + var = get_token_start(p); + if((p = strchr(var, '='))) + *p++ = 0; + else + return "invalid value assignment"; + + strtrim(var); + + for(i = 0;abook_vars[i].option; i++) + if(!strcmp(abook_vars[i].option, var)) + return opt_set_set_option(var, p, &abook_vars[i]); + + return "unknown option"; } -#endif -static void -options_add_key(char *key, char *value) + +static struct { + char *token; + char * (*func) (char *line); +} opt_parsers[] = { + { "set", opt_parse_set }, + { NULL } +}; + +static bool +opt_parse_line(char *line, int n, char *fn) { - const int flags = DONT_REPLACE_KEY; + int i; + char *p; + char *err = NULL; + + assert(line && fn); + + line = get_token_start(line); + p = get_token_end(line); + *p++ = 0; + + if(!*line) + return FALSE; - conff_add_key(&abook_config, key, value, flags); + strtrim(line); + strtrim(p); + + for(i = 0; opt_parsers[i].token; i++) + if(!strcmp(opt_parsers[i].token, line)) { + if(!(err = opt_parsers[i].func(p))) + return FALSE; + break; + } + + fprintf(stderr, "%s: parse error at line %d: ", fn, n); + if(err) + fprintf(stderr, "%s\n", err); + else + fprintf(stderr, "unknown token %s\n", line); + + return TRUE; } -static void -default_options() +int +load_opts(char *filename) { - options_add_key("autosave", "true"); - - options_add_key("show_all_emails", "true"); - options_add_key("emailpos", "25"); - options_add_key("extra_column", "phone"); - options_add_key("extra_alternative", "-1"); - options_add_key("extrapos", "65"); + FILE *in; + char *line = NULL; + int n; + bool err = FALSE; + + if((in = fopen(filename, "r")) == NULL) + return -1; - options_add_key("mutt_command", "mutt"); - options_add_key("mutt_return_all_emails", "true"); + + for(n = 1;!feof(in); n++) { + line = getaline(in); - options_add_key("print_command", "lpr"); + if(feof(in)) + break; - options_add_key("filesel_sort", "false"); + if(line && *line) { + opt_line_remove_comments(line); + if(*line) + err = opt_parse_line(line, n, filename); + } - options_add_key("www_command", "lynx"); + my_free(line); + } - options_add_key("address_style", "eu"); + free(line); - options_add_key("use_ascii_only", "false"); + if(err) { + printf("Press any key to continue...\n"); + fgetc(stdin); + } + + return err; } +