2 * Copyright (C) 2016 Andre Noll <maan@tuebingen.mpg.de>
4 * Licensed under the LGPL v3, see http://www.gnu.org/licenses/lgpl-3.0.html
7 /* We don't want symbols to clash with those of other flex users. */
8 %option prefix="lls_yy"
10 /* Generate a scanner which is safe to use in multithreaded programs. */
14 %option never-interactive
20 IDENTIFIER [a-zA-Z]+[a-zA-Z0-9_-]*
21 EQUALS [[:space:]]*=[[:space:]]*
22 OPTION [a-zA-Z]+[a-zA-Z0-9_-]*
30 #include "lopsub-internal.h"
35 static const char *subcommand;
37 static int add_option(yyscan_t yyscanner);
38 static int parse_arg(char **result, yyscan_t yyscanner);
39 static int yywrap(yyscan_t yyscanner) {return 1;}
44 /* skip comments and whitespace */
48 <INITIAL,SC_SCANNING>\[[[:space:]]*{IDENTIFIER}[[:space:]]*\][[:space:]]*\n {
51 assert(yytext[0] == '[');
54 for (i = 1; i < yyleng; i++)
55 if (!isspace(yytext[i]))
57 for (j = i; j < yyleng; j++)
58 if (yytext[j] == ']' || isspace(yytext[j]))
62 if (strcmp(yytext + i, subcommand))
68 <SC_SCANNING>{OPTION}[[:space:]]*\n add_option(yyscanner);
70 <SC_SCANNING>{OPTION}({EQUALS}|[[:space:]]+) {
71 int ret = add_option(yyscanner);
79 const char *opt = rargv[rargc - 1];
81 size_t opt_len = strlen(opt), arg_len;
82 int ret = parse_arg(&arg, yyscanner);
87 result = malloc(opt_len + arg_len + 2);
91 result[opt_len] = '=';
92 strcpy(result + opt_len + 1, arg);
94 result[opt_len + arg_len + 1] = '\0';
95 free(rargv[rargc - 1]);
96 rargv[rargc - 1] = result;
102 /* This rule runs iff none of the above patterns matched */
106 #include <sys/types.h>
107 #include <sys/stat.h>
111 static int expand_result(void)
113 int nargc = rargc + 1;
114 char **nrargv = realloc(rargv, (nargc + 1) * sizeof(char *));
124 static int add_option(yyscan_t yyscanner)
128 int len = yyget_leng(yyscanner);
129 char *text = yyget_text(yyscanner);
131 for (n = 0; n < len; n++)
132 if (!isalnum(text[n]) && !(text[n] == '-'))
135 ret = expand_result();
138 rargv[rargc - 1] = malloc(n + 2 + 1);
139 if (!rargv[rargc - 1])
141 rargv[rargc - 1][0] = rargv[rargc - 1][1] = '-';
142 memcpy(rargv[rargc - 1] + 2, text, n);
143 rargv[rargc - 1][n + 2] = '\0';
147 static int parse_arg(char **result, yyscan_t yyscanner)
149 bool backslash = false, quote = false;
153 int len = yyget_leng(yyscanner);
154 char *text = yyget_text(yyscanner);
156 *result = malloc(len + 1);
159 for (in = text, out = *result; *in; in++) {
165 } else if (*in == 'n' || *in == 't') {
166 if (backslash) { /* \n or \t */
167 *out++ = (*in == 'n')? '\n' : '\t';
171 } else if (*in == '"') {
176 } else if (isspace(*in)) {
177 if (!backslash && !quote)
180 /* copy the character */
184 ret = -E_LLS_TRAILING_BACKSLASH;
187 ret = -E_LLS_UNMATCHED_QUOTE;
190 /* look at first non-space character */
196 ret = -E_LLS_TRAILING_GARBAGE;
201 return out - *result;
209 int lls_convert_config(const char *buf, size_t nbytes, const char *subcmd,
210 char ***result, char **errctx)
213 YY_BUFFER_STATE yybs;
219 ret = yylex_init(&yyscanner);
222 yy_push_state(subcmd? INITIAL : SC_SCANNING, yyscanner);
223 yybs = yy_scan_bytes(buf, nbytes, yyscanner);
225 return -E_LLS_YY_SCAN;
227 rargv = malloc((rargc + 1) * sizeof(char *));
230 rargv[0] = strdup(__FUNCTION__);
236 ret = yylex(yyscanner);
237 yy_delete_buffer(yybs, yyscanner);
238 yylex_destroy(yyscanner);
244 *errctx = malloc(100);
246 sprintf(*errctx, "error at line %d",
247 yyget_lineno(yyscanner));
249 for (; rargc >= 0; rargc--)
253 return -E_LLS_YY_LEX;
256 void lls_free_argv(char **argv)
262 for (i = 0; argv[i]; i++)
269 char buf[100 * 1024];
270 int ret, len, i, argc;
273 ret = read(STDIN_FILENO, buf, sizeof(buf));
277 ret = lls_convert_config(buf, len, NULL, &argv, NULL);
281 for (i = 0; i < argc; i++)
282 printf("argv[%d]: %s\n", i, rargv[i]);