X-Git-Url: http://git.tuebingen.mpg.de/?p=lopsub.git;a=blobdiff_plain;f=config_file.l;h=f603b8ee4636a7e48af43246144e89e451e6e109;hp=0b8435041fa0a1ba55546e885304ab30442a31f4;hb=3daf86d883abadef69583109aace38677e946cca;hpb=e5b276f1a15604f1c7efe754074a86fabbb6bf6f diff --git a/config_file.l b/config_file.l index 0b84350..f603b8e 100644 --- a/config_file.l +++ b/config_file.l @@ -4,6 +4,15 @@ * Licensed under the LGPL v3, see http://www.gnu.org/licenses/lgpl-3.0.html */ + /* We don't want symbols to clash with those of other flex users. */ +%option prefix="lls_yy" + + /* Generate a scanner which is safe to use in multithreaded programs. */ +%option reentrant + + /* To maintain state in a reentrant way. */ +%option extra-type="struct lls_yy_config_file_extra *" + %option stack %option never-interactive %option yylineno @@ -24,104 +33,15 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]* #include "lopsub-internal.h" #include "lopsub.h" - static int rargc; - static char **rargv; - static const char *subcommand; - - static int yywrap(void) {return 1;} - static int expand_result(void) - { - int nargc = rargc + 1; - char **nrargv = realloc(rargv, (nargc + 1) * sizeof(char *)); - - if (!nrargv) - return -E_LLS_NOMEM; - rargc = nargc; - rargv = nrargv; - rargv[rargc] = NULL; - return 1; - } - - static int add_option(void) - { - int ret; - unsigned n; + struct lls_yy_config_file_extra { + int argc; + char **argv; + const char *subcmd; + }; - for (n = 0; n < yyleng; n++) - if (!isalnum(yytext[n]) && !(yytext[n] == '-')) - break; - assert(n > 0); - ret = expand_result(); - if (ret < 0) - return ret; - rargv[rargc - 1] = malloc(n + 2 + 1); - if (!rargv[rargc - 1]) - return -E_LLS_NOMEM; - rargv[rargc - 1][0] = rargv[rargc - 1][1] = '-'; - memcpy(rargv[rargc - 1] + 2, yytext, n); - rargv[rargc - 1][n + 2] = '\0'; - return 1; - } - - static int parse_arg(char **result) - { - bool backslash = false, quote = false; - const char *in; - char *out; - int ret; - - *result = malloc(yyleng + 1); - if (!*result) - return -E_LLS_NOMEM; - for (in = yytext, out = *result; *in; in++) { - if (*in == '\\') { - if (!backslash) { - backslash = true; - continue; - } - } else if (*in == 'n' || *in == 't') { - if (backslash) { /* \n or \t */ - *out++ = (*in == 'n')? '\n' : '\t'; - backslash = false; - continue; - } - } else if (*in == '"') { - if (!backslash) { - quote = !quote; - continue; - } - } else if (isspace(*in)) { - if (!backslash && !quote) - break; - } - /* copy the character */ - *out++ = *in; - backslash = false; - } - ret = -E_LLS_TRAILING_BACKSLASH; - if (backslash) - goto fail; - ret = -E_LLS_UNMATCHED_QUOTE; - if (quote) - goto fail; - /* look at first non-space character */ - for (; *in; in++) { - if (isspace(*in)) - continue; - if (*in == '#') - break; - ret = -E_LLS_TRAILING_GARBAGE; - goto fail; - } - /* success */ - *out = '\0'; - return out - *result; - fail: - assert(ret < 0); - free(*result); - *result = NULL; - return ret; - } + static int add_option(yyscan_t yyscanner); + static int parse_arg(char **result, yyscan_t yyscanner); + static int yywrap(yyscan_t yyscanner) {return 1;} %} %% @@ -132,9 +52,10 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]* \[[[:space:]]*{IDENTIFIER}[[:space:]]*\][[:space:]]*\n { int i, j; + const char *subcmd = yyget_extra(yyscanner)->subcmd; assert(yytext[0] == '['); - if (!subcommand) + if (!subcmd) return 0; for (i = 1; i < yyleng; i++) if (!isspace(yytext[i])) @@ -144,16 +65,16 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]* break; assert(j < yyleng); yytext[j] = '\0'; - if (strcmp(yytext + i, subcommand)) + if (strcmp(yytext + i, subcmd)) BEGIN(INITIAL); else BEGIN(SC_SCANNING); } -{OPTION}[[:space:]]*\n add_option(); +{OPTION}[[:space:]]*\n add_option(yyscanner); {OPTION}({EQUALS}|[[:space:]]+) { - int ret = add_option(); + int ret = add_option(yyscanner); if (ret < 0) return ret; @@ -161,10 +82,11 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]* } .*\n { - const char *opt = rargv[rargc - 1]; + struct lls_yy_config_file_extra *extra = yyget_extra(yyscanner); + const char *opt = extra->argv[extra->argc - 1]; char *arg, *result; size_t opt_len = strlen(opt), arg_len; - int ret = parse_arg(&arg); + int ret = parse_arg(&arg, yyscanner); if (ret < 0) return ret; @@ -177,8 +99,8 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]* strcpy(result + opt_len + 1, arg); free(arg); result[opt_len + arg_len + 1] = '\0'; - free(rargv[rargc - 1]); - rargv[rargc - 1] = result; + free(extra->argv[extra->argc - 1]); + extra->argv[extra->argc - 1] = result; BEGIN(SC_SCANNING); } @@ -193,49 +115,105 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]* #include #include -int lls_convert_config(const char *buf, size_t nbytes, const char *subcmd, - char ***result, char **errctx) +static int expand_result(yyscan_t yyscanner) { + struct lls_yy_config_file_extra *extra = yyget_extra(yyscanner); + int nargc = extra->argc + 1; + char **nrargv = realloc(extra->argv, (nargc + 1) * sizeof(char *)); + + if (!nrargv) + return -E_LLS_NOMEM; + extra->argc = nargc; + extra->argv = nrargv; + extra->argv[extra->argc] = NULL; + return 1; +} + +static int add_option(yyscan_t yyscanner) +{ + struct lls_yy_config_file_extra *extra = yyget_extra(yyscanner); int ret; - YY_BUFFER_STATE yybs; + unsigned n; + int len = yyget_leng(yyscanner); + char *narg, *text = yyget_text(yyscanner); - *result = NULL; - if (errctx) - *errctx = NULL; - subcommand = subcmd; - if (!subcmd) - BEGIN(SC_SCANNING); - else - BEGIN(INITIAL); - yybs = yy_scan_bytes(buf, nbytes); - if (!yybs) - return -E_LLS_YY_SCAN; - rargc = 1; - rargv = malloc((rargc + 1) * sizeof(char *)); - if (!rargv) + for (n = 0; n < len; n++) + if (!isalnum(text[n]) && !(text[n] == '-')) + break; + assert(n > 0); + ret = expand_result(yyscanner); + if (ret < 0) + return ret; + narg = malloc(n + 2 + 1); + if (!narg) return -E_LLS_NOMEM; - rargv[0] = strdup(__FUNCTION__); - if (!rargv[0]) { - free(rargv); + narg[0] = narg[1] = '-'; + memcpy(narg + 2, text, n); + narg[n + 2] = '\0'; + extra->argv[extra->argc - 1] = narg; + return 1; +} + +static int parse_arg(char **result, yyscan_t yyscanner) +{ + bool backslash = false, quote = false; + const char *in; + char *out; + int ret; + int len = yyget_leng(yyscanner); + char *text = yyget_text(yyscanner); + + *result = malloc(len + 1); + if (!*result) return -E_LLS_NOMEM; + for (in = text, out = *result; *in; in++) { + if (*in == '\\') { + if (!backslash) { + backslash = true; + continue; + } + } else if (*in == 'n' || *in == 't') { + if (backslash) { /* \n or \t */ + *out++ = (*in == 'n')? '\n' : '\t'; + backslash = false; + continue; + } + } else if (*in == '"') { + if (!backslash) { + quote = !quote; + continue; + } + } else if (isspace(*in)) { + if (!backslash && !quote) + break; + } + /* copy the character */ + *out++ = *in; + backslash = false; } - rargv[1] = NULL; - ret = yylex(); - yy_delete_buffer(yybs); - if (ret >= 0) { - *result = rargv; - return rargc; - } - if (errctx) { - *errctx = malloc(100); - if (*errctx) - sprintf(*errctx, "error at line %d", yyget_lineno()); + ret = -E_LLS_TRAILING_BACKSLASH; + if (backslash) + goto fail; + ret = -E_LLS_UNMATCHED_QUOTE; + if (quote) + goto fail; + /* look at first non-space character */ + for (; *in; in++) { + if (isspace(*in)) + continue; + if (*in == '#') + break; + ret = -E_LLS_TRAILING_GARBAGE; + goto fail; } - for (; rargc >= 0; rargc--) - free(rargv[rargc]); - free(rargv); + /* success */ + *out = '\0'; + return out - *result; +fail: + assert(ret < 0); + free(*result); *result = NULL; - return -E_LLS_YY_LEX; + return ret; } void lls_free_argv(char **argv) @@ -248,6 +226,65 @@ void lls_free_argv(char **argv) free(argv[i]); free(argv); } + +int lls_convert_config(const char *buf, size_t nbytes, const char *subcmd, + char ***result, char **errctx) +{ + int ret; + YY_BUFFER_STATE yybs; + yyscan_t yyscanner; + struct lls_yy_config_file_extra extra; + + *result = NULL; + if (errctx) + *errctx = NULL; + + extra.argc = 1; + extra.argv = malloc((extra.argc + 1) * sizeof(char *)); + if (!extra.argv) + return -E_LLS_NOMEM; + extra.argv[0] = strdup(__FUNCTION__); + if (!extra.argv[0]) { + free(extra.argv); + return -E_LLS_NOMEM; + } + extra.argv[1] = NULL; + extra.subcmd = subcmd; + + ret = yylex_init_extra(&extra, &yyscanner); + if (ret != 0) { + ret = -E_LLS_NOMEM; + goto free_argv; + } + yy_push_state(subcmd? INITIAL : SC_SCANNING, yyscanner); + yybs = yy_scan_bytes(buf, nbytes, yyscanner); + if (!yybs) { + ret = -E_LLS_YY_SCAN; + goto destroy; + } + ret = yylex(yyscanner); + if (ret < 0) { + ret = -E_LLS_YY_LEX; + if (errctx) { + *errctx = malloc(100); + if (*errctx) + sprintf(*errctx, "error at line %d", + yyget_lineno(yyscanner)); + } + } + yy_delete_buffer(yybs, yyscanner); +destroy: + yylex_destroy(yyscanner); +free_argv: + if (ret < 0) + lls_free_argv(extra.argv); + else { + *result = extra.argv; + ret = extra.argc; + } + return ret; +} + #if 0 int main(void) {