X-Git-Url: https://git.deb.at/w?a=blobdiff_plain;f=options.c;h=8196bcd50a74e1498dc08c52a8593b8bfe79c6e0;hb=c5d8ef5198f2bfd02f678b7a709b6538ef83cd44;hp=c1c167789c7a3372f97b24bc0f5c55346661884a;hpb=7dca83329bb3ce545d6d03e10754999b9a82ca01;p=pkg%2Fabook.git diff --git a/options.c b/options.c index c1c1677..8196bcd 100644 --- a/options.c +++ b/options.c @@ -1,157 +1,397 @@ /* - * $Id: options.c,v 1.7 2001/08/23 09:39:56 jheinonen Exp $ + * $Id: options.c,v 1.21 2003/12/05 18:11:55 jheinonen Exp $ * * 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 + +#define UL (unsigned long) + +/* + * option types + */ -struct conff_node *abook_config; +enum opt_type { + OT_BOOL, + OT_STR, + OT_INT +}; -static int rcfile_exist(); -static void default_options(); +struct option { + char *option; + enum opt_type type; + unsigned int data; + unsigned long init; +}; -extern char *rcfile; +static struct option abook_vars[] = { + { "autosave", OT_BOOL, BOOL_AUTOSAVE, TRUE }, -static char * -abook_opt_conff_get_val(char *key) + { "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 }, + + { "add_email_prevent_duplicates", OT_BOOL, BOOL_ADD_EMAIL_PREVENT_DUPLICATES, FALSE }, + { "sort_field", OT_STR, STR_SORT_FIELD, UL "nick" }, + + { NULL } +}; + +static unsigned char bool_opts[BOOL_MAX]; +static int int_opts[INT_MAXIMUM]; +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_MAXIMUM); + 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_MAXIMUM); - 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 < BOOL_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 -close_config() +free_opts() +{ + int i; + + /* + * only strings need to be freed + */ + for(i = 0; i < STR_MAX; i++) { + free(str_opts[i]); + str_opts[i] = NULL; + } +} + +/* + * file parsing + */ + +typedef struct { + char *data, *ptr; +} buffer; + +static void +opt_line_remove_comments(char *p) { - save_options(); + bool in_quote = FALSE; + bool escape = FALSE; + + assert(p != NULL); - conff_free_nodes(abook_config); + 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 int -rcfile_exist() +void +find_token_start(buffer *b) { - return ( (0 == access(SYSWIDE_RCFILE, F_OK)) || - (0 == access(rcfile, F_OK)) ); + assert(b); + + for(; ISSPACE(*b -> ptr); b -> ptr ++); } void -load_options() +find_token_end(buffer *b) { - int ret; + assert(b); + + for(find_token_start(b); *(b -> ptr); b -> ptr ++) { + if(ISSPACE(*(b -> ptr))) { + break; + } + } +} + +static char * +opt_set_set_option(char *var, char *p, struct option *opt) +{ + 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; + default: + assert(0); } + + return NULL; } -void -save_options() +static char * +opt_parse_set(buffer *b) { - if( rcfile_exist() ) /* don't overwrite existing config */ - return; + int i; + char *p; + + find_token_start(b); + if((p = strchr(b -> ptr, '='))) + *p++ = 0; + else + return "invalid value assignment"; + + strtrim(b -> ptr); - conff_save_file(abook_config, rcfile); + for(i = 0;abook_vars[i].option; i++) + if(!strcmp(abook_vars[i].option, b -> ptr)) + return opt_set_set_option(b -> ptr, p, &abook_vars[i]); + + return "unknown option"; } -static void -options_add_key(char *key, char *value) +#include "database.h" /* needed for change_custom_field_name */ + +static char * +opt_parse_customfield(buffer *b) { - const int flags = DONT_REPLACE_KEY; + char *p, num[5]; + int n; + size_t len; + + find_token_start(b); + p = b -> ptr; + find_token_end(b); + + memset(num, 0, sizeof(num)); + + len = (b -> ptr - p); + strncpy(num, p, min(sizeof(num) - 1, len)); + n = safe_atoi(num); + + find_token_start(b); + + if(change_custom_field_name(b->ptr, n) == -1) + return "invalid custom field number"; - conff_add_key(&abook_config, key, value, flags); + return NULL; } -static void -default_options() +static struct { + char *token; + char * (*func) (buffer *line); +} opt_parsers[] = { + { "set", opt_parse_set }, + { "customfield", opt_parse_customfield }, + { NULL } +}; + +static bool +opt_parse_line(char *line, int n, char *fn) { - options_add_key("autosave", "true"); + int i; + char *err = NULL; + char *token; + buffer b; + + 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"); + b.ptr = line; - options_add_key("mutt_command", "mutt"); - options_add_key("mutt_return_all_emails", "true"); + find_token_start(&b); + b.data = b.ptr; + find_token_end(&b); + *b.ptr++ = 0; - options_add_key("print_command", "lpr"); + if(!*line) + return FALSE; - options_add_key("filesel_sort", "false"); + strtrim(b.data); + strtrim(b.ptr); - options_add_key("www_command", "lynx"); + token = b.data; + b.data = b.ptr = b.ptr; - options_add_key("address_style", "eu"); + for(i = 0; opt_parsers[i].token; i++) + if(!strcmp(opt_parsers[i].token, token)) { + if(!(err = opt_parsers[i].func(&b))) + 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", token); - options_add_key("use_ascii_only", "false"); + return TRUE; } + +int +load_opts(char *filename) +{ + FILE *in; + char *line = NULL; + int n; + int err = 0; + + 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) ? 1:0; + } + + my_free(line); + } + + free(line); + + return err; +} +