]> git.tuebingen.mpg.de Git - lopsub.git/blobdiff - config_file.l
debian: Final version of 64-bit time_t transition.
[lopsub.git] / config_file.l
index f6fff31e171fc5ba0f2b2cfd47fd41f133fe3e29..66c1b769192186ba77b474bc4bdf65190962768c 100644 (file)
@@ -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
@@ -15,7 +21,7 @@
 %s SC_SCANNING
 
 IDENTIFIER [a-zA-Z]+[a-zA-Z0-9_-]*
-EQUALS [[:space:]]*=[[:space:]]*
+EQUALS [[:blank:]]*=[[:blank:]]*
 OPTION [a-zA-Z]+[a-zA-Z0-9_-]*
 
 %{
@@ -27,26 +33,29 @@ 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;}
 %}
 
 %%
 
  /* skip comments and whitespace */
-^[[:space:]]*#.*\n ;
-[[:space:]]|\n+ ;
+^[[:blank:]]*#.*\n ;
+[[:blank:]]|\n+ ;
 
-<INITIAL,SC_SCANNING>\[[[:space:]]*{IDENTIFIER}[[:space:]]*\][[:space:]]*\n {
+<INITIAL,SC_SCANNING>\[[[:blank:]]*{IDENTIFIER}[[:blank:]]*\][[:blank:]]*\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);
 }
 
-<SC_SCANNING>{OPTION}[[:space:]]*\n add_option();
+<SC_SCANNING>{OPTION}[[:blank:]]*\n add_option(yyscanner);
 
-<SC_SCANNING>{OPTION}({EQUALS}|[[:space:]]+) {
-       int ret = add_option();
+<SC_SCANNING>{OPTION}({EQUALS}|[[:blank:]]+) {
+       int ret = add_option(yyscanner);
 
        if (ret < 0)
                return ret;
@@ -73,10 +82,11 @@ OPTION [a-zA-Z]+[a-zA-Z0-9_-]*
 }
 
 <SC_ARG>.*\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 <fcntl.h>
 #include <stdio.h>
 
-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,62 +216,76 @@ 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, "yylex error");
+               }
+       }
+       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
+/* flex -o t.c config_file.l && cc -o tcf t.c */
 int main(void)
 {
        char buf[100 * 1024];
@@ -270,7 +301,7 @@ int main(void)
                exit(EXIT_FAILURE);
        argc = ret;
        for (i = 0; i < argc; i++)
-               printf("argv[%d]: %s\n", i, rargv[i]);
+               printf("argv[%d]: %s\n", i, argv[i]);
        return EXIT_SUCCESS;
 }
 #endif