From: Steven Luo Date: Thu, 17 Dec 2009 07:31:51 +0000 (-0800) Subject: Add independent config file parsing functions X-Git-Tag: v3.0rc1~15 X-Git-Url: http://git.maemo.org/git/?p=browser-switch;a=commitdiff_plain;h=9f08a817761251fa1c0070e3c03558ddfda5a162;ds=sidebyside Add independent config file parsing functions Config file parsing will also be needed by the config UI, so break out into its own function so that it can be shared between the config UI and the C implementation. --- diff --git a/configfile.c b/configfile.c index ee0e085..5200159 100644 --- a/configfile.c +++ b/configfile.c @@ -23,9 +23,15 @@ #include #include #include +#include +#include #include "configfile.h" +static regex_t re_ignore, re_config1, re_config2; +static int re_init = 0; + +/* Open config file for reading */ FILE *open_config_file(void) { char *homedir, *configfile; size_t len; @@ -51,3 +57,123 @@ FILE *open_config_file(void) { free(configfile); return fp; } + +/* Initialize the config file parser + Returns 1 if initialization successful, 0 otherwise */ +int parse_config_file_begin(void) { + /* Just return if parser's already been initialized */ + if (re_init) + return 1; + + /* compile regex matching blank lines or comments */ + if (regcomp(&re_ignore, REGEX_IGNORE, REGEX_IGNORE_FLAGS)) + return 0; + /* compile regex matching foo = "bar", with arbitrary whitespace at + beginning and end of line and surrounding the = */ + if (regcomp(&re_config1, REGEX_CONFIG1, REGEX_CONFIG1_FLAGS)) { + regfree(&re_ignore); + return 0; + } + /* compile regex matching foo = bar, with arbitrary whitespace at + beginning of line and surrounding the = */ + if (regcomp(&re_config2, REGEX_CONFIG2, REGEX_CONFIG2_FLAGS)) { + regfree(&re_ignore); + regfree(&re_config1); + return 0; + } + + re_init = 1; + return 1; +} + +/* End config file parsing and free the resources */ +void parse_config_file_end(void) { + /* Just return if parser's not active */ + if (!re_init) + return; + + regfree(&re_ignore); + regfree(&re_config1); + regfree(&re_config2); +} + +/* Read the next line from a config file and store it into a swb_config_line, + parsing it into key and value if possible + Caller is responsible for freeing the strings in the swb_config_line if + call returns successfully + Returns 0 on success (whether line parsed or not), 1 on EOF, -1 on error */ +int parse_config_file_line(FILE *fp, struct swb_config_line *line) { + regmatch_t substrs[3]; + size_t len; + char *tmp; + + if (!re_init || !fp || !line) + return -1; + + line->parsed = 0; + line->key = NULL; + line->value = NULL; + + if (!(line->key = calloc(MAXLINE, sizeof(char)))) + return -1; + + /* Read in the next line of the config file + XXX doesn't deal with lines longer than MAXLINE */ + if (!fgets(line->key, MAXLINE, fp)) { + free(line->key); + line->key = NULL; + if (feof(fp)) + return 1; + else + return -1; + } + printf("%s", line->key); + + /* no need to parse blank lines and comments */ + if (!regexec(&re_ignore, line->key, 0, NULL, 0)) + goto finish; + + /* Find the substrings corresponding to the key and value + If the line doesn't match our idea of a config file entry, + don't parse it */ + if (regexec(&re_config1, line->key, 3, substrs, 0) && + regexec(&re_config2, line->key, 3, substrs, 0)) + goto finish; + if (substrs[1].rm_so == -1 || substrs[2].rm_so == -1) + goto finish; + + /* copy the config value into a new string */ + len = substrs[2].rm_eo - substrs[2].rm_so; + if (!(line->value = calloc(len+1, sizeof(char)))) { + free(line->key); + line->key = NULL; + return -1; + } + strncpy(line->value, line->key+substrs[2].rm_so, len); + /* calloc() zeroes the memory, so string is automatically + null terminated */ + + /* make key point to a null-terminated string holding the + config key */ + len = substrs[1].rm_eo - substrs[1].rm_so; + memmove(line->key, line->key+substrs[1].rm_so, len); + line->key[len] = '\0'; + + /* done parsing the line */ + line->parsed = 1; + printf("%s: '%s'\n", line->key, line->value); + +finish: + if (!line->parsed) { + /* Toss a trailing newline, if present */ + len = strlen(line->key); + if (line->key[len-1] == '\n') + line->key[len-1] = '\0'; + } + /* Try to shrink the allocation for key, to save space if someone + wants to keep it around */ + len = strlen(line->key); + if ((tmp = realloc(line->key, len+1))) + line->key = tmp; + return 0; +} diff --git a/configfile.h b/configfile.h index c7863a7..c655274 100644 --- a/configfile.h +++ b/configfile.h @@ -47,6 +47,19 @@ #define REGEX_CONFIG2_FLAGS REG_EXTENDED|REG_NEWLINE +struct swb_config_line { + /* Whether or not the line has been parsed */ + int parsed; + /* If parsed, the config key; otherwise, the entire line */ + char *key; + /* If parsed, the config value */ + char *value; +}; + FILE *open_config_file(void); +int parse_config_file_begin(void); +void parse_config_file_end(void); +int parse_config_file_line(FILE *fp, struct swb_config_line *line); + #endif /* _CONFIGFILE_H */