+/*
+ * syntax: set <option> = <value>
+ */
+static char *
+opt_parse_set(buffer *b)
+{
+ char *var, *err;
+
+ if((err = get_token(b, TOKEN_EQUAL)))
+ return err;
+
+ if((var = b->data) == NULL)
+ return _("invalid value assignment");
+
+ return opt_set_option(var, b->ptr);
+}
+
+static char *
+opt_parse_customfield(buffer *b)
+{
+ return _("customfield: obsolete command - please use the "
+ "'field' and 'view' commands instead");
+}
+
+#include "views.h" /* needed for add_field_to_view */
+
+/*
+ * syntax: view <tab name> = <field1> [ , <field2>, ... ]
+ */
+static char *
+opt_parse_view(buffer *b)
+{
+ char *err, *view;
+
+ if((err = get_token(b, TOKEN_EQUAL)))
+ return err;
+
+ if((view = b->data) == NULL)
+ return _("no view name provided");
+
+ while(1) {
+ if((err = get_token(b, TOKEN_COMMA)))
+ return err;
+
+ if(b->data == NULL)
+ break;
+
+ if((err = add_field_to_view(view, b->data)))
+ return err;
+ }
+
+ return NULL;
+}
+
+#include "database.h" /* needed for declare_new_field */
+
+/*
+ * syntax: field <identifier> = <human readable name> [ , <type> ]
+ */
+static char *
+opt_parse_field(buffer *b)
+{
+ char *err, *field, *name;
+
+ if((err = get_token(b, TOKEN_EQUAL)))
+ return err;
+
+ if((field = b->data) == NULL)
+ return _("no field identifier provided");
+
+ if((err = get_token(b, TOKEN_COMMA)))
+ return err;
+
+ if((name = b->data) == NULL)
+ return _("no field name provided");
+
+ if((err = declare_new_field(field,
+ name,
+ b->ptr,
+ 0 /* reject "standard" fields */)))
+ return err;
+
+ return NULL;
+}
+
+
+static struct {
+ char *token;
+ char * (*func) (buffer *line);
+} opt_parsers[] = {
+ { "set", opt_parse_set },
+ { "customfield", opt_parse_customfield }, /* obsolete */
+ { "view", opt_parse_view },
+ { "field", opt_parse_field },
+ { NULL }
+};
+
+static bool
+opt_parse_line(char *line, int n, char *fn)
+{
+ int i;
+ char *err = NULL;
+ char *token;
+ buffer b;
+
+ assert(line && fn);
+
+ b.ptr = line;
+
+ if((err = get_token(&b, 0))) {
+ fprintf(stderr, "%s\n", err);
+ return FALSE;
+ }
+
+ if(b.data == NULL)
+ return FALSE;
+
+ strtrim(b.data);
+ strtrim(b.ptr);
+
+ token = b.data;
+ b.data = b.ptr = b.ptr;
+
+ 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);
+
+ return TRUE;
+}
+
+int
+load_opts(char *filename)