* Licensed under the LGPL v3, see http://www.gnu.org/licenses/lgpl-3.0.html
*/
-%option noyywrap
+ /* 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
static char **rargv;
static const char *subcommand;
- 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;
-
- 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;}
%}
%%
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;
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;
#include <fcntl.h>
#include <stdio.h>
+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(yyscan_t yyscanner)
+{
+ int ret;
+ unsigned n;
+ int len = yyget_leng(yyscanner);
+ char *text = yyget_text(yyscanner);
+
+ for (n = 0; n < len; n++)
+ if (!isalnum(text[n]) && !(text[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, text, n);
+ rargv[rargc - 1][n + 2] = '\0';
+ 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;
+ }
+ 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;
+}
+
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;
*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;
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;
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]);