aboutsummaryrefslogtreecommitdiffstats
path: root/src/mds-kbdc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mds-kbdc/compile-layout.c81
-rw-r--r--src/mds-kbdc/include-stack.c98
-rw-r--r--src/mds-kbdc/include-stack.h46
3 files changed, 199 insertions, 26 deletions
diff --git a/src/mds-kbdc/compile-layout.c b/src/mds-kbdc/compile-layout.c
index 62eb925..d6df226 100644
--- a/src/mds-kbdc/compile-layout.c
+++ b/src/mds-kbdc/compile-layout.c
@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "compile-layout.h"
+/* TODO add call stack */
#include "include-stack.h"
#include "string.h"
@@ -40,13 +41,12 @@
* Add an error with “included from here”-notes to the error list
*
* @param NODE:const mds_kbdc_tree_t* The node the triggered the error
- * @param PTR:size_t The number of “included from here”-notes
* @param SEVERITY:identifier * in `MDS_KBDC_PARSE_ERROR_*` to indicate severity
* @param ...:const char*, ... Error description format string and arguments
* @scope error:mds_kbdc_parse_error_t* Variable where the new error will be stored
*/
-#define NEW_ERROR(NODE, PTR, SEVERITY, ...) \
- NEW_ERROR_WITH_INCLUDES(NODE, PTR, SEVERITY, __VA_ARGS__)
+#define NEW_ERROR(NODE, SEVERITY, ...) \
+ NEW_ERROR_WITH_INCLUDES(NODE, includes_ptr, SEVERITY, __VA_ARGS__)
/**
* Beginning of failure clause
@@ -150,12 +150,24 @@ 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,
+ mds_kbdc_include_stack_t** restrict macro_include_stack)
+{
+ (void) macro_name;
+ (void) macro;
+ (void) macro_include_stack;
+ return 0; /* TODO */
+}
+
static int get_macro(const mds_kbdc_tree_macro_call_t* restrict macro_call,
- const mds_kbdc_tree_macro_t** restrict macro)
+ const mds_kbdc_tree_macro_t** restrict macro,
+ mds_kbdc_include_stack_t** restrict macro_include_stack)
{
- NEW_ERROR(macro_call, includes_ptr, ERROR, "macro ‘%s’ as not been defined yet", macro_call->name);
+ NEW_ERROR(macro_call, ERROR, "macro ‘%s’ as not been defined yet", macro_call->name);
/* return set `*macro = NULL` if `(*macro)->processed == PROCESS_LEVEL` */
(void) macro;
+ (void) macro_include_stack;
return 0; /* TODO */
pfail:
return -1;
@@ -265,7 +277,7 @@ static int compile_variant(mds_kbdc_tree_information_variant_t* restrict tree)
if (result->variant)
{
if (multiple_variants == 0)
- NEW_ERROR(tree, includes_ptr, ERROR, "only one ‘variant’ is allowed");
+ NEW_ERROR(tree, ERROR, "only one ‘variant’ is allowed");
multiple_variants = 1;
return 0;
}
@@ -400,13 +412,13 @@ static int compile_have_range(mds_kbdc_tree_assumption_have_range_t* restrict tr
if ((first[0] < 0) || (first[1] >= 0))
{
- NEW_ERROR(tree, includes_ptr, ERROR, "iteration boundary must be a single character string");
+ NEW_ERROR(tree, ERROR, "iteration boundary must be a single character string");
error->start = lineoff_first, lineoff_first = 0;
error->end = error->start + strlen(tree->first);
}
if ((last[0] < 0) || (last[1] >= 0))
{
- NEW_ERROR(tree, includes_ptr, ERROR, "iteration boundary must be a single character string");
+ NEW_ERROR(tree, ERROR, "iteration boundary must be a single character string");
error->start = lineoff_last, lineoff_last = 0;
error->end = error->start + strlen(tree->last);
}
@@ -454,7 +466,8 @@ static int compile_have_range(mds_kbdc_tree_assumption_have_range_t* restrict tr
static int check_marco_calls(const mds_kbdc_tree_t* restrict tree)
{
#define t(...) if (rc |= r = (__VA_ARGS__), r < 0) return r
- const mds_kbdc_tree_macro_t* macro;
+ const mds_kbdc_tree_macro_t* _macro;
+ mds_kbdc_include_stack_t* _macro_include_stack;
void* data;
int r, rc = 0;
again:
@@ -478,7 +491,7 @@ static int check_marco_calls(const mds_kbdc_tree_t* restrict tree)
break;
case C(MACRO_CALL):
- t (get_macro(&(tree->macro_call), &macro));
+ t (get_macro(&(tree->macro_call), &_macro, &_macro_include_stack));
break;
default:
@@ -487,7 +500,8 @@ static int check_marco_calls(const mds_kbdc_tree_t* restrict tree)
tree = tree->next;
goto again;
- (void) macro;
+ (void) _macro;
+ (void) _macro_include_stack;
#undef t
}
@@ -633,25 +647,25 @@ static int check_name_suffix(struct mds_kbdc_tree_callable* restrict tree)
if (name == NULL)
{
- NEW_ERROR(tree, includes_ptr, ERROR, "name-suffix is missing");
+ NEW_ERROR(tree, ERROR, "name-suffix is missing");
goto name_error;
}
if (*++name == '\0')
{
- NEW_ERROR(tree, includes_ptr, ERROR, "empty name-suffix");
+ NEW_ERROR(tree, ERROR, "empty name-suffix");
goto name_error;
}
if (!strcmp(name, "0"))
return 0;
if (*name == '\0')
{
- NEW_ERROR(tree, includes_ptr, ERROR, "leading zero in name-suffix");
+ NEW_ERROR(tree, ERROR, "leading zero in name-suffix");
goto name_error;
}
for (; *name; name++)
if ((*name < '0') || ('0' < *name))
{
- NEW_ERROR(tree, includes_ptr, ERROR, "name-suffix may only contain digits");
+ NEW_ERROR(tree, ERROR, "name-suffix may only contain digits");
goto name_error;
}
@@ -704,11 +718,24 @@ static int compile_function(mds_kbdc_tree_function_t* restrict tree)
static int compile_macro(mds_kbdc_tree_macro_t* restrict tree)
{
#define t(expr) fail_if ((r = (expr), r < 0)); if (r) tree->processed = PROCESS_LEVEL
- int r;
+ const mds_kbdc_tree_macro_t* macro;
+ mds_kbdc_include_stack_t* macro_include_stack;
+ mds_kbdc_include_stack_t* our_include_stack = NULL;
+ int r, saved_errno;
t (check_name_suffix((struct mds_kbdc_tree_callable*)tree));
- /* TODO check for redefinition */
+ 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));
+ mds_kbdc_include_stack_free(our_include_stack);
+ return 0;
+ }
t (check_marco_calls(tree->inner));
t (check_function_calls(tree->inner));
@@ -716,8 +743,9 @@ static int compile_macro(mds_kbdc_tree_macro_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
}
@@ -756,13 +784,13 @@ static int compile_for(mds_kbdc_tree_for_t* restrict tree)
if ((first[0] < 0) || (first[1] >= 0))
{
- NEW_ERROR(tree, includes_ptr, ERROR, "iteration boundary must be a single character string");
+ NEW_ERROR(tree, ERROR, "iteration boundary must be a single character string");
error->start = lineoff_first, lineoff_first = 0;
error->end = error->start + strlen(tree->first);
}
if ((last[0] < 0) || (last[1] >= 0))
{
- NEW_ERROR(tree, includes_ptr, ERROR, "iteration boundary must be a single character string");
+ NEW_ERROR(tree, ERROR, "iteration boundary must be a single character string");
error->start = lineoff_last, lineoff_last = 0;
error->end = error->start + strlen(tree->last);
}
@@ -983,7 +1011,9 @@ static int compile_macro_call(mds_kbdc_tree_macro_call_t* restrict tree)
{
mds_kbdc_tree_t* arg = NULL;
mds_kbdc_tree_t* arg_;
- const mds_kbdc_tree_macro_t* macro = NULL;
+ const mds_kbdc_tree_macro_t* macro;
+ mds_kbdc_include_stack_t* macro_include_stack;
+ mds_kbdc_include_stack_t* our_include_stack = NULL;
size_t variable;
int bad, saved_errno;
@@ -992,14 +1022,18 @@ static int compile_macro_call(mds_kbdc_tree_macro_call_t* restrict tree)
if (bad)
return 0;
- fail_if (get_macro(tree, &macro));
+ fail_if (get_macro(tree, &macro, &macro_include_stack));
if (macro == NULL)
goto done;
fail_if (push_stack());
for (arg_ = arg; arg_; arg_ = arg_->next)
fail_if (let(variable, NULL, arg_, NULL, 0, 0));
+ fail_if ((our_include_stack = mds_kbdc_include_stack_save(), our_include_stack == NULL));
+ fail_if (mds_kbdc_include_stack_restore(macro_include_stack));
fail_if (compile_subtree(macro->inner));
+ fail_if (mds_kbdc_include_stack_restore(our_include_stack));
+ mds_kbdc_include_stack_free(our_include_stack), our_include_stack = NULL;
fail_if (pop_stack());
done:
@@ -1008,6 +1042,7 @@ static int compile_macro_call(mds_kbdc_tree_macro_call_t* restrict tree)
return 0;
FAIL_BEGIN;
mds_kbdc_tree_free(arg);
+ mds_kbdc_include_stack_free(our_include_stack);
FAIL_END;
}
diff --git a/src/mds-kbdc/include-stack.c b/src/mds-kbdc/include-stack.c
index 401bde5..dd2bc98 100644
--- a/src/mds-kbdc/include-stack.c
+++ b/src/mds-kbdc/include-stack.c
@@ -20,6 +20,7 @@
#include <alloca.h>
#include <stdlib.h>
#include <errno.h>
+#include <string.h>
@@ -58,6 +59,11 @@ static size_t includes_size = 0;
*/
size_t includes_ptr = 0;
+/**
+ * The latest saved include-stack
+ */
+static mds_kbdc_include_stack_t* latest_save = NULL;
+
/**
@@ -93,6 +99,7 @@ int mds_kbdc_include_stack_dump(size_t ptr)
*/
void mds_kbdc_include_stack_begin(mds_kbdc_parsed_t* restrict result_)
{
+ latest_save = NULL;
result = result_;
original_pathname = result_->pathname;
original_source_code = result_->source_code;
@@ -108,6 +115,7 @@ void mds_kbdc_include_stack_begin(mds_kbdc_parsed_t* restrict result_)
void mds_kbdc_include_stack_end(void)
{
int saved_errno = errno;
+ latest_save = NULL;
result->pathname = original_pathname;
result->source_code = original_source_code;
free(includes), includes = NULL;
@@ -133,15 +141,16 @@ int mds_kbdc_include_stack_push(const mds_kbdc_tree_include_t* restrict tree, vo
if (includes_ptr == includes_size)
fail_if (xxrealloc(old, includes, includes_size += 4, mds_kbdc_tree_include_t*));
- fail_if (xmalloc(*data, 2, void*));
-
- includes[includes_ptr++] = tree;
+ fail_if (xmalloc(*data, 3, void*));
((char**)(*data))[0] = result->pathname;
((mds_kbdc_source_code_t**)(*data))[1] = result->source_code;
+ ((mds_kbdc_include_stack_t**)(*data))[2] = latest_save;
+ includes[includes_ptr++] = tree;
result->pathname = tree->filename;
result->source_code = tree->source_code;
+ latest_save = NULL;
return 0;
pfail:
@@ -163,8 +172,91 @@ void mds_kbdc_include_stack_pop(void* data)
int saved_errno = errno;
result->pathname = ((char**)data)[0];
result->source_code = ((mds_kbdc_source_code_t**)data)[1];
+ latest_save = ((mds_kbdc_include_stack_t**)data)[2];
includes_ptr--;
free(data);
errno = saved_errno;
}
+
+/**
+ * Save the current include-stack
+ *
+ * @return The include-stack, `NULL` on error
+ */
+mds_kbdc_include_stack_t* mds_kbdc_include_stack_save(void)
+{
+ int saved_errno;
+
+ if (latest_save)
+ {
+ latest_save->duplicates++;
+ return latest_save;
+ }
+
+ latest_save = malloc(sizeof(mds_kbdc_include_stack_t));
+ if (latest_save == NULL)
+ return NULL;
+
+ latest_save->stack = NULL;
+ latest_save->ptr = includes_ptr;
+ latest_save->duplicates = 0;
+
+ if (latest_save->ptr == 0)
+ return latest_save;
+
+ fail_if (xmalloc(latest_save->stack, latest_save->ptr, const mds_kbdc_tree_include_t*));
+ memcpy(latest_save->stack, includes, latest_save->ptr * sizeof(const mds_kbdc_tree_include_t*));
+
+ return latest_save;
+ pfail:
+ saved_errno = errno;
+ free(latest_save->stack);
+ latest_save = NULL;
+ errno = saved_errno;
+ return NULL;
+}
+
+
+/**
+ * Restore a previous include-stack
+ *
+ * @param stack The include-stack
+ * @return Zero on success, -1 on error
+ */
+int mds_kbdc_include_stack_restore(mds_kbdc_include_stack_t* restrict stack)
+{
+ const mds_kbdc_tree_include_t** new;
+
+ latest_save = stack;
+
+ if (stack->ptr > includes_size)
+ {
+ new = realloc(includes, stack->ptr * sizeof(const mds_kbdc_tree_include_t*));
+ if (new == NULL)
+ return -1;
+ includes = new;
+ includes_size = stack->ptr;
+ }
+
+ memcpy(includes, stack->stack, stack->ptr * sizeof(const mds_kbdc_tree_include_t*));
+ includes_ptr = stack->ptr;
+ return 0;
+}
+
+
+/**
+ * Destroy a previous include-stack and free its allocation
+ *
+ * @param stack The include-stack
+ */
+void mds_kbdc_include_stack_free(mds_kbdc_include_stack_t* restrict stack)
+{
+ if ((stack == NULL) || (stack->duplicates--))
+ return;
+ free(stack->stack);
+ free(stack);
+ if (latest_save == stack)
+ latest_save = NULL;
+}
+
diff --git a/src/mds-kbdc/include-stack.h b/src/mds-kbdc/include-stack.h
index 6758589..49a6248 100644
--- a/src/mds-kbdc/include-stack.h
+++ b/src/mds-kbdc/include-stack.h
@@ -63,6 +63,30 @@
/**
+ * A saved state of the include stack
+ */
+typedef struct mds_kbdc_include_stack
+{
+ /**
+ * Stack of visited include-statements
+ */
+ const mds_kbdc_tree_include_t** stack;
+
+ /**
+ * The number elements stored in `stack` (do not edit)
+ */
+ size_t ptr;
+
+ /**
+ * The number of duplicates there are of this object
+ */
+ size_t duplicates;
+
+} mds_kbdc_include_stack_t;
+
+
+
+/**
* The number elements stored by `mds_kbdc_include_stack_push`
* but not removed by `mds_kbdc_include_stack_pop`
*/
@@ -113,6 +137,28 @@ int mds_kbdc_include_stack_push(const mds_kbdc_tree_include_t* restrict tree, vo
*/
void mds_kbdc_include_stack_pop(void* data);
+/**
+ * Save the current include-stack
+ *
+ * @return The include-stack, `NULL` on error
+ */
+mds_kbdc_include_stack_t* mds_kbdc_include_stack_save(void);
+
+/**
+ * Restore a previous include-stack
+ *
+ * @param stack The include-stack
+ * @return Zero on success, -1 on error
+ */
+int mds_kbdc_include_stack_restore(mds_kbdc_include_stack_t* restrict stack);
+
+/**
+ * Destroy a previous include-stack and free its allocation
+ *
+ * @param stack The include-stack
+ */
+void mds_kbdc_include_stack_free(mds_kbdc_include_stack_t* restrict stack);
+
#endif