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
8 %option never-interactive
14 IDENTIFIER [a-zA-Z]+[a-zA-Z0-9_-]*
15 EQUALS [[:space:]]*=[[:space:]]*
16 OPTION [a-zA-Z]+[a-zA-Z0-9_-]*
24 #include "lopsub-internal.h"
29 static const char *subcommand;
31 static int yywrap(void) {return 1;}
32 static int expand_result(void)
34 int nargc = rargc + 1;
35 char **nrargv = realloc(rargv, (nargc + 1) * sizeof(char *));
45 static int add_option(void)
50 for (n = 0; n < yyleng; n++)
51 if (!isalnum(yytext[n]) && !(yytext[n] == '-'))
54 ret = expand_result();
57 rargv[rargc - 1] = malloc(n + 2 + 1);
58 if (!rargv[rargc - 1])
60 rargv[rargc - 1][0] = rargv[rargc - 1][1] = '-';
61 memcpy(rargv[rargc - 1] + 2, yytext, n);
62 rargv[rargc - 1][n + 2] = '\0';
66 static int parse_arg(char **result)
68 bool backslash = false, quote = false;
73 *result = malloc(yyleng + 1);
76 for (in = yytext, out = *result; *in; in++) {
82 } else if (*in == 'n' || *in == 't') {
83 if (backslash) { /* \n or \t */
84 *out++ = (*in == 'n')? '\n' : '\t';
88 } else if (*in == '"') {
93 } else if (isspace(*in)) {
94 if (!backslash && !quote)
97 /* copy the character */
101 ret = -E_LLS_TRAILING_BACKSLASH;
104 ret = -E_LLS_UNMATCHED_QUOTE;
107 /* look at first non-space character */
113 ret = -E_LLS_TRAILING_GARBAGE;
118 return out - *result;
129 /* skip comments and whitespace */
133 <INITIAL,SC_SCANNING>\[[[:space:]]*{IDENTIFIER}[[:space:]]*\][[:space:]]*\n {
136 assert(yytext[0] == '[');
139 for (i = 1; i < yyleng; i++)
140 if (!isspace(yytext[i]))
142 for (j = i; j < yyleng; j++)
143 if (yytext[j] == ']' || isspace(yytext[j]))
147 if (strcmp(yytext + i, subcommand))
153 <SC_SCANNING>{OPTION}[[:space:]]*\n add_option();
155 <SC_SCANNING>{OPTION}({EQUALS}|[[:space:]]+) {
156 int ret = add_option();
164 const char *opt = rargv[rargc - 1];
166 size_t opt_len = strlen(opt), arg_len;
167 int ret = parse_arg(&arg);
172 result = malloc(opt_len + arg_len + 2);
176 result[opt_len] = '=';
177 strcpy(result + opt_len + 1, arg);
179 result[opt_len + arg_len + 1] = '\0';
180 free(rargv[rargc - 1]);
181 rargv[rargc - 1] = result;
187 /* This rule runs iff none of the above patterns matched */
191 #include <sys/types.h>
192 #include <sys/stat.h>
196 int lls_convert_config(const char *buf, size_t nbytes, const char *subcmd,
197 char ***result, char **errctx)
200 YY_BUFFER_STATE yybs;
210 yybs = yy_scan_bytes(buf, nbytes);
212 return -E_LLS_YY_SCAN;
214 rargv = malloc((rargc + 1) * sizeof(char *));
217 rargv[0] = strdup(__FUNCTION__);
224 yy_delete_buffer(yybs);
230 *errctx = malloc(100);
232 sprintf(*errctx, "error at line %d", yyget_lineno());
234 for (; rargc >= 0; rargc--)
238 return -E_LLS_YY_LEX;
241 void lls_free_argv(char **argv)
247 for (i = 0; argv[i]; i++)
254 char buf[100 * 1024];
255 int ret, len, i, argc;
258 ret = read(STDIN_FILENO, buf, sizeof(buf));
262 ret = lls_convert_config(buf, len, NULL, &argv, NULL);
266 for (i = 0; i < argc; i++)
267 printf("argv[%d]: %s\n", i, rargv[i]);