diff options
Diffstat (limited to '')
-rw-r--r-- | src/mds-kbdc/make-tree.c | 109 | ||||
-rw-r--r-- | src/mds-kbdc/raw-data.c | 2 | ||||
-rw-r--r-- | src/mds-kbdc/raw-data.h | 14 |
3 files changed, 100 insertions, 25 deletions
diff --git a/src/mds-kbdc/make-tree.c b/src/mds-kbdc/make-tree.c index c0a2d90..c533416 100644 --- a/src/mds-kbdc/make-tree.c +++ b/src/mds-kbdc/make-tree.c @@ -141,30 +141,86 @@ while (0) -// CHARS_1 +#define CHARS(var) \ + do \ + { \ + if (too_few) \ + break; \ + line += strlen(line); \ + *end = prev_end_char, prev_end_char = '\0'; \ + while (*line && (*line == ' ')) \ + line++; \ + if (*line == '\0') \ + { \ + line = original, end = line + strlen(line); \ + NEW_ERROR(1, ERROR, "too few parameters"); \ + line = end, too_few = 1; \ + } \ + else \ + { \ + char* arg_end = line; \ + char* call_end = arg_end; \ + int escape = 0, quote = 0; \ + while (*arg_end) \ + { \ + char c = *arg_end++; \ + if (escape) escape = 0; \ + else if (arg_end <= call_end) ; \ + else if (c == '\\') \ + { \ + escape = 0; \ + call_end = arg_end + get_end_of_call(arg_end, 0, strlen(arg_end)); \ + } \ + else if (quote) quote = (c != '"'); \ + else if (c == ' ') break; \ + else quote = (c == '"'); \ + } \ + prev_end_char = *arg_end, *arg_end = '\0'; \ + fail_if ((node->var = strdup(line)) == NULL); \ + end = line = arg_end; \ + } \ + } \ + while (0) -// CHARS_2 +#define CHARS_END \ + while (*line && (*line == ' ')) \ + line++; \ + do \ + if (*line) \ + { \ + NEW_ERROR(1, ERROR, "too many parameters"); \ + error->end = strlen(source_code.lines[line_i]); \ + } \ + while (0) \ -#define QUOTES_1(var) \ - { \ - line += strlen(line); \ - *end = prev_end_char; \ - while (*line && (*line == ' ')) \ - line++; \ - if (*line && (*line != '"')) \ - { \ - char* arg_end = line; \ - while (*arg_end && (*arg_end != ' ')) \ - arg_end++; \ - NEW_ERROR(1, ERROR, "parameter must be in quotes"); \ - error->end = (size_t)(arg_end - source_code.lines[line_i]); \ - } \ - *end = '\0'; \ - line = original; \ - } \ - CHARS_1(var) +#define QUOTES \ + do \ + { \ + char* line_ = line; \ + line += strlen(line); \ + *end = prev_end_char; \ + while (*line && (*line == ' ')) \ + line++; \ + if (*line && (*line != '"')) \ + { \ + char* arg_end = line; \ + while (*arg_end && (*arg_end != ' ')) \ + arg_end++; \ + NEW_ERROR(1, ERROR, "parameter must be in quotes"); \ + error->end = (size_t)(arg_end - source_code.lines[line_i]); \ + } \ + *end = '\0'; \ + line = line_; \ + } \ + while (0) + + +#define QUOTES_1(var) \ + QUOTES; \ + CHARS(var); \ + CHARS_END @@ -237,6 +293,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu char* end; char prev_end_char; char* original; + int too_few = 0; while (*line && (*line == ' ')) line++; @@ -321,13 +378,15 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu else if (!strcmp(line, "have_chars")) { NEW_NODE(assumption_have_chars, ASSUMPTION_HAVE_CHARS); - QUOTES_1(filename); + QUOTES_1(chars); LEAF; } else if (!strcmp(line, "have_range")) { NEW_NODE(assumption_have_range, ASSUMPTION_HAVE_RANGE); - CHARS_2(first, last); + CHARS(first); + CHARS(last); + CHARS_END; LEAF; } else if (!strcmp(line, "end")) @@ -357,6 +416,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu ; else { + /* TODO not a keyword if it contains special characters */ NEW_ERROR(1, ERROR, "invalid keyword ‘%s’", line); } @@ -385,8 +445,9 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu #undef QUOTES_1 -#undef CHARS_2 -#undef CHARS_1 +#undef QUOTES +#undef CHARS_END +#undef CHARS #undef NAMES_1 #undef NO_PARAMETERS #undef LEAF diff --git a/src/mds-kbdc/raw-data.c b/src/mds-kbdc/raw-data.c index 7c1f5fd..60c3e17 100644 --- a/src/mds-kbdc/raw-data.c +++ b/src/mds-kbdc/raw-data.c @@ -145,7 +145,7 @@ static char* read_file(const char* restrict pathname, size_t* restrict size) * or `size` if the call do not end (that is, the code ends * prematurely), or zero if there is no function call at `offset` */ -static __attribute__((pure)) size_t get_end_of_call(char* restrict content, size_t offset, size_t size) +size_t get_end_of_call(char* restrict content, size_t offset, size_t size) { #define C content[ptr] #define r(lower, upper) (((lower) <= C) && (C <= (upper))) diff --git a/src/mds-kbdc/raw-data.h b/src/mds-kbdc/raw-data.h index a0217d6..335afc6 100644 --- a/src/mds-kbdc/raw-data.h +++ b/src/mds-kbdc/raw-data.h @@ -81,6 +81,20 @@ void source_code_free(source_code_t* restrict this); /** + * Find the end of a function call + * + * @param content The code + * @param offset The index after the first character after the backslash + * that triggered this call + * @param size The length of `code` + * @return The index of the character after the bracket that closes + * the function call (may be outside the code by one character), + * or `size` if the call do not end (that is, the code ends + * prematurely), or zero if there is no function call at `offset` + */ +size_t get_end_of_call(char* restrict content, size_t offset, size_t size) __attribute__((pure)); + +/** * Read lines of a source file * * @param pathname The pathname of the source file |