- 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;
- }