aboutsummaryrefslogtreecommitdiffstats
path: root/src/mds-kbdc/compile-layout.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mds-kbdc/compile-layout.c139
1 files changed, 104 insertions, 35 deletions
diff --git a/src/mds-kbdc/compile-layout.c b/src/mds-kbdc/compile-layout.c
index d6df226..e677c23 100644
--- a/src/mds-kbdc/compile-layout.c
+++ b/src/mds-kbdc/compile-layout.c
@@ -19,6 +19,7 @@
/* TODO add call stack */
#include "include-stack.h"
+#include "builtin-functions.h"
#include "string.h"
#include <stdlib.h>
@@ -150,8 +151,15 @@ static int pop_stack(void)
return 0; /* TODO */
}
-static int get_macro_lax(const char* restrict macro_name,
- const mds_kbdc_tree_macro_t** restrict macro,
+static int set_macro(const mds_kbdc_tree_macro_t* restrict macro,
+ mds_kbdc_include_stack_t* macro_include_stack)
+{
+ (void) macro;
+ (void) macro_include_stack;
+ return 0; /* TODO */
+}
+
+static int get_macro_lax(const char* restrict macro_name, const mds_kbdc_tree_macro_t** restrict macro,
mds_kbdc_include_stack_t** restrict macro_include_stack)
{
(void) macro_name;
@@ -174,6 +182,7 @@ static int get_macro(const mds_kbdc_tree_macro_call_t* restrict macro_call,
}
+
/**
* Compile an include-statement
*
@@ -604,26 +613,11 @@ static int check_function_calls(const mds_kbdc_tree_t* restrict tree)
t (check_function_calls(tree->if_.otherwise));
break;
- case C(LET):
- t (check_function_calls(tree->let.value));
- break;
-
- case C(ARRAY):
- t (check_function_calls(tree->array.elements));
- break;
-
- case C(KEYS):
- t (check_function_calls_in_keys(&(tree->keys)));
- break;
-
- case C(STRING):
- t (check_function_calls_in_string(&(tree->string)));
- break;
-
- case C(MAP):
- t (check_function_calls(tree->map.sequence));
- break;
-
+ case C(LET): t (check_function_calls(tree->let.value)); break;
+ case C(ARRAY): t (check_function_calls(tree->array.elements)); break;
+ case C(KEYS): t (check_function_calls_in_keys(&(tree->keys))); break;
+ case C(STRING): t (check_function_calls_in_string(&(tree->string))); break;
+ case C(MAP): t (check_function_calls(tree->map.sequence)); break;
default:
break;
}
@@ -691,11 +685,37 @@ static int check_name_suffix(struct mds_kbdc_tree_callable* restrict tree)
static int compile_function(mds_kbdc_tree_function_t* restrict tree)
{
#define t(expr) fail_if ((r = (expr), r < 0)); if (r) tree->processed = PROCESS_LEVEL
- int r;
+ const mds_kbdc_tree_function_t* function;
+ mds_kbdc_include_stack_t* function_include_stack;
+ mds_kbdc_include_stack_t* our_include_stack = NULL;
+ char* suffixless;
+ char* suffix_start;
+ size_t arg_count;
+ int r, saved_errno;
t (check_name_suffix((struct mds_kbdc_tree_callable*)tree));
- /* TODO check for redefinition */
+ suffixless = strdup(tree->name);
+ fail_if (suffixless == NULL);
+ suffix_start = strchr(suffixless, '/');
+ *suffix_start++ = '\0';
+ arg_count = (size_t)atoll(suffix_start);
+
+ if (builtin_function_defined(suffixless, arg_count))
+ {
+ NEW_ERROR(tree, ERROR, "function ‘%s’ is already defined as a builtin function", tree->name);
+ return 0;
+ }
+ /* TODO check for redefinition */ function = NULL, function_include_stack = NULL;
+ if (function)
+ {
+ NEW_ERROR(tree, ERROR, "function ‘%s’ is already defined", tree->name);
+ fail_if (mds_kbdc_include_stack_restore(function_include_stack));
+ NEW_ERROR(function, NOTE, "previously defined here");
+ fail_if (mds_kbdc_include_stack_restore(our_include_stack));
+ mds_kbdc_include_stack_free(our_include_stack);
+ return 0;
+ }
t (check_marco_calls(tree->inner));
t (check_function_calls(tree->inner));
@@ -703,8 +723,9 @@ static int compile_function(mds_kbdc_tree_function_t* restrict tree)
/* TODO add definition */
return 0;
- pfail:
- return -1;
+ FAIL_BEGIN;
+ mds_kbdc_include_stack_free(our_include_stack);
+ FAIL_END;
#undef t
}
@@ -723,13 +744,14 @@ static int compile_macro(mds_kbdc_tree_macro_t* restrict tree)
mds_kbdc_include_stack_t* our_include_stack = NULL;
int r, saved_errno;
+ fail_if ((our_include_stack = mds_kbdc_include_stack_save(), our_include_stack == NULL));
+
t (check_name_suffix((struct mds_kbdc_tree_callable*)tree));
t (get_macro_lax(tree->name, &macro, &macro_include_stack));
if (macro)
{
NEW_ERROR(tree, ERROR, "macro ‘%s’ is already defined", tree->name);
- fail_if ((our_include_stack = mds_kbdc_include_stack_save(), our_include_stack == NULL));
fail_if (mds_kbdc_include_stack_restore(macro_include_stack));
NEW_ERROR(macro, NOTE, "previously defined here");
fail_if (mds_kbdc_include_stack_restore(our_include_stack));
@@ -740,7 +762,7 @@ static int compile_macro(mds_kbdc_tree_macro_t* restrict tree)
t (check_marco_calls(tree->inner));
t (check_function_calls(tree->inner));
- /* TODO add definition */
+ t (set_macro(tree, our_include_stack));
return 0;
FAIL_BEGIN;
@@ -967,6 +989,38 @@ static int compile_array(mds_kbdc_tree_array_t* restrict tree)
/**
+ * Check that a chain of strings and key-combinations
+ * does not contain NULL characters
+ *
+ * @param tree The tree to check
+ * @return Zero on success, -1 on error, 1 if any of
+ * the elements contain a NULL character
+ */
+static int check_nonnul(mds_kbdc_tree_t* restrict tree)
+{
+ const char* restrict string;
+ int rc = 0;
+ again:
+ if (tree == NULL)
+ return rc;
+
+ for (string = tree->string.string; *string; string++)
+ if ((string[0] == (char)0xC0) && (string[1] == (char)0x80))
+ {
+ NEW_ERROR(tree, ERROR, "NULL characters are not allowed in mappings");
+ tree->processed = PROCESS_LEVEL;
+ rc = 1;
+ break;
+ }
+
+ tree = tree->next;
+ goto again;
+ pfail:
+ return -1;
+}
+
+
+/**
* Compile a mapping- or value-statement
*
* @param tree The tree to compile
@@ -980,17 +1034,32 @@ static int compile_map(mds_kbdc_tree_map_t* restrict tree)
int saved_errno;
fail_if ((seq = mds_kbdc_tree_dup(tree->sequence), seq = NULL));
- fail_if ((res = mds_kbdc_tree_dup(tree->result), res = NULL));
-
fail_if ((bad |= evaluate_element(seq), bad < 0));
- fail_if ((bad |= evaluate_element(res), bad < 0));
- if (bad)
- return 0;
- /* TODO */
+ if (tree->result)
+ {
+ fail_if ((res = mds_kbdc_tree_dup(tree->result), res = NULL));
+ fail_if ((bad |= evaluate_element(res), bad < 0));
+ }
- /* NUL-characters (0xC0 0x80) is only allowed in value-statements */
+ if (bad)
+ goto done;
+ if (tree->result)
+ {
+ fail_if ((bad |= check_nonnul(seq), bad < 0));
+ fail_if ((bad |= check_nonnul(res), bad < 0));
+ if (bad)
+ goto done;
+
+ /* TODO */
+ }
+ else
+ {
+ /* TODO */
+ }
+
+ done:
mds_kbdc_tree_free(seq);
mds_kbdc_tree_free(res);
return 0;