diff options
Diffstat (limited to 'src/mds-kbdc/process-includes.c')
-rw-r--r-- | src/mds-kbdc/process-includes.c | 397 |
1 files changed, 194 insertions, 203 deletions
diff --git a/src/mds-kbdc/process-includes.c b/src/mds-kbdc/process-includes.c index 69b9c73..a46533c 100644 --- a/src/mds-kbdc/process-includes.c +++ b/src/mds-kbdc/process-includes.c @@ -32,7 +32,7 @@ /** * Tree type constant shortener */ -#define C(TYPE) MDS_KBDC_TREE_TYPE_##TYPE +#define C(TYPE) MDS_KBDC_TREE_TYPE_##TYPE /** * Add an error to the error list @@ -42,26 +42,26 @@ * @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, SEVERITY, ...) \ - NEW_ERROR_(result, SEVERITY, 1, (NODE)->loc_line, \ - (NODE)->loc_start, (NODE)->loc_end, 1, __VA_ARGS__) +#define NEW_ERROR(NODE, SEVERITY, ...)\ + NEW_ERROR_(result, SEVERITY, 1, (NODE)->loc_line,\ + (NODE)->loc_start, (NODE)->loc_end, 1, __VA_ARGS__) /** * Variable whether the latest created error is stored */ -static mds_kbdc_parse_error_t* error; +static mds_kbdc_parse_error_t *error; /** * The parameter of `process_includes` */ -static mds_kbdc_parsed_t* restrict result; +static mds_kbdc_parsed_t *restrict result; /** * Stack of attributes of already included files */ -static struct stat* restrict included; +static struct stat *restrict included; /** * The number elements allocated for `included` @@ -81,66 +81,62 @@ static size_t included_ptr = 0; * @param subresult The results of the processed include * @param tree The include statement */ -static int transfer_errors(mds_kbdc_parsed_t* restrict subresult, mds_kbdc_tree_include_t* restrict tree) +static int +transfer_errors(mds_kbdc_parsed_t *restrict subresult, mds_kbdc_tree_include_t *restrict tree) { - mds_kbdc_parse_error_t** errors = NULL; - mds_kbdc_parse_error_t* suberror; - size_t errors_ptr = 0; - int saved_errno, annotated = 0; - - /* Allocate temporary list for errors. */ - if (subresult->errors_ptr == 0) - return 0; - fail_if (xmalloc(errors, subresult->errors_ptr * 2, mds_kbdc_parse_error_t*)); - - /* List errors backwards, so that we can easily handle errors and add “included from here”-note. */ - while (subresult->errors_ptr--) - { - suberror = subresult->errors[subresult->errors_ptr]; - - /* If it is more severe than a note, we want to say there it was included. */ - if (annotated == 0) - { - NEW_ERROR(tree, NOTE, "included from here"); - errors[errors_ptr++] = error; - result->errors[--(result->errors_ptr)] = NULL; - annotated = 1; + mds_kbdc_parse_error_t **errors = NULL, *suberror, **new_errors; + size_t errors_ptr = 0, new_errors_size; + int saved_errno, annotated = 0; + + /* Allocate temporary list for errors. */ + if (!subresult->errors_ptr) + return 0; + fail_if (xmalloc(errors, subresult->errors_ptr * 2, mds_kbdc_parse_error_t*)); + + /* List errors backwards, so that we can easily handle errors and add “included from here”-note. */ + while (subresult->errors_ptr--) { + suberror = subresult->errors[subresult->errors_ptr]; + + /* If it is more severe than a note, we want to say there it was included. */ + if (!annotated) { + NEW_ERROR(tree, NOTE, "included from here"); + errors[errors_ptr++] = error; + result->errors[--(result->errors_ptr)] = NULL; + annotated = 1; + } + + /* Include error. */ + errors[errors_ptr++] = suberror; + subresult->errors[subresult->errors_ptr] = NULL; + + /* Make sure when there are nested inclusions that the outermost inclusion * is annotated last. */ + if (suberror->severity > MDS_KBDC_PARSE_ERROR_NOTE) + annotated = 0; } - - /* Include error. */ - errors[errors_ptr++] = suberror; - subresult->errors[subresult->errors_ptr] = NULL; - - /* Make sure when there are nested inclusions that the outermost inclusion * is annotated last. */ - if (suberror->severity > MDS_KBDC_PARSE_ERROR_NOTE) - annotated = 0; - } - - /* Append errors. */ - for (; errors_ptr--; errors[errors_ptr] = NULL) - { - if (result->errors_ptr + 1 >= result->errors_size) - { - size_t new_errors_size = result->errors_size ? (result->errors_size << 1) : 2; - mds_kbdc_parse_error_t** new_errors = result->errors; - - fail_if (xrealloc(new_errors, new_errors_size, mds_kbdc_parse_error_t*)); - result->errors = new_errors; - result->errors_size = new_errors_size; + + /* Append errors. */ + for (; errors_ptr--; errors[errors_ptr] = NULL) { + if (result->errors_ptr + 1 >= result->errors_size) { + new_errors_size = result->errors_size ? (result->errors_size << 1) : 2; + new_errors = result->errors; + + fail_if (xrealloc(new_errors, new_errors_size, mds_kbdc_parse_error_t*)); + result->errors = new_errors; + result->errors_size = new_errors_size; + } + + result->errors[result->errors_ptr++] = errors[errors_ptr]; + result->errors[result->errors_ptr] = NULL; } - - result->errors[result->errors_ptr++] = errors[errors_ptr]; - result->errors[result->errors_ptr] = NULL; - } - - free(errors); - return 0; - fail: - saved_errno = errno; - while (errors_ptr--) - mds_kbdc_parse_error_free(errors[errors_ptr]); - free(errors); - return errno = saved_errno, -1; + + free(errors); + return 0; +fail: + saved_errno = errno; + while (errors_ptr--) + mds_kbdc_parse_error_free(errors[errors_ptr]); + free(errors); + return errno = saved_errno, -1; } @@ -150,86 +146,83 @@ static int transfer_errors(mds_kbdc_parsed_t* restrict subresult, mds_kbdc_tree_ * @param tree The include-statement * @return Zero on success, -1 on error */ -static int process_include(mds_kbdc_tree_include_t* restrict tree) +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 (xstrdup(dirname, result->pathname)); - *(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. */ - old = tree->filename, tree->filename = NULL; - tree->filename = parse_raw_string(old); - fail_if (tree->filename == NULL); - free(old), old = NULL; - 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->source_code = subresult.source_code, subresult.source_code = 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. */ - fail_if (transfer_errors(&subresult, tree)); - - /* Release resources. */ - mds_kbdc_parsed_destroy(&subresult); - - return 0; - fail: - saved_errno = errno; - free(dirname); - free(cwd); - free(old); - mds_kbdc_parsed_destroy(&subresult); - return errno = saved_errno, -1; +#define process(expr)\ + fail_if ((expr) < 0);\ + if (mds_kbdc_parsed_is_fatal(&subresult))\ + goto stop; + + mds_kbdc_parsed_t subresult, *our_result; + char *dirname = NULL, *cwd = NULL, *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 (xstrdup(dirname, result->pathname)); + *(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. */ + old = tree->filename, tree->filename = NULL; + tree->filename = parse_raw_string(old); + fail_if (tree->filename == NULL); + free(old), old = NULL; + 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->source_code = subresult.source_code, subresult.source_code = 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. */ + fail_if (transfer_errors(&subresult, tree)); + + /* Release resources. */ + mds_kbdc_parsed_destroy(&subresult); + + return 0; +fail: + saved_errno = errno; + free(dirname); + free(cwd); + free(old); + mds_kbdc_parsed_destroy(&subresult); + return errno = saved_errno, -1; #undef process } @@ -240,32 +233,32 @@ static int process_include(mds_kbdc_tree_include_t* restrict tree) * @param tree The tree * @return Zero on success, -1 on error */ -static int process_includes_in_tree(mds_kbdc_tree_t* restrict tree) +static int +process_includes_in_tree(mds_kbdc_tree_t *restrict tree) { -#define p(expr) fail_if (process_includes_in_tree(tree->expr)) - 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): - fail_if (process_include(&(tree->include))); - break; - default: - break; - } - - tree = tree->next; - goto again; - fail: - return -1; +#define p(expr) fail_if (process_includes_in_tree(tree->expr)) +again: + if (!tree) + 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): + fail_if (process_include(&(tree->include))); + break; + default: + break; + } + + tree = tree->next; + goto again; +fail: + return -1; #undef p } @@ -276,45 +269,43 @@ static int process_includes_in_tree(mds_kbdc_tree_t* restrict tree) * @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_) +int +process_includes(mds_kbdc_parsed_t *restrict result_) { - int r, saved_errno; - struct stat attr; - size_t i; - - result = result_; - - fail_if (stat(result->pathname, &attr)); - - if (included_ptr == included_size) - { - struct stat* old; - if (xxrealloc(old, included, included_size += 4, struct stat)) - fail_if (included = old, 1); - } - - for (i = 0; i < included_ptr; i++) - if ((included[i].st_dev == attr.st_dev) && (included[i].st_ino == attr.st_ino)) - { - NEW_ERROR_(result, ERROR, 0, 0, 0, 0, 1, "resursive inclusion"); - return 0; - } - - included[included_ptr++] = attr; - - r = process_includes_in_tree(result_->tree); - saved_errno = errno; - - if (--included_ptr == 0) - free(included), included_size = 0; - - return errno = saved_errno, r; - fail: - return -1; + int r, saved_errno; + struct stat attr, *old; + size_t i; + + result = result_; + + fail_if (stat(result->pathname, &attr)); + + if (included_ptr == included_size) { + if (xxrealloc(old, included, included_size += 4, struct stat)) + fail_if (included = old, 1); + } + + for (i = 0; i < included_ptr; i++) { + if ((included[i].st_dev == attr.st_dev) && (included[i].st_ino == attr.st_ino)) { + NEW_ERROR_(result, ERROR, 0, 0, 0, 0, 1, "resursive inclusion"); + return 0; + } + } + + included[included_ptr++] = attr; + + r = process_includes_in_tree(result_->tree); + saved_errno = errno; + + if (!--included_ptr) + free(included), included_size = 0; + + return errno = saved_errno, r; +fail: + return -1; } #undef NEW_ERROR #undef C - |