3 * $Id: options.c,v 1.33 2006/09/06 08:48:33 jheinonen Exp $
5 * by JH <jheinonen@users.sourceforge.net>
7 * Copyright (C) Jaakko Heinonen
30 #define UL (unsigned long)
49 static struct option abook_vars
[] = {
50 { "autosave", OT_BOOL
, BOOL_AUTOSAVE
, TRUE
},
52 { "show_all_emails", OT_BOOL
, BOOL_SHOW_ALL_EMAILS
, TRUE
},
53 { "index_format", OT_STR
, STR_INDEX_FORMAT
, UL
" {name:22} {email:40} {phone:12|workphone|mobile}" },
54 { "mutt_command", OT_STR
, STR_MUTT_COMMAND
, UL
"mutt" },
55 { "mutt_return_all_emails", OT_BOOL
, BOOL_MUTT_RETURN_ALL_EMAILS
,
58 { "print_command", OT_STR
, STR_PRINT_COMMAND
, UL
"lpr" },
60 { "www_command", OT_STR
, STR_WWW_COMMAND
, UL
"lynx" },
62 { "address_style", OT_STR
, STR_ADDRESS_STYLE
, UL
"eu" },
64 { "use_ascii_only", OT_BOOL
, BOOL_USE_ASCII_ONLY
, FALSE
},
66 { "add_email_prevent_duplicates", OT_BOOL
, BOOL_ADD_EMAIL_PREVENT_DUPLICATES
, FALSE
},
67 { "preserve_fields", OT_STR
, STR_PRESERVE_FIELDS
, UL
"standard" },
68 { "sort_field", OT_STR
, STR_SORT_FIELD
, UL
"nick" },
69 { "show_cursor", OT_BOOL
, BOOL_SHOW_CURSOR
, FALSE
},
74 static unsigned char bool_opts
[BOOL_MAX
];
75 static int int_opts
[INT_MAXIMUM
];
76 static char *str_opts
[STR_MAX
];
79 set_int(enum int_opts opt
, int value
)
81 assert(opt
>= 0 && opt
< INT_MAXIMUM
);
83 int_opts
[opt
] = value
;
87 set_bool(enum bool_opts opt
, bool value
)
89 assert(opt
>= 0 && opt
< BOOL_MAX
);
91 bool_opts
[opt
] = value
;
95 set_str(enum str_opts opt
, char *value
)
97 assert(opt
>= 0 && opt
< STR_MAX
);
102 str_opts
[opt
] = xstrdup(value
);
106 opt_get_int(enum int_opts opt
)
108 assert(opt
>= 0 && opt
< INT_MAXIMUM
);
110 return int_opts
[opt
];
114 opt_get_bool(enum bool_opts opt
)
116 assert(opt
>= 0 && opt
< BOOL_MAX
);
118 return bool_opts
[opt
];
122 opt_get_str(enum str_opts opt
)
124 assert(opt
>= 0 && opt
< STR_MAX
);
126 return str_opts
[opt
];
130 restore_default(struct option
*p
)
134 set_bool(p
-> data
, (bool)p
-> init
);
137 set_int(p
-> data
, (int)p
-> init
);
141 set_str(p
-> data
, (char *) p
-> init
);
153 for(i
= 0; abook_vars
[i
].option
; i
++)
154 restore_default(&abook_vars
[i
]);
163 * only strings need to be freed
165 for(i
= 0; i
< STR_MAX
; i
++) {
180 opt_line_remove_comments(char *p
)
182 bool in_quote
= FALSE
;
191 in_quote
= !in_quote
;
208 * - b->data points to the found token, or NULL is end of parsing
209 * - b->ptr points to the begining of next token
211 * If the TOKEN_ALLOC option is used, the original string is not mangled
212 * and memory is allocated for the token.
215 get_token(buffer
*b
, int options
)
223 if(*b
->ptr
&& strchr("\"'", *b
->ptr
))
235 ((options
& TOKEN_EQUAL
) && (c
== '=')) ||
236 ((options
& TOKEN_COMMA
) && (c
== ',')))
240 } else if(c
== quote
) {
250 return _("quote mismatch");
252 if(options
& (TOKEN_EQUAL
| TOKEN_COMMA
))
253 SKIPWS(b
->ptr
); /* whitespaces can precede the sign */
255 if((options
& TOKEN_EQUAL
) && (*b
->ptr
!= '='))
256 return _("no assignment character found");
258 if((options
& TOKEN_COMMA
) && *b
->ptr
&& (*b
->ptr
!= ','))
259 return _("error in comma separated list");
261 if(b
->ptr
== b
->data
) {
263 return NULL
; /* no error, just end of parsing */
266 if(options
& TOKEN_ALLOC
) /* freeing is the caller's responsibility */
267 b
->data
= xstrndup(b
->data
, end
- b
->data
);
271 b
->ptr
++; /* advance to next token */
278 opt_set_set_option(char *p
, struct option
*opt
)
287 if(*p
== '\"' && p
[len
- 1] == '\"') {
289 return _("invalid value");
294 switch(opt
-> type
) {
296 set_str(opt
-> data
, p
);
299 set_int(opt
-> data
, safe_atoi(p
));
302 if(!strcasecmp(p
, "true") || !strcasecmp(p
, "on"))
303 set_bool(opt
-> data
, TRUE
);
304 else if(!strcasecmp(p
, "false") ||
305 !strcasecmp(p
, "off"))
306 set_bool(opt
-> data
, FALSE
);
308 return _("invalid value");
318 opt_set_option(char *var
, char *p
)
325 for(i
= 0; abook_vars
[i
].option
; i
++)
326 if(!strcmp(abook_vars
[i
].option
, var
))
327 return opt_set_set_option(p
, &abook_vars
[i
]);
329 return _("unknown option");
338 str
= opt_get_str(STR_PRESERVE_FIELDS
);
339 if(strcasecmp(str
, "all") && strcasecmp(str
, "none") &&
340 strcasecmp(str
, "standard")) {
341 fprintf(stderr
, _("valid values for the 'preserve_fields' "
342 "option are 'all', 'standard' "
343 "(default), and 'none'\n"));
344 restore_default(&abook_vars
[STR_PRESERVE_FIELDS
]);
347 str
= opt_get_str(STR_ADDRESS_STYLE
);
348 if(strcasecmp(str
, "eu") && strcasecmp(str
, "uk") &&
349 strcasecmp(str
, "us")) {
350 fprintf(stderr
, _("valid values for the 'address_style' "
351 "option are 'eu' (default), 'uk', "
353 restore_default(&abook_vars
[STR_ADDRESS_STYLE
]);
361 * syntax: set <option> = <value>
364 opt_parse_set(buffer
*b
)
368 if((err
= get_token(b
, TOKEN_EQUAL
)))
371 if((var
= b
->data
) == NULL
)
372 return _("invalid value assignment");
374 return opt_set_option(var
, b
->ptr
);
378 opt_parse_customfield(buffer
*b
)
380 return _("customfield: obsolete command - please use the "
381 "'field' and 'view' commands instead");
384 #include "views.h" /* needed for add_field_to_view */
387 * syntax: view <tab name> = <field1> [ , <field2>, ... ]
390 opt_parse_view(buffer
*b
)
394 if((err
= get_token(b
, TOKEN_EQUAL
)))
397 if((view
= b
->data
) == NULL
)
398 return _("no view name provided");
401 if((err
= get_token(b
, TOKEN_COMMA
)))
407 if((err
= add_field_to_view(view
, b
->data
)))
414 #include "database.h" /* needed for declare_new_field */
417 * syntax: field <identifier> = <human readable name> [ , <type> ]
420 opt_parse_field(buffer
*b
)
422 char *err
, *field
, *name
;
424 if((err
= get_token(b
, TOKEN_EQUAL
)))
427 if((field
= b
->data
) == NULL
)
428 return _("no field identifier provided");
430 if((err
= get_token(b
, TOKEN_COMMA
)))
433 if((name
= b
->data
) == NULL
)
434 return _("no field name provided");
436 if((err
= declare_new_field(field
,
439 0 /* reject "standard" fields */)))
448 const char * (*func
) (buffer
*line
);
450 { "set", opt_parse_set
},
451 { "customfield", opt_parse_customfield
}, /* obsolete */
452 { "view", opt_parse_view
},
453 { "field", opt_parse_field
},
458 opt_parse_line(char *line
, int n
, char *fn
)
461 const char *err
= NULL
;
469 if((err
= get_token(&b
, 0))) {
470 fprintf(stderr
, "%s\n", err
);
481 b
.data
= b
.ptr
= b
.ptr
;
483 for(i
= 0; opt_parsers
[i
].token
; i
++)
484 if(!strcmp(opt_parsers
[i
].token
, token
)) {
485 if(!(err
= opt_parsers
[i
].func(&b
)))
490 fprintf(stderr
, _("%s: parse error at line %d: "), fn
, n
);
492 fprintf(stderr
, "%s\n", err
);
494 fprintf(stderr
, _("unknown token %s\n"), token
);
500 load_opts(char *filename
)
507 if((in
= fopen(filename
, "r")) == NULL
)
510 for(n
= 1;!feof(in
); n
++) {
517 opt_line_remove_comments(line
);
519 err
+= opt_parse_line(line
, n
, filename
) ? 1:0;
528 /* post-initialization */
529 err
+= check_options();
530 if(!strcasecmp(opt_get_str(STR_PRESERVE_FIELDS
), "standard"))
531 init_standard_fields();