config_file.l: Instruct flex to create a reentrant scanner.
authorAndre Noll <maan@tuebingen.mpg.de>
Wed, 12 Jul 2017 09:43:25 +0000 (11:43 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Tue, 28 Nov 2017 09:54:36 +0000 (10:54 +0100)
This requires some modifications:

* Most functions take an additional yyscan_t argument.
* We must call yylex_init and yylex_destroy().
* Accessor methods must be used to get yytext and yylen.

We used to set the initial start condition in lls_convert_config(),
before the call to yylex(). For reentrant scanners, however,
the BEGIN macro can not be used in the user code section where
lls_convert_config() is located. But pushing a state works and should
be equivalent.

The generated scanner is not reentrant yet because it still has global
variables. This issue will be addressed in a subsequent patch.

config_file.l

index f6fff31..d055599 100644 (file)
@@ -7,6 +7,9 @@
  /* 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
+
 %option stack
 %option never-interactive
 %option yylineno
@@ -31,9 +34,9 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]*
        static char **rargv;
        static const char *subcommand;
 
-       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;}
 %}
 
 %%
@@ -62,10 +65,10 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]*
                BEGIN(SC_SCANNING);
 }
 
-<SC_SCANNING>{OPTION}[[:space:]]*\n add_option();
+<SC_SCANNING>{OPTION}[[:space:]]*\n add_option(yyscanner);
 
 <SC_SCANNING>{OPTION}({EQUALS}|[[:space:]]+) {
-       int ret = add_option();
+       int ret = add_option(yyscanner);
 
        if (ret < 0)
                return ret;
@@ -76,7 +79,7 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]*
        const char *opt = rargv[rargc - 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;
@@ -118,13 +121,15 @@ static int expand_result(void)
        return 1;
 }
 
-static int add_option(void)
+static int add_option(yyscan_t yyscanner)
 {
        int ret;
        unsigned n;
+       int len = yyget_leng(yyscanner);
+       char *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();
@@ -134,22 +139,24 @@ static int add_option(void)
        if (!rargv[rargc - 1])
                return -E_LLS_NOMEM;
        rargv[rargc - 1][0] = rargv[rargc - 1][1] = '-';
-       memcpy(rargv[rargc - 1] + 2, yytext, n);
+       memcpy(rargv[rargc - 1] + 2, text, n);
        rargv[rargc - 1][n + 2] = '\0';
        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;
@@ -204,16 +211,16 @@ int lls_convert_config(const char *buf, size_t nbytes, const char *subcmd,
 {
        int ret;
        YY_BUFFER_STATE yybs;
+       yyscan_t yyscanner;
 
        *result = NULL;
        if (errctx)
                *errctx = NULL;
+       ret = yylex_init(&yyscanner);
+       assert(ret == 0);
        subcommand = subcmd;
-       if (!subcmd)
-               BEGIN(SC_SCANNING);
-       else
-               BEGIN(INITIAL);
-       yybs = yy_scan_bytes(buf, nbytes);
+       yy_push_state(subcmd? INITIAL : SC_SCANNING, yyscanner);
+       yybs = yy_scan_bytes(buf, nbytes, yyscanner);
        if (!yybs)
                return -E_LLS_YY_SCAN;
        rargc = 1;
@@ -226,8 +233,9 @@ int lls_convert_config(const char *buf, size_t nbytes, const char *subcmd,
                return -E_LLS_NOMEM;
        }
        rargv[1] = NULL;
-       ret = yylex();
-       yy_delete_buffer(yybs);
+       ret = yylex(yyscanner);
+       yy_delete_buffer(yybs, yyscanner);
+       yylex_destroy(yyscanner);
        if (ret >= 0) {
                *result = rargv;
                return rargc;
@@ -235,7 +243,8 @@ int lls_convert_config(const char *buf, size_t nbytes, const char *subcmd,
        if (errctx) {
                *errctx = malloc(100);
                if (*errctx)
-                       sprintf(*errctx, "error at line %d", yyget_lineno());
+                       sprintf(*errctx, "error at line %d",
+                               yyget_lineno(yyscanner));
        }
        for (; rargc >= 0; rargc--)
                free(rargv[rargc]);