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"
11 %option never-interactive
17 IDENTIFIER [a-zA-Z]+[a-zA-Z0-9_-]*
18 EQUALS [[:space:]]*=[[:space:]]*
19 OPTION [a-zA-Z]+[a-zA-Z0-9_-]*
27 #include "lopsub-internal.h"
32 static const char *subcommand;
34 static int add_option(void);
35 static int parse_arg(char **result);
36 static int yywrap(void) {return 1;}
41 /* skip comments and whitespace */
45 <INITIAL,SC_SCANNING>\[[[:space:]]*{IDENTIFIER}[[:space:]]*\][[:space:]]*\n {
48 assert(yytext[0] == '[');
51 for (i = 1; i < yyleng; i++)
52 if (!isspace(yytext[i]))
54 for (j = i; j < yyleng; j++)
55 if (yytext[j] == ']' || isspace(yytext[j]))
59 if (strcmp(yytext + i, subcommand))
65 <SC_SCANNING>{OPTION}[[:space:]]*\n add_option();
67 <SC_SCANNING>{OPTION}({EQUALS}|[[:space:]]+) {
68 int ret = add_option();
76 const char *opt = rargv[rargc - 1];
78 size_t opt_len = strlen(opt), arg_len;
79 int ret = parse_arg(&arg);
84 result = malloc(opt_len + arg_len + 2);
88 result[opt_len] = '=';
89 strcpy(result + opt_len + 1, arg);
91 result[opt_len + arg_len + 1] = '\0';
92 free(rargv[rargc - 1]);
93 rargv[rargc - 1] = result;
99 /* This rule runs iff none of the above patterns matched */
103 #include <sys/types.h>
104 #include <sys/stat.h>
108 static int expand_result(void)
110 int nargc = rargc + 1;
111 char **nrargv = realloc(rargv, (nargc + 1) * sizeof(char *));
121 static int add_option(void)
126 for (n = 0; n < yyleng; n++)
127 if (!isalnum(yytext[n]) && !(yytext[n] == '-'))
130 ret = expand_result();
133 rargv[rargc - 1] = malloc(n + 2 + 1);
134 if (!rargv[rargc - 1])
136 rargv[rargc - 1][0] = rargv[rargc - 1][1] = '-';
137 memcpy(rargv[rargc - 1] + 2, yytext, n);
138 rargv[rargc - 1][n + 2] = '\0';
142 static int parse_arg(char **result)
144 bool backslash = false, quote = false;
149 *result = malloc(yyleng + 1);
152 for (in = yytext, out = *result; *in; in++) {
158 } else if (*in == 'n' || *in == 't') {
159 if (backslash) { /* \n or \t */
160 *out++ = (*in == 'n')? '\n' : '\t';
164 } else if (*in == '"') {
169 } else if (isspace(*in)) {
170 if (!backslash && !quote)
173 /* copy the character */
177 ret = -E_LLS_TRAILING_BACKSLASH;
180 ret = -E_LLS_UNMATCHED_QUOTE;
183 /* look at first non-space character */
189 ret = -E_LLS_TRAILING_GARBAGE;
194 return out - *result;
202 int lls_convert_config(const char *buf, size_t nbytes, const char *subcmd,
203 char ***result, char **errctx)
206 YY_BUFFER_STATE yybs;
216 yybs = yy_scan_bytes(buf, nbytes);
218 return -E_LLS_YY_SCAN;
220 rargv = malloc((rargc + 1) * sizeof(char *));
223 rargv[0] = strdup(__FUNCTION__);
230 yy_delete_buffer(yybs);
236 *errctx = malloc(100);
238 sprintf(*errctx, "error at line %d", yyget_lineno());
240 for (; rargc >= 0; rargc--)
244 return -E_LLS_YY_LEX;
247 void lls_free_argv(char **argv)
253 for (i = 0; argv[i]; i++)
260 char buf[100 * 1024];
261 int ret, len, i, argc;
264 ret = read(STDIN_FILENO, buf, sizeof(buf));
268 ret = lls_convert_config(buf, len, NULL, &argv, NULL);
272 for (i = 0; i < argc; i++)
273 printf("argv[%d]: %s\n", i, rargv[i]);