1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

config: Add struct conf_parsing_state.

This commit is contained in:
Kalle Olavi Niemitalo 2008-02-03 00:16:38 +02:00 committed by Kalle Olavi Niemitalo
parent 63e82e68e4
commit 4c64afec26

View File

@ -56,16 +56,31 @@
* value to an option, but sometimes you may want to first create the option * value to an option, but sometimes you may want to first create the option
* ;). Then this will come handy. */ * ;). Then this will come handy. */
struct conf_parsing_state {
/** This part may be copied to a local variable as a bookmark
* and restored later. So it must not contain any pointers
* that would have to be freed in that situation. */
struct conf_parsing_pos {
/** Points to the next character to be parsed from the
* configuration file. */
unsigned char *look;
/* Skip comments and whitespace, /** The line number corresponding to #look. This is
* setting *@line to the number of lines skipped. */ * shown in error messages. */
static unsigned char * int line;
skip_white(unsigned char *start, int *line) } pos;
};
/** Skip comments and whitespace. */
static void
skip_white(struct conf_parsing_pos *pos)
{ {
unsigned char *start = pos->look;
while (*start) { while (*start) {
while (isspace(*start)) { while (isspace(*start)) {
if (*start == '\n') { if (*start == '\n') {
(*line)++; pos->line++;
} }
start++; start++;
} }
@ -73,11 +88,12 @@ skip_white(unsigned char *start, int *line)
if (*start == '#') { if (*start == '#') {
start += strcspn(start, "\n"); start += strcspn(start, "\n");
} else { } else {
return start; pos->look = start;
return;
} }
} }
return start; pos->look = start;
} }
/* Parse a command. Returns error code. */ /* Parse a command. Returns error code. */
@ -87,33 +103,34 @@ skip_white(unsigned char *start, int *line)
* will only possibly set OPT_WATERMARK flag to the option (if enabled). */ * will only possibly set OPT_WATERMARK flag to the option (if enabled). */
static enum parse_error static enum parse_error
parse_set(struct option *opt_tree, unsigned char **file, int *line, parse_set(struct option *opt_tree, struct conf_parsing_state *state,
struct string *mirror, int is_system_conf) struct string *mirror, int is_system_conf)
{ {
unsigned char *orig_pos = *file; unsigned char *orig_pos = state->pos.look;
unsigned char *optname; unsigned char *optname;
*file = skip_white(*file, line); skip_white(&state->pos);
if (!**file) return ERROR_PARSE; if (!*state->pos.look) return ERROR_PARSE;
/* Option name */ /* Option name */
optname = *file; optname = state->pos.look;
while (isident(**file) || **file == '*' || **file == '.' || **file == '+') while (isident(*state->pos.look) || *state->pos.look == '*'
(*file)++; || *state->pos.look == '.' || *state->pos.look == '+')
state->pos.look++;
optname = memacpy(optname, *file - optname); optname = memacpy(optname, state->pos.look - optname);
if (!optname) return ERROR_NOMEM; if (!optname) return ERROR_NOMEM;
*file = skip_white(*file, line); skip_white(&state->pos);
/* Equal sign */ /* Equal sign */
if (**file != '=') { mem_free(optname); return ERROR_PARSE; } if (*state->pos.look != '=') { mem_free(optname); return ERROR_PARSE; }
(*file)++; /* '=' */ state->pos.look++; /* '=' */
*file = skip_white(*file, line); skip_white(&state->pos);
if (!**file) { mem_free(optname); return ERROR_VALUE; } if (!*state->pos.look) { mem_free(optname); return ERROR_VALUE; }
/* Mirror what we already have */ /* Mirror what we already have */
if (mirror) add_bytes_to_string(mirror, orig_pos, *file - orig_pos); if (mirror) add_bytes_to_string(mirror, orig_pos, state->pos.look - orig_pos);
/* Option value */ /* Option value */
{ {
@ -129,7 +146,8 @@ parse_set(struct option *opt_tree, unsigned char **file, int *line,
if (!option_types[opt->type].read) if (!option_types[opt->type].read)
return ERROR_VALUE; return ERROR_VALUE;
val = option_types[opt->type].read(opt, file, line); val = option_types[opt->type].read(opt, &state->pos.look,
&state->pos.line);
if (!val) return ERROR_VALUE; if (!val) return ERROR_VALUE;
if (mirror) { if (mirror) {
@ -155,28 +173,29 @@ parse_set(struct option *opt_tree, unsigned char **file, int *line,
} }
static enum parse_error static enum parse_error
parse_unset(struct option *opt_tree, unsigned char **file, int *line, parse_unset(struct option *opt_tree, struct conf_parsing_state *state,
struct string *mirror, int is_system_conf) struct string *mirror, int is_system_conf)
{ {
unsigned char *orig_pos = *file; unsigned char *orig_pos = state->pos.look;
unsigned char *optname; unsigned char *optname;
/* XXX: This does not handle the autorewriting well and is mostly a /* XXX: This does not handle the autorewriting well and is mostly a
* quick hack than anything now. --pasky */ * quick hack than anything now. --pasky */
*file = skip_white(*file, line); skip_white(&state->pos);
if (!**file) return ERROR_PARSE; if (!*state->pos.look) return ERROR_PARSE;
/* Option name */ /* Option name */
optname = *file; optname = state->pos.look;
while (isident(**file) || **file == '*' || **file == '.' || **file == '+') while (isident(*state->pos.look) || *state->pos.look == '*'
(*file)++; || *state->pos.look == '.' || *state->pos.look == '+')
state->pos.look++;
optname = memacpy(optname, *file - optname); optname = memacpy(optname, state->pos.look - optname);
if (!optname) return ERROR_NOMEM; if (!optname) return ERROR_NOMEM;
/* Mirror what we have */ /* Mirror what we have */
if (mirror) add_bytes_to_string(mirror, orig_pos, *file - orig_pos); if (mirror) add_bytes_to_string(mirror, orig_pos, state->pos.look - orig_pos);
{ {
struct option *opt; struct option *opt;
@ -201,47 +220,50 @@ parse_unset(struct option *opt_tree, unsigned char **file, int *line,
} }
static enum parse_error static enum parse_error
parse_bind(struct option *opt_tree, unsigned char **file, int *line, parse_bind(struct option *opt_tree, struct conf_parsing_state *state,
struct string *mirror, int is_system_conf) struct string *mirror, int is_system_conf)
{ {
unsigned char *orig_pos = *file, *next_pos; unsigned char *orig_pos = state->pos.look, *next_pos;
unsigned char *keymap, *keystroke, *action; unsigned char *keymap, *keystroke, *action;
enum parse_error err = ERROR_NONE; enum parse_error err = ERROR_NONE;
*file = skip_white(*file, line); skip_white(&state->pos);
if (!**file) return ERROR_PARSE; if (!*state->pos.look) return ERROR_PARSE;
/* Keymap */ /* Keymap */
keymap = option_types[OPT_STRING].read(NULL, file, line); keymap = option_types[OPT_STRING].read(NULL, &state->pos.look,
*file = skip_white(*file, line); &state->pos.line);
if (!keymap || !**file) skip_white(&state->pos);
if (!keymap || !*state->pos.look)
return ERROR_OPTION; return ERROR_OPTION;
/* Keystroke */ /* Keystroke */
keystroke = option_types[OPT_STRING].read(NULL, file, line); keystroke = option_types[OPT_STRING].read(NULL, &state->pos.look,
*file = skip_white(*file, line); &state->pos.line);
if (!keystroke || !**file) { skip_white(&state->pos);
if (!keystroke || !*state->pos.look) {
mem_free(keymap); mem_free_if(keystroke); mem_free(keymap); mem_free_if(keystroke);
return ERROR_OPTION; return ERROR_OPTION;
} }
/* Equal sign */ /* Equal sign */
*file = skip_white(*file, line); skip_white(&state->pos);
if (**file != '=') { if (*state->pos.look != '=') {
mem_free(keymap); mem_free(keystroke); mem_free(keymap); mem_free(keystroke);
return ERROR_PARSE; return ERROR_PARSE;
} }
(*file)++; /* '=' */ state->pos.look++; /* '=' */
*file = skip_white(*file, line); skip_white(&state->pos);
if (!**file) { if (!*state->pos.look) {
mem_free(keymap); mem_free(keystroke); mem_free(keymap); mem_free(keystroke);
return ERROR_PARSE; return ERROR_PARSE;
} }
/* Action */ /* Action */
next_pos = *file; next_pos = state->pos.look;
action = option_types[OPT_STRING].read(NULL, file, line); action = option_types[OPT_STRING].read(NULL, &state->pos.look,
&state->pos.line);
if (!action) { if (!action) {
mem_free(keymap); mem_free(keystroke); mem_free(keymap); mem_free(keystroke);
return ERROR_VALUE; return ERROR_VALUE;
@ -277,30 +299,32 @@ static int load_config_file(unsigned char *, unsigned char *, struct option *,
struct string *, int); struct string *, int);
static enum parse_error static enum parse_error
parse_include(struct option *opt_tree, unsigned char **file, int *line, parse_include(struct option *opt_tree, struct conf_parsing_state *state,
struct string *mirror, int is_system_conf) struct string *mirror, int is_system_conf)
{ {
unsigned char *orig_pos = *file; unsigned char *orig_pos = state->pos.look;
unsigned char *fname; unsigned char *fname;
struct string dumbstring; struct string dumbstring;
if (!init_string(&dumbstring)) return ERROR_NOMEM; if (!init_string(&dumbstring)) return ERROR_NOMEM;
*file = skip_white(*file, line); skip_white(&state->pos);
if (!**file) { if (!*state->pos.look) {
done_string(&dumbstring); done_string(&dumbstring);
return ERROR_PARSE; return ERROR_PARSE;
} }
/* File name */ /* File name */
fname = option_types[OPT_STRING].read(NULL, file, line); fname = option_types[OPT_STRING].read(NULL, &state->pos.look,
&state->pos.line);
if (!fname) { if (!fname) {
done_string(&dumbstring); done_string(&dumbstring);
return ERROR_VALUE; return ERROR_VALUE;
} }
/* Mirror what we already have */ /* Mirror what we already have */
if (mirror) add_bytes_to_string(mirror, orig_pos, *file - orig_pos); if (mirror) add_bytes_to_string(mirror, orig_pos,
state->pos.look - orig_pos);
/* We want load_config_file() to watermark stuff, but not to load /* We want load_config_file() to watermark stuff, but not to load
* anything, polluting our beloved options tree - thus, we will feed it * anything, polluting our beloved options tree - thus, we will feed it
@ -326,7 +350,7 @@ parse_include(struct option *opt_tree, unsigned char **file, int *line,
struct parse_handler { struct parse_handler {
const unsigned char *command; const unsigned char *command;
enum parse_error (*handler)(struct option *opt_tree, enum parse_error (*handler)(struct option *opt_tree,
unsigned char **file, int *line, struct conf_parsing_state *state,
struct string *mirror, int is_system_conf); struct string *mirror, int is_system_conf);
}; };
@ -340,7 +364,7 @@ static const struct parse_handler parse_handlers[] = {
static enum parse_error static enum parse_error
parse_config_command(struct option *options, unsigned char **file, int *line, parse_config_command(struct option *options, struct conf_parsing_state *state,
struct string *mirror, int is_system_conf) struct string *mirror, int is_system_conf)
{ {
const struct parse_handler *handler; const struct parse_handler *handler;
@ -349,8 +373,8 @@ parse_config_command(struct option *options, unsigned char **file, int *line,
handler++) { handler++) {
int cmdlen = strlen(handler->command); int cmdlen = strlen(handler->command);
if (!strncmp(*file, handler->command, cmdlen) if (!strncmp(state->pos.look, handler->command, cmdlen)
&& isspace((*file)[cmdlen])) { && isspace(state->pos.look[cmdlen])) {
enum parse_error err; enum parse_error err;
struct string mirror2 = NULL_STRING; struct string mirror2 = NULL_STRING;
struct string *m2 = NULL; struct string *m2 = NULL;
@ -358,12 +382,12 @@ parse_config_command(struct option *options, unsigned char **file, int *line,
/* Mirror what we already have */ /* Mirror what we already have */
if (mirror && init_string(&mirror2)) { if (mirror && init_string(&mirror2)) {
m2 = &mirror2; m2 = &mirror2;
add_bytes_to_string(m2, *file, cmdlen); add_bytes_to_string(m2, state->pos.look, cmdlen);
} }
*file += cmdlen; state->pos.look += cmdlen;
err = handler->handler(options, file, line, m2, err = handler->handler(options, state, m2,
is_system_conf); is_system_conf);
if (!err && mirror && m2) { if (!err && mirror && m2) {
add_string_to_string(mirror, m2); add_string_to_string(mirror, m2);
@ -380,9 +404,12 @@ parse_config_command(struct option *options, unsigned char **file, int *line,
enum parse_error enum parse_error
parse_config_exmode_command(unsigned char *cmd) parse_config_exmode_command(unsigned char *cmd)
{ {
int dummyline = 0; struct conf_parsing_state state = {{ 0 }};
return parse_config_command(config_options, &cmd, &dummyline, NULL, 0); state.pos.look = cmd;
state.pos.line = 0;
return parse_config_command(config_options, &state, NULL, 0);
} }
#endif /* CONFIG_EXMODE */ #endif /* CONFIG_EXMODE */
@ -391,7 +418,7 @@ parse_config_file(struct option *options, unsigned char *name,
unsigned char *file, struct string *mirror, unsigned char *file, struct string *mirror,
int is_system_conf) int is_system_conf)
{ {
struct conf_parsing_pos pos = { 0 }; struct conf_parsing_state state = {{ 0 }};
int error_occurred = 0; int error_occurred = 0;
enum parse_error err = 0; enum parse_error err = 0;
enum verbose_level verbose = get_cmd_opt_int("verbose"); enum verbose_level verbose = get_cmd_opt_int("verbose");
@ -404,31 +431,36 @@ parse_config_file(struct option *options, unsigned char *name,
"no memory left", /* ERROR_NOMEM */ "no memory left", /* ERROR_NOMEM */
}; };
while (file && *file) { state.pos.look = file;
unsigned char *orig_pos = file; state.pos.line = 1;
while (state.pos.look && *state.pos.look) {
unsigned char *orig_pos = state.pos.look;
/* Skip all possible comments and whitespace. */ /* Skip all possible comments and whitespace. */
file = skip_white(file, &line); skip_white(&state.pos);
/* Mirror what we already have */ /* Mirror what we already have */
if (mirror) if (mirror)
add_bytes_to_string(mirror, orig_pos, file - orig_pos); add_bytes_to_string(mirror, orig_pos,
state.pos.look - orig_pos);
/* Second chance to escape from the hell. */ /* Second chance to escape from the hell. */
if (!*file) break; if (!*state.pos.look) break;
err = parse_config_command(options, &file, &line, mirror, err = parse_config_command(options, &state, mirror,
is_system_conf); is_system_conf);
if (err == ERROR_COMMAND) { if (err == ERROR_COMMAND) {
orig_pos = file; orig_pos = state.pos.look;
/* Jump over this crap we can't understand. */ /* Jump over this crap we can't understand. */
while (!isspace(*file) && *file != '#' && *file) while (!isspace(*state.pos.look)
file++; && *state.pos.look != '#' && *state.pos.look)
state.pos.look++;
/* Mirror what we already have */ /* Mirror what we already have */
if (mirror) add_bytes_to_string(mirror, orig_pos, if (mirror) add_bytes_to_string(mirror, orig_pos,
file - orig_pos); state.pos.look - orig_pos);
} }
if (!mirror && err) { if (!mirror && err) {
@ -437,7 +469,7 @@ parse_config_file(struct option *options, unsigned char *name,
* anymore now (?). --pasky */ * anymore now (?). --pasky */
if (verbose >= VERBOSE_WARNINGS) { if (verbose >= VERBOSE_WARNINGS) {
fprintf(stderr, "%s:%d: %s\n", fprintf(stderr, "%s:%d: %s\n",
name, line, error_msg[err]); name, state.pos.line, error_msg[err]);
error_occurred = 1; error_occurred = 1;
} }
err = 0; err = 0;