#include <ecoli_test.h>
#include <ecoli_strvec.h>
#include <ecoli_node.h>
+#include <ecoli_parsed.h>
+#include <ecoli_completed.h>
#include <ecoli_node_seq.h>
#include <ecoli_node_str.h>
#include <ecoli_node_option.h>
{
size_t i = 0;
- /* skip spaces */
- while (!isblank(str[i]) && str[i] != '\0')
+ /* eat chars until we find a quote, space, or end of string */
+ while (!isblank(str[i]) && str[i] != '\0' &&
+ str[i] != '"' && str[i] != '\'')
i++;
return i;
// printf("str=%s\n", str);
- strvec = ec_strvec_new();
+ strvec = ec_strvec();
if (strvec == NULL)
goto fail;
return NULL;
}
-static struct ec_parsed *ec_node_sh_lex_parse(const struct ec_node *gen_node,
- const struct ec_strvec *strvec)
+static int
+ec_node_sh_lex_parse(const struct ec_node *gen_node,
+ struct ec_parsed *state,
+ const struct ec_strvec *strvec)
{
struct ec_node_sh_lex *node = (struct ec_node_sh_lex *)gen_node;
- struct ec_strvec *new_vec = NULL, *match_strvec;
- struct ec_parsed *parsed = NULL, *child_parsed;
+ struct ec_strvec *new_vec = NULL;
+ struct ec_parsed *child_parsed;
const char *str;
+ int ret;
- parsed = ec_parsed_new();
- if (parsed == NULL)
- return NULL;
-
- if (ec_strvec_len(strvec) == 0)
- return parsed;
-
- str = ec_strvec_val(strvec, 0);
- new_vec = tokenize(str, 0, 0, NULL);
- if (new_vec == NULL)
- goto fail;
-
- child_parsed = ec_node_parse_strvec(node->child, new_vec);
- if (child_parsed == NULL)
+ if (ec_strvec_len(strvec) == 0) {
+ new_vec = ec_strvec();
+ } else {
+ str = ec_strvec_val(strvec, 0);
+ new_vec = tokenize(str, 0, 0, NULL);
+ }
+ if (new_vec == NULL) {
+ ret = -ENOMEM;
goto fail;
+ }
- if (!ec_parsed_matches(child_parsed) ||
- ec_parsed_len(child_parsed) !=
- ec_strvec_len(new_vec)) {
- ec_strvec_free(new_vec);
- ec_parsed_free(child_parsed);
- return parsed;
+ ret = ec_node_parse_child(node->child, state, new_vec);
+ if (ret >= 0) {
+ if ((unsigned)ret == ec_strvec_len(new_vec)) {
+ ret = 1;
+ } else {
+ child_parsed = ec_parsed_get_last_child(state);
+ ec_parsed_del_child(state, child_parsed);
+ ec_parsed_free(child_parsed);
+ ret = EC_PARSED_NOMATCH;
+ }
}
+
ec_strvec_free(new_vec);
new_vec = NULL;
- ec_parsed_add_child(parsed, child_parsed);
- match_strvec = ec_strvec_ndup(strvec, 0, 1);
- if (match_strvec == NULL)
- goto fail;
- ec_parsed_set_match(parsed, gen_node, match_strvec);
-
- return parsed;
+ return ret;
fail:
ec_strvec_free(new_vec);
- ec_parsed_free(parsed);
-
- return NULL;
+ return ret;
}
-static struct ec_completed *ec_node_sh_lex_complete(const struct ec_node *gen_node,
- const struct ec_strvec *strvec)
+static int
+ec_node_sh_lex_complete(const struct ec_node *gen_node,
+ struct ec_completed *completed,
+ struct ec_parsed *parsed,
+ const struct ec_strvec *strvec)
{
struct ec_node_sh_lex *node = (struct ec_node_sh_lex *)gen_node;
- struct ec_completed *completed, *child_completed = NULL;
struct ec_strvec *new_vec = NULL;
const char *str;
char missing_quote;
-
-// printf("==================\n");
- completed = ec_completed_new();
- if (completed == NULL)
- return NULL;
+ int ret;
if (ec_strvec_len(strvec) != 1)
- return completed;
+ return 0;
str = ec_strvec_val(strvec, 0);
+// printf("\nold:%s\n", str);
new_vec = tokenize(str, 1, 1, &missing_quote);
if (new_vec == NULL)
goto fail;
+// printf("new:%s\n", ec_strvec_val(new_vec, 0));
-// ec_strvec_dump(new_vec, stdout);
-
- child_completed = ec_node_complete_strvec(node->child, new_vec);
- if (child_completed == NULL)
+ // XXX: complete should add the quotes for !EC_PARTIAL: use another
+ // completed object
+ ret = ec_node_complete_child(node->child, completed, parsed, new_vec);
+ if (ret < 0)
goto fail;
ec_strvec_free(new_vec);
- new_vec = NULL;
- ec_completed_merge(completed, child_completed);
- return completed;
+ return 0;
fail:
ec_strvec_free(new_vec);
- ec_completed_free(completed);
- return NULL;
+ return -1;
}
static void ec_node_sh_lex_free_priv(struct ec_node *gen_node)
if (child == NULL)
return NULL;
- node = (struct ec_node_sh_lex *)__ec_node_new(&ec_node_sh_lex_type, id);
+ node = (struct ec_node_sh_lex *)__ec_node(&ec_node_sh_lex_type, id);
if (node == NULL) {
ec_node_free(child);
return NULL;
return &node->gen;
}
+/* LCOV_EXCL_START */
static int ec_node_sh_lex_testcase(void)
{
struct ec_node *node;
ret |= EC_TEST_CHECK_PARSE(node, 1, " foo bar");
ret |= EC_TEST_CHECK_PARSE(node, 1, " 'foo' \"bar\"");
ret |= EC_TEST_CHECK_PARSE(node, 1, " 'f'oo 'toto' bar");
+ ret |= EC_TEST_CHECK_PARSE(node, -1, " foo toto bar'");
ec_node_free(node);
/* test completion */
}
ret |= EC_TEST_CHECK_COMPLETE(node,
"", EC_NODE_ENDLIST,
- "foo", EC_NODE_ENDLIST,
- "foo");
+ "foo", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
" ", EC_NODE_ENDLIST,
- "foo", EC_NODE_ENDLIST,
- "foo");
+ "foo", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"f", EC_NODE_ENDLIST,
- "oo", EC_NODE_ENDLIST,
- "oo");
+ "foo", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"foo", EC_NODE_ENDLIST,
- "", EC_NODE_ENDLIST,
- "");
+ "foo", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"foo ", EC_NODE_ENDLIST,
- "bar", "toto", EC_NODE_ENDLIST,
- "");
+ "bar", "toto", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"foo t", EC_NODE_ENDLIST,
- "oto", EC_NODE_ENDLIST,
- "oto");
+ "toto", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"foo b", EC_NODE_ENDLIST,
- "ar", EC_NODE_ENDLIST,
- "ar");
+ "bar", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"foo bar", EC_NODE_ENDLIST,
- "", EC_NODE_ENDLIST,
- "");
+ "bar", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"foo bar ", EC_NODE_ENDLIST,
- "titi", EC_NODE_ENDLIST,
- "titi");
+ "titi", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"foo toto bar ", EC_NODE_ENDLIST,
- "titi", EC_NODE_ENDLIST,
- "titi");
+ "titi", EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"x", EC_NODE_ENDLIST,
- EC_NODE_ENDLIST,
- "");
+ EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"foo barx", EC_NODE_ENDLIST,
- EC_NODE_ENDLIST,
- "");
+ EC_NODE_ENDLIST);
ec_node_free(node);
return ret;
}
+/* LCOV_EXCL_STOP */
static struct ec_test ec_node_sh_lex_test = {
.name = "node_sh_lex",