aboutsummaryrefslogtreecommitdiffstats
path: root/src/mds-kbdc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mds-kbdc')
-rw-r--r--src/mds-kbdc/make-tree.c109
-rw-r--r--src/mds-kbdc/raw-data.c2
-rw-r--r--src/mds-kbdc/raw-data.h14
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