X-Git-Url: https://git.deb.at/w?a=blobdiff_plain;f=options.c;h=82aae49cef02ae9566945f4559608d54e061a2e4;hb=c38bc4bc5254bd5925d8567e7ff1554a7844b8c7;hp=31d5eaaa9bdd33f00976297dacfeca90b12a582f;hpb=8c3f50479d2b84db00ed9b8305ca92a5b56ba32e;p=pkg%2Fabook.git diff --git a/options.c b/options.c index 31d5eaa..82aae49 100644 --- a/options.c +++ b/options.c @@ -2,156 +2,362 @@ /* * $Id$ * - * by JH + * 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) +{ + assert(opt >= 0 && opt < STR_MAX); + + return str_opts[opt]; +} + +static void +restore_default(struct option *p) { - return abook_opt_conff_get_val(key); + 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 -close_config() +free_opts() { - save_options(); + int i; - conff_free_nodes(abook_config); + /* + * only strings need to be freed + */ + for(i = 0; i < STR_MAX; i++) { + free(str_opts[i]); + str_opts[i] = NULL; + } } -static int -rcfile_exist() +/* + * file parsing + */ + +static void +opt_line_remove_comments(char *p) { - return ( (0 == access(SYSWIDE_RCFILE, F_OK)) || - (0 == access(rcfile, F_OK)) ); + 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; + } + } } -void -load_options() +static char * +get_token_start(char *p) { - int ret; + assert(p); - if( (ret = conff_load_file(&abook_config, rcfile, - REPLACE_KEY)) > 0) { - fprintf(stderr, "%s: parse error at line %d\n", rcfile, ret); - exit(1); - } + for(; ISSPACE(*p); p++); + + return 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); +static char * +get_token_end(char *p) +{ + assert(p); + + for(p = get_token_start(p); *p; p++) { + if(ISSPACE(*p)) { + break; + } } + + return p; } -void -save_options() +static char * +opt_set_set_option(char *var, char *p, struct option *opt) { - if( rcfile_exist() ) /* don't overwrite existing config */ - return; + int len; + + strtrim(p); + + len = strlen(p); - conff_save_file(abook_config, rcfile); + if(p[len - 1] == '\"' && *p == '\"') { + if(len < 3) + return "invalid value"; + p[len - 1] = 0; + p++; + } + + 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; } -static void -options_add_key(char *key, char *value) +static char * +opt_parse_set(char *p) { - const int flags = DONT_REPLACE_KEY; + char *var; + int i; + + var = get_token_start(p); + if((p = strchr(var, '='))) + *p++ = 0; + else + return "invalid value assignment"; + + strtrim(var); - conff_add_key(&abook_config, key, value, flags); + 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"; } -static void -default_options() + +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) { - options_add_key("autosave", "true"); + int i; + char *p; + char *err = NULL; + + assert(line && fn); - options_add_key("show_all_emails", "true"); - options_add_key("emailpos", "25"); - options_add_key("extra_column", "7"); - options_add_key("extra_alternative", "-1"); - options_add_key("extrapos", "65"); + line = get_token_start(line); + p = get_token_end(line); + *p++ = 0; - options_add_key("mutt_command", "mutt"); - options_add_key("mutt_return_all_emails", "true"); + if(!*line) + return FALSE; - options_add_key("print_command", "lpr"); + strtrim(line); + strtrim(p); - options_add_key("filesel_sort", "false"); + 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); - options_add_key("www_command", "lynx"); + return TRUE; +} - options_add_key("address_style", "eu"); +int +load_opts(char *filename) +{ + FILE *in; + char *line = NULL; + int n; + bool err = FALSE; + + if((in = fopen(filename, "r")) == NULL) + return -1; + + + for(n = 1;!feof(in); n++) { + line = getaline(in); + + if(feof(in)) + break; + + if(line && *line) { + opt_line_remove_comments(line); + if(*line) + err = opt_parse_line(line, n, filename); + } - options_add_key("use_ascii_only", "true"); + my_free(line); + } + + free(line); + + if(err) { + printf("Press any key to continue...\n"); + fgetc(stdin); + } + + return err; } +