aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2014-12-05 08:47:22 +0100
committerMattias Andrée <maandree@operamail.com>2014-12-05 08:47:22 +0100
commit0d6bd3bbae6b60a3f16d2a831f063cfd4cd1bdfe (patch)
tree6120d9c1e56f1b0cece7f88b85e5481854e3c3c9
parentmds-kbdc: m + include stack for macro and check for redefinitions of macros (diff)
downloadmds-0d6bd3bbae6b60a3f16d2a831f063cfd4cd1bdfe.tar.gz
mds-0d6bd3bbae6b60a3f16d2a831f063cfd4cd1bdfe.tar.bz2
mds-0d6bd3bbae6b60a3f16d2a831f063cfd4cd1bdfe.tar.xz
mds-kbdc: misc
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to '')
-rw-r--r--Makefile4
-rw-r--r--src/mds-kbdc/builtin-functions.c336
-rw-r--r--src/mds-kbdc/builtin-functions.h (renamed from src/mds-kbdc/functions.h)28
-rw-r--r--src/mds-kbdc/compile-layout.c139
-rw-r--r--src/mds-kbdc/functions.c293
5 files changed, 456 insertions, 344 deletions
diff --git a/Makefile b/Makefile
index 826ae17..805d8c2 100644
--- a/Makefile
+++ b/Makefile
@@ -30,8 +30,8 @@ OBJ_mds-server_ = mds-server interception-condition client multicast \
OBJ_mds-registry_ = mds-registry util globals reexec registry signals \
slave
-OBJ_mds-kbdc_ = mds-kbdc globals raw-data functions string tree \
- make-tree parse-error simplify-tree parsed \
+OBJ_mds-kbdc_ = mds-kbdc globals raw-data builtin-functions string \
+ tree make-tree parse-error simplify-tree parsed \
process-includes validate-tree eliminate-dead-code \
paths include-stack compile-layout
diff --git a/src/mds-kbdc/builtin-functions.c b/src/mds-kbdc/builtin-functions.c
new file mode 100644
index 0000000..cfac8ac
--- /dev/null
+++ b/src/mds-kbdc/builtin-functions.c
@@ -0,0 +1,336 @@
+/**
+ * mds — A micro-display server
+ * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "builtin-functions.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+
+/**
+ * Define useful data for built-in function with 2 parameters
+ */
+#define define_2 \
+ const char32_t* restrict a = *args++; \
+ const char32_t* restrict b = *args++; \
+ size_t an = string_length(a); \
+ size_t bn = string_length(b); \
+ size_t i, n = an > bn ? an : bn; \
+ char32_t* restrict rc = malloc((n + 1) * sizeof(char32_t)); \
+ if (rc == NULL) \
+ return NULL; \
+ rc[n] = -1
+
+/**
+ * Define useful data for built-in function with 1 parameter
+ */
+#define define_1 \
+ const char32_t* restrict a = *args++; \
+ size_t i, n = string_length(a); \
+ char32_t* restrict rc = malloc((n + 1) * sizeof(char32_t)); \
+ if (rc == NULL) \
+ return NULL; \
+ rc[n] = -1
+
+
+/**
+ * Definition of the built-in function add/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_add_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] + b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function sub/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_sub_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] - b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function mul/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_mul_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] * b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function div/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_div_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] / b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function mod/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_mod_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] % b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function rsh/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_rsh_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] << b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function lsh/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_lsh_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] >> b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function or/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_or_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] | b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function and/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_and_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] & b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function xor/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_xor_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] ^ b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function not/1
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_not_1(const char32_t** restrict args)
+{
+ define_1;
+ for (i = 0; i < n; i++)
+ rc[i] = !a[i];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function equals/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_equals_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] == b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function greater/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_greater_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] > b[i % bn];
+ return rc;
+}
+
+
+/**
+ * Definition of the built-in function less/2
+ *
+ * @param args The arguments passed to the function
+ * @return The return value of the function, `NULL` on error
+ */
+static char32_t* builtin_function_less_2(const char32_t** restrict args)
+{
+ define_2;
+ for (i = 0; i < n; i++)
+ rc[i] = a[i % an] < b[i % bn];
+ return rc;
+}
+
+
+/* static char32_t* builtin_function_set_3(const char32_t** restrict args); (variable index value) */
+/* static char32_t* builtin_function_get_2(const char32_t** restrict args); (variable index) */
+
+
+#undef define_1
+#undef define_2
+
+
+/**
+ * Check whether a function is a builtin function
+ *
+ * @param name The name of the function
+ * @param arg_count The number of arguments to pass to the function
+ * @return Whether the described function is a builtin function
+ */
+int builtin_function_defined(const char* restrict name, size_t arg_count)
+{
+ size_t i;
+ static const char* const BUILTIN_FUNCTIONS_2[] =
+ {
+ "add", "sub", "mul", "div", "mod", "rsh", "lsh", "or",
+ "and", "xor", "equals", "greater", "less", "get", NULL
+ };
+
+ if (arg_count == 3)
+ return !strcmp(name, "set");
+ else if (arg_count == 1)
+ return !strcmp(name, "not");
+ else if (arg_count == 2)
+ for (i = 0; BUILTIN_FUNCTIONS_2[i]; i++)
+ if (!strcmp(name, BUILTIN_FUNCTIONS_2[i]))
+ return 1;
+
+ return 0;
+}
+
+
+/**
+ * Invoke a builtin function
+ *
+ * @param name The name of the function
+ * @param arg_count The number of arguments to pass to the function
+ * @param args The arguments to pass
+ * @return The return value of the function, `NULL` on error
+ */
+char32_t* builtin_function_invoke(const char* restrict name, size_t arg_count, const char32_t** restrict args)
+{
+ if (arg_count == 3)
+ if (!strcmp(name, "set"))
+ return NULL; /* TODO builtin_function_set_3(args) */
+
+ if (arg_count == 1)
+ if (!strcmp(name, "not"))
+ return builtin_function_not_1(args);
+
+ if (arg_count != 2)
+ return NULL;
+
+ if (!strcmp(name, "add")) return builtin_function_add_2(args);
+ if (!strcmp(name, "sub")) return builtin_function_sub_2(args);
+ if (!strcmp(name, "mul")) return builtin_function_mul_2(args);
+ if (!strcmp(name, "div")) return builtin_function_div_2(args);
+ if (!strcmp(name, "mod")) return builtin_function_mod_2(args);
+ if (!strcmp(name, "rsh")) return builtin_function_rsh_2(args);
+ if (!strcmp(name, "lsh")) return builtin_function_lsh_2(args);
+ if (!strcmp(name, "or")) return builtin_function_or_2(args);
+ if (!strcmp(name, "and")) return builtin_function_and_2(args);
+ if (!strcmp(name, "xor")) return builtin_function_xor_2(args);
+ if (!strcmp(name, "equals")) return builtin_function_equals_2(args);
+ if (!strcmp(name, "greater")) return builtin_function_greater_2(args);
+ if (!strcmp(name, "less")) return builtin_function_less_2(args);
+ if (!strcmp(name, "get")) return NULL; /* TODO builtin_function_get_2(args) */
+
+ return NULL;
+}
+
diff --git a/src/mds-kbdc/functions.h b/src/mds-kbdc/builtin-functions.h
index 158c0b1..ebe3935 100644
--- a/src/mds-kbdc/functions.h
+++ b/src/mds-kbdc/builtin-functions.h
@@ -15,8 +15,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef MDS_MDS_KBDC_FUNCTIONS_H
-#define MDS_MDS_KBDC_FUNCTIONS_H
+#ifndef MDS_MDS_KBDC_BUILTIN_FUNCTIONS_H
+#define MDS_MDS_KBDC_BUILTIN_FUNCTIONS_H
#include "string.h"
@@ -25,26 +25,26 @@
#include <stdarg.h>
+
/**
- * Check whether a function is defined.
+ * Check whether a function is a builtin function
*
- * @param name The name of the function.
- * @param arg_count The number of arguments to pass to the function.
- * @return Whether the function is defined for the selected number of arguments.
+ * @param name The name of the function
+ * @param arg_count The number of arguments to pass to the function
+ * @return Whether the described function is a builtin function
*/
-int function_check_defined(const char32_t* restrict name, size_t arg_count) __attribute__((nonnull));
+int builtin_function_defined(const char* restrict name, size_t arg_count) __attribute__((pure));
/**
- * Invoke a function defined in the keyboard layout source code, or that is builtin.
+ * Invoke a builtin function
*
- * @param name The name of the function.
- * @param arg_count The number of arguments to pass to the function.
- * @param ...:char32_t* The arguments to pass, do not end with a sentinel.
- * @return The return value of the function, `NULL` on error.
+ * @param name The name of the function
+ * @param arg_count The number of arguments to pass to the function
+ * @param args The arguments to pass
+ * @return The return value of the function, `NULL` on error
*/
-char32_t* function_invoke(const char32_t* restrict name, size_t arg_count, ...) __attribute__((nonnull));
+char32_t* builtin_function_invoke(const char* restrict name, size_t arg_count, const char32_t** restrict args);
-/* TODO define functions, check if function is built in */
#endif
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;
diff --git a/src/mds-kbdc/functions.c b/src/mds-kbdc/functions.c
deleted file mode 100644
index 33fa70d..0000000
--- a/src/mds-kbdc/functions.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/**
- * mds — A micro-display server
- * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include "functions.h"
-
-#include <stdlib.h>
-
-
-
-/**
- * Define useful data for built-in function with 2 parameters.
- */
-#define define_2 \
- const char32_t* restrict a = va_arg(args, const char32_t*); \
- const char32_t* restrict b = va_arg(args, const char32_t*); \
- size_t an = string_length(a); \
- size_t bn = string_length(b); \
- size_t i, n = an > bn ? an : bn; \
- char32_t* restrict rc = malloc((n + 1) * sizeof(char32_t)); \
- if (rc == NULL) \
- return NULL; \
- rc[n] = -1
-
-/**
- * Define useful data for built-in function with 1 parameter.
- */
-#define define_1 \
- const char32_t* restrict a = va_arg(args, const char32_t*); \
- size_t i, n = string_length(a); \
- char32_t* restrict rc = malloc((n + 1) * sizeof(char32_t)); \
- if (rc == NULL) \
- return NULL; \
- rc[n] = -1
-
-
-/**
- * Definition of the built-in function add/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_add_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] + b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function sub/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_sub_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] - b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function mul/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_mul_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] * b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function div/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_div_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] / b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function mod/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_mod_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] % b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function rsh/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_rsh_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] << b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function lsh/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_lsh_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] >> b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function or/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_or_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] | b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function and/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_and_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] & b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function xor/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_xor_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] ^ b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function not/1.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_not_1(va_list args)
-{
- define_1;
- for (i = 0; i < n; i++)
- rc[i] = !a[i];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function equals/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_equals_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] == b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function greater/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_greater_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] > b[i % bn];
- return rc;
-}
-
-
-/**
- * Definition of the built-in function less/2.
- *
- * @param args The arguments passed to the function.
- * @return The return value of the function, `NULL` on error.
- */
-static char32_t* function_builtin_less_2(va_list args)
-{
- define_2;
- for (i = 0; i < n; i++)
- rc[i] = a[i % an] < b[i % bn];
- return rc;
-}
-
-
-/* static char32_t* function_builtin_set_3(va_list args); (variable index value) */
-/* static char32_t* function_builtin_get_2(va_list args); (variable index) */
-
-
-#undef define_1
-#undef define_2
-
-
-/**
- * Check whether a function is defined.
- *
- * @param name The name of the function.
- * @param arg_count The number of arguments to pass to the function.
- * @return Whether the function is defined for the selected number of arguments.
- */
-int function_check_defined(const char32_t* restrict name, size_t arg_count)
-{
- return 0; /* TODO */
-}
-
-
-/**
- * Invoke a function defined in the keyboard layout source code, or that is builtin.
- *
- * @param name The name of the function.
- * @param arg_count The number of arguments to pass to the function.
- * @param ...:char32_t* The arguments to pass, do not end with a sentinel.
- * @return The return value of the function, `NULL` on error.
- */
-char32_t* function_invoke(const char32_t* restrict name, size_t arg_count, ...)
-{
- return NULL; /* TODO */
-}
-