X-Git-Url: http://git.tuebingen.mpg.de/?p=lopsub.git;a=blobdiff_plain;f=config_file.l;h=f603b8ee4636a7e48af43246144e89e451e6e109;hp=f6fff31e171fc5ba0f2b2cfd47fd41f133fe3e29;hb=0a8299dd8da7dba7437550d12bf180d9e10d512b;hpb=42ce69710691440c9afc2781124b57447fa18415 diff --git a/config_file.l b/config_file.l index f6fff31..f603b8e 100644 --- a/config_file.l +++ b/config_file.l @@ -7,6 +7,12 @@ /* 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 @@ -27,13 +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; + struct lls_yy_config_file_extra { + int argc; + char **argv; + const char *subcmd; + }; - static int add_option(void); - static int parse_arg(char **result); - static int yywrap(void) {return 1;} + static int add_option(yyscan_t yyscanner); + static int parse_arg(char **result, yyscan_t yyscanner); + static int yywrap(yyscan_t yyscanner) {return 1;} %} %% @@ -44,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])) @@ -56,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; @@ -73,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; @@ -89,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); } @@ -105,51 +115,58 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]* #include #include -static int expand_result(void) +static int expand_result(yyscan_t yyscanner) { - int nargc = rargc + 1; - char **nrargv = realloc(rargv, (nargc + 1) * sizeof(char *)); + 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; - rargc = nargc; - rargv = nrargv; - rargv[rargc] = NULL; + extra->argc = nargc; + extra->argv = nrargv; + extra->argv[extra->argc] = NULL; return 1; } -static int add_option(void) +static int add_option(yyscan_t yyscanner) { + struct lls_yy_config_file_extra *extra = yyget_extra(yyscanner); int ret; unsigned n; + int len = yyget_leng(yyscanner); + char *narg, *text = yyget_text(yyscanner); - for (n = 0; n < yyleng; n++) - if (!isalnum(yytext[n]) && !(yytext[n] == '-')) + for (n = 0; n < len; n++) + if (!isalnum(text[n]) && !(text[n] == '-')) break; assert(n > 0); - ret = expand_result(); + ret = expand_result(yyscanner); if (ret < 0) return ret; - rargv[rargc - 1] = malloc(n + 2 + 1); - if (!rargv[rargc - 1]) + narg = malloc(n + 2 + 1); + if (!narg) 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'; + 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) +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(yyleng + 1); + *result = malloc(len + 1); if (!*result) return -E_LLS_NOMEM; - for (in = yytext, out = *result; *in; in++) { + for (in = text, out = *result; *in; in++) { if (*in == '\\') { if (!backslash) { backslash = true; @@ -199,61 +216,75 @@ fail: return ret; } +void lls_free_argv(char **argv) +{ + int i; + + if (!argv) + return; + for (i = 0; argv[i]; i++) + 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; - 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) + + extra.argc = 1; + extra.argv = malloc((extra.argc + 1) * sizeof(char *)); + if (!extra.argv) return -E_LLS_NOMEM; - rargv[0] = strdup(__FUNCTION__); - if (!rargv[0]) { - free(rargv); + extra.argv[0] = strdup(__FUNCTION__); + if (!extra.argv[0]) { + free(extra.argv); return -E_LLS_NOMEM; } - rargv[1] = NULL; - ret = yylex(); - yy_delete_buffer(yybs); - if (ret >= 0) { - *result = rargv; - return rargc; + extra.argv[1] = NULL; + extra.subcmd = subcmd; + + ret = yylex_init_extra(&extra, &yyscanner); + if (ret != 0) { + ret = -E_LLS_NOMEM; + goto free_argv; } - if (errctx) { - *errctx = malloc(100); - if (*errctx) - sprintf(*errctx, "error at line %d", yyget_lineno()); + yy_push_state(subcmd? INITIAL : SC_SCANNING, yyscanner); + yybs = yy_scan_bytes(buf, nbytes, yyscanner); + if (!yybs) { + ret = -E_LLS_YY_SCAN; + goto destroy; } - for (; rargc >= 0; rargc--) - free(rargv[rargc]); - free(rargv); - *result = NULL; - return -E_LLS_YY_LEX; + 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; } -void lls_free_argv(char **argv) -{ - int i; - - if (!argv) - return; - for (i = 0; argv[i]; i++) - free(argv[i]); - free(argv); -} #if 0 int main(void) {