aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mds-kbdc/process-includes.c149
1 files changed, 145 insertions, 4 deletions
diff --git a/src/mds-kbdc/process-includes.c b/src/mds-kbdc/process-includes.c
index 0b068f1..1e9c5ff 100644
--- a/src/mds-kbdc/process-includes.c
+++ b/src/mds-kbdc/process-includes.c
@@ -17,7 +17,20 @@
*/
#include "process-includes.h"
+#include "make-tree.h"
+#include "simplify-tree.h"
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+
+/**
+ * Tree type constant shortener
+ */
+#define C(TYPE) MDS_KBDC_TREE_TYPE_##TYPE
/**
* Add an error the to error list
@@ -38,20 +51,148 @@
*/
static mds_kbdc_parse_error_t* error;
+/**
+ * The parameter of `process_includes`
+ */
+static mds_kbdc_parsed_t* restrict result;
+
/**
- * Include included files and process them upto this level
+ * Process an include-statement
*
- * @param result `result` from `simplify_tree`, will be updated
- * @return -1 if an error occursed that cannot be stored in `result`, zero otherwise
+ * @param tree The include-statement
+ * @return Zero on success, -1 on error
*/
-int process_includes(mds_kbdc_parsed_t* restrict result)
+static int process_include(mds_kbdc_tree_include_t* restrict tree)
{
+#define process(expr) \
+ fail_if ((expr) < 0); \
+ if (mds_kbdc_parsed_is_fatal(&subresult)) \
+ goto stop;
+
+ mds_kbdc_parsed_t subresult;
+ mds_kbdc_parsed_t* our_result;
+ char* dirname = NULL;
+ char* cwd = NULL;
+ char* old = NULL;
+ size_t cwd_size = 4096 >> 1;
+ int saved_errno;
+
+ /* Initialise result structure for the included file. */
+ mds_kbdc_parsed_initialise(&subresult);
+
+ /* Get dirname of current file. */
+ fail_if ((dirname = strdup(result->pathname)) == NULL);
+ *(strrchr(dirname, '/')) = '\0';
+
+ /* Get the current working directory. */
+ /* glibc offers ways to do this in just one function call,
+ * but we will not assume that glibc is used here. */
+ for (;;)
+ {
+ fail_if (!xxrealloc(old, cwd, cwd_size <<= 1, char));
+ if (getcwd(cwd, cwd_size))
+ break;
+ else
+ fail_if (errno != ERANGE);
+ }
+
+ /* Switch working directory. */
+ fail_if (chdir(dirname));
+ free(dirname), dirname = NULL;
+
+ /* Store `result` as it will be switched by the inner `process_includes`. */
+ our_result = result;
+
+ /* Process include. */
+ process (parse_to_tree(tree->filename, &subresult));
+ process (simplify_tree(&subresult));
+ process (process_includes(&subresult));
+ stop:
+
+ /* Switch back `result`. */
+ result = our_result;
+
+ /* Switch back to the old working directory. */
+ fail_if (chdir(cwd));
+ free(cwd), cwd = NULL;
+
+ /* Move over data to our result. */
+ free(tree->filename);
+ tree->filename = subresult.pathname, subresult.pathname = NULL;
+ tree->inner = subresult.tree, subresult.tree = NULL;
+ if (result->severest_error_level < subresult.severest_error_level)
+ result->severest_error_level = subresult.severest_error_level;
+
+ /* Move over errors. */
+ /* TODO */
+
+ /* Release resources. */
+ mds_kbdc_parsed_destroy(&subresult);
+
return 0;
+ pfail:
+ saved_errno = errno;
+ free(dirname);
+ free(cwd);
+ free(old);
+ mds_kbdc_parsed_destroy(&subresult);
+ return errno = saved_errno, -1;
+#undef process
+}
+
+
+/**
+ * Process a subtree
+ *
+ * @param tree The tree
+ * @return Zero on success, -1 on error
+ */
+static int process_includes_in_tree(mds_kbdc_tree_t* restrict tree)
+{
+#define p(expr) if ((r = process_includes_in_tree(tree->expr))) return r
+ int r;
+ again:
+ if (tree == NULL)
+ return 0;
+
+ switch (tree->type)
+ {
+ case C(INFORMATION): p (information.inner); break;
+ case C(FUNCTION): p (function.inner); break;
+ case C(MACRO): p (macro.inner); break;
+ case C(ASSUMPTION): p (assumption.inner); break;
+ case C(FOR): p (for_.inner); break;
+ case C(IF): p (if_.inner); p (if_.otherwise); break;
+ case C(INCLUDE):
+ if ((r = process_include(&(tree->include))))
+ return r;
+ break;
+ default:
+ break;
+ }
+
+ tree = tree->next;
+ goto again;
+#undef p
+}
+
+
+/**
+ * Include included files and process them upto this level
+ *
+ * @param result_ `result` from `simplify_tree`, will be updated
+ * @return -1 if an error occursed that cannot be stored in `result`, zero otherwise
+ */
+int process_includes(mds_kbdc_parsed_t* restrict result_)
+{
+ result = result_;
+ return process_includes_in_tree(result_->tree);
}
#undef NEW_ERROR
+#undef C