diff options
-rw-r--r-- | src/mds-kbdc/make-tree.c | 98 | ||||
-rw-r--r-- | src/mds-kbdc/make-tree.h | 11 | ||||
-rw-r--r-- | src/mds-kbdc/mds-kbdc.c | 30 | ||||
-rw-r--r-- | src/mds-kbdc/parsed.c | 22 | ||||
-rw-r--r-- | src/mds-kbdc/parsed.h | 24 | ||||
-rw-r--r-- | src/mds-kbdc/simplify-tree.c | 112 | ||||
-rw-r--r-- | src/mds-kbdc/simplify-tree.h | 12 |
7 files changed, 93 insertions, 216 deletions
diff --git a/src/mds-kbdc/make-tree.c b/src/mds-kbdc/make-tree.c index 2e3668c..1d91a57 100644 --- a/src/mds-kbdc/make-tree.c +++ b/src/mds-kbdc/make-tree.c @@ -17,10 +17,6 @@ */ #include "make-tree.h" -#include "raw-data.h" - -#include <libmdsserver/macros.h> - #include <limits.h> #include <stdlib.h> #include <libgen.h> @@ -80,7 +76,7 @@ * Pointer to the beginning of the current line */ #define LINE \ - (source_code.lines[line_i]) + (result->source_code->lines[line_i]) /** @@ -94,33 +90,14 @@ /** * Add an error the to error list * - * @param ERROR_IS_IN_FILE:int Whether the error is in the layout code - * @param SEVERITY:identifier * in `MDS_KBDC_PARSE_ERROR_*` to indicate severity - * @param ...:const char*, ... Error description format string and arguments + * @param ERROR_IS_IN_FILE:int Whether the error is in the layout code + * @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(ERROR_IS_IN_FILE, SEVERITY, ...) \ - do \ - { \ - if (errors_ptr + 1 >= errors_size) \ - { \ - errors_size = errors_size ? (errors_size << 1) : 2; \ - fail_if (xxrealloc(old_errors, *errors, errors_size, mds_kbdc_parse_error_t*)); \ - } \ - fail_if (xcalloc(error, 1, mds_kbdc_parse_error_t)); \ - (*errors)[errors_ptr + 0] = error; \ - (*errors)[errors_ptr + 1] = NULL; \ - errors_ptr++; \ - error->line = line_i; \ - error->severity = MDS_KBDC_PARSE_ERROR_##SEVERITY; \ - error->error_is_in_file = ERROR_IS_IN_FILE; \ - error->start = (size_t)(line - LINE); \ - error->end = (size_t)(end - LINE); \ - fail_if ((error->pathname = strdup(pathname)) == NULL); \ - if (ERROR_IS_IN_FILE) \ - fail_if ((error->code = strdup(source_code.real_lines[line_i])) == NULL); \ - fail_if (xasprintf(error->description, __VA_ARGS__)); \ - } \ - while (0) +#define NEW_ERROR(ERROR_IS_IN_FILE, SEVERITY, ...) \ + NEW_ERROR_(result, SEVERITY, ERROR_IS_IN_FILE, line_i, \ + (size_t)(line - LINE), (size_t)(end - LINE), 1, __VA_ARGS__) /** @@ -674,57 +651,39 @@ * Parse a file into a syntax tree * * @param filename The filename of the file to parse - * @param result Output parameter for the root of the tree, `NULL` if -1 is returned - * @param errors `NULL`-terminated list of found error, `NULL` if no errors were found or if -1 is returned - * @return -1 if an error occursed that cannot be stored in `*errors`, zero otherwise + * @param result Output parameter for the parsing result + * @return -1 if an error occursed that cannot be stored in `result`, zero otherwise */ -int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict result, - mds_kbdc_parse_error_t*** restrict errors) +int parse_to_tree(const char* restrict filename, mds_kbdc_parsed_t* restrict result) { mds_kbdc_parse_error_t* error; - mds_kbdc_parse_error_t** old_errors = NULL; - char* pathname; - mds_kbdc_source_code_t source_code; - size_t errors_size = 0; - size_t errors_ptr = 0; size_t line_i, line_n; const char** keyword_stack = NULL; mds_kbdc_tree_t*** tree_stack = NULL; size_t stack_ptr = 0; int saved_errno, in_array = 0; - *result = NULL; - *errors = NULL; - mds_kbdc_source_code_initialise(&source_code); + fail_if (xmalloc(result->source_code, 1, mds_kbdc_source_code_t)); + mds_kbdc_source_code_initialise(result->source_code); /* Get a non-relative pathname for the file, relative filenames * can be misleading as the program can have changed working * directory to be able to resolve filenames. */ - pathname = realpath(filename, NULL); - fail_if (pathname == NULL); + result->pathname = realpath(filename, NULL); + fail_if (result->pathname == NULL); /* Check that the file exists and can be read. */ - if (access(pathname, R_OK) < 0) + if (access(result->pathname, R_OK) < 0) { saved_errno = errno; - fail_if (xmalloc(*errors, 2, mds_kbdc_parse_error_t*)); - fail_if (xmalloc(**errors, 1, mds_kbdc_parse_error_t)); - (*errors)[1] = NULL; - - (**errors)->severity = MDS_KBDC_PARSE_ERROR_ERROR; - (**errors)->error_is_in_file = 0; - (**errors)->pathname = pathname, pathname = NULL; - (**errors)->line = 0; - (**errors)->start = 0; - (**errors)->end = 0; - (**errors)->code = NULL; - (**errors)->description = strdup(strerror(saved_errno)); - fail_if ((**errors)->description == NULL); + NEW_ERROR_(result, ERROR, 0, 0, 0, 0, 0, NULL); + error->description = strdup(strerror(saved_errno)); + fail_if (error->description == NULL); return 0; } /* Read the file and simplify it a bit. */ - fail_if (read_source_lines(pathname, &source_code) < 0); + fail_if (read_source_lines(result->pathname, result->source_code) < 0); /* TODO '\t':s should be expanded into ' ':s. */ /* Allocate stacks needed to parse the tree. */ @@ -732,20 +691,20 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu /* The maxium line-length is needed because lines can have there own stacking, * like sequence mapping lines, additionally, let statements can have one array. */ size_t max_line_length = 0, cur_line_length; - for (line_i = 0, line_n = source_code.line_count; line_i < line_n; line_i++) + for (line_i = 0, line_n = result->source_code->line_count; line_i < line_n; line_i++) { cur_line_length = strlen(LINE); if (max_line_length < cur_line_length) max_line_length = cur_line_length; } - fail_if (xmalloc(keyword_stack, source_code.line_count + max_line_length, const char*)); - fail_if (xmalloc(tree_stack, source_code.line_count + max_line_length + 1, mds_kbdc_tree_t**)); + fail_if (xmalloc(keyword_stack, result->source_code->line_count + max_line_length, const char*)); + fail_if (xmalloc(tree_stack, result->source_code->line_count + max_line_length + 1, mds_kbdc_tree_t**)); } /* Create a node-slot for the tree root. */ - *tree_stack = result; + *tree_stack = &(result->tree); - for (line_i = 0, line_n = source_code.line_count; line_i < line_n; line_i++) + for (line_i = 0, line_n = result->source_code->line_count; line_i < line_n; line_i++) { char* line = LINE; char* end; @@ -1059,21 +1018,14 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu } } - free(pathname); free(keyword_stack); free(tree_stack); - mds_kbdc_source_code_destroy(&source_code); return 0; pfail: saved_errno = errno; - free(pathname); free(keyword_stack); free(tree_stack); - mds_kbdc_source_code_destroy(&source_code); - mds_kbdc_parse_error_free_all(old_errors); - mds_kbdc_parse_error_free_all(*errors), *errors = NULL; - mds_kbdc_tree_free(*result), *result = NULL; return errno = saved_errno, -1; } diff --git a/src/mds-kbdc/make-tree.h b/src/mds-kbdc/make-tree.h index 6c02a8f..e854dad 100644 --- a/src/mds-kbdc/make-tree.h +++ b/src/mds-kbdc/make-tree.h @@ -19,20 +19,17 @@ #define MDS_MDS_KBDC_MAKE_TREE_H -#include "tree.h" -#include "parse-error.h" +#include "parsed.h" /** * Parse a file into a syntax tree * * @param filename The filename of the file to parse - * @param result Output parameter for the root of the tree, `NULL` if -1 is returned - * @param errors `NULL`-terminated list of found error, `NULL` if no errors were found or if -1 is returned - * @return -1 if an error occursed that cannot be stored in `*errors`, zero otherwise + * @param result Output parameter for the parsing result + * @return -1 if an error occursed that cannot be stored in `result`, zero otherwise */ -int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict result, - mds_kbdc_parse_error_t*** restrict errors); +int parse_to_tree(const char* restrict filename, mds_kbdc_parsed_t* restrict result); #endif diff --git a/src/mds-kbdc/mds-kbdc.c b/src/mds-kbdc/mds-kbdc.c index dc3327f..f7bfb06 100644 --- a/src/mds-kbdc/mds-kbdc.c +++ b/src/mds-kbdc/mds-kbdc.c @@ -38,33 +38,23 @@ */ int main(int argc_, char** argv_) { - mds_kbdc_parse_error_t** parse_errors; - mds_kbdc_tree_t* tree; + mds_kbdc_parsed_t result; + int fatal; argc = argc_; argv = argv_; - fail_if (parse_to_tree(argv[1], &tree, &parse_errors) < 0); - mds_kbdc_tree_print(tree, stderr); - if (parse_errors != NULL) - { - mds_kbdc_parse_error_t** errors = parse_errors; - int fatal = 0; - while (*errors) - { - if ((*errors)->severity >= MDS_KBDC_PARSE_ERROR_ERROR) - fatal = 1; - mds_kbdc_parse_error_print(*errors++, stderr); - } - mds_kbdc_parse_error_free_all(parse_errors); - if (fatal) - return mds_kbdc_tree_free(tree), 1; - } - mds_kbdc_tree_free(tree); - return 0; + mds_kbdc_parsed_initialise(&result); + fail_if (parse_to_tree(argv[1], &result) < 0); + fatal = mds_kbdc_parsed_is_fatal(&result); + mds_kbdc_tree_print(result.tree, stderr); + mds_kbdc_parsed_print_errors(&result, stderr); + mds_kbdc_parsed_destroy(&result); + return fatal; pfail: xperror(*argv); + mds_kbdc_parsed_destroy(&result); return 1; } diff --git a/src/mds-kbdc/parsed.c b/src/mds-kbdc/parsed.c index e7d821b..6b4160f 100644 --- a/src/mds-kbdc/parsed.c +++ b/src/mds-kbdc/parsed.c @@ -49,6 +49,18 @@ void mds_kbdc_parsed_destroy(mds_kbdc_parsed_t* restrict this) /** + * Check whether a fatal errors has occurred + * + * @param this The parsing result + * @return Whether a fatal errors has occurred + */ +int mds_kbdc_parsed_is_fatal(mds_kbdc_parsed_t* restrict this) +{ + return this->severest_error_level >= MDS_KBDC_PARSE_ERROR_ERROR; +} + + +/** * Print all encountered errors * * @param this The parsing result @@ -57,8 +69,9 @@ void mds_kbdc_parsed_destroy(mds_kbdc_parsed_t* restrict this) void mds_kbdc_parsed_print_errors(mds_kbdc_parsed_t* restrict this, FILE* output) { mds_kbdc_parse_error_t** errors = this->errors; - while (*errors) - mds_kbdc_parse_error_print(*errors++, output); + if (errors) + while (*errors) + mds_kbdc_parse_error_print(*errors++, output); } @@ -77,7 +90,8 @@ mds_kbdc_parse_error_t* mds_kbdc_parsed_new_error(mds_kbdc_parsed_t* restrict th int error_is_in_file, size_t line, size_t start, size_t end) { mds_kbdc_parse_error_t* error = NULL; - int saved_errno, old_errors_ptr = this->errors_ptr; + size_t old_errors_ptr = this->errors_ptr; + int saved_errno; if (this->errors_ptr + 1 >= this->errors_size) { @@ -105,7 +119,7 @@ mds_kbdc_parse_error_t* mds_kbdc_parsed_new_error(mds_kbdc_parsed_t* restrict th error->line = line; error->start = start; error->end = end; - error->code = strdup(this->source_code.real_lines[line]); + error->code = strdup(this->source_code->real_lines[line]); fail_if (error->code == NULL); } diff --git a/src/mds-kbdc/parsed.h b/src/mds-kbdc/parsed.h index f2a847e..567168c 100644 --- a/src/mds-kbdc/parsed.h +++ b/src/mds-kbdc/parsed.h @@ -37,16 +37,18 @@ * @param LINE:size_t The line where the error occurred, zero-based * @param START:size_t The byte where the error started, on the line, inclusive, zero-based * @param END:size_t The byte where the error ended, on the line, exclusive, zero-based + * @param WITH_DESCRIPTION:int Whether a description should be stored * @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_(RESULT, SEVERITY, ERROR_IS_IN_FILE, LINE, START, END, ...) \ - do \ - { \ - error = mds_kbdc_parsed_new_error(RESULT, SEVERITY, ERROR_IS_IN_FILE, LINE, START, END); \ - fail_if (error == NULL); \ - fail_if (xasprintf(error->description, __VA_ARGS__)); \ - } \ +#define NEW_ERROR_(RESULT, SEVERITY, ERROR_IS_IN_FILE, LINE, START, END, WITH_DESCRIPTION, ...) \ + do \ + { \ + error = mds_kbdc_parsed_new_error(RESULT, MDS_KBDC_PARSE_ERROR_##SEVERITY, \ + ERROR_IS_IN_FILE, LINE, START, END); \ + fail_if (error == NULL); \ + fail_if (WITH_DESCRIPTION && xasprintf(error->description, __VA_ARGS__)); \ + } \ while (0) @@ -117,6 +119,14 @@ void mds_kbdc_parsed_initialise(mds_kbdc_parsed_t* restrict this); void mds_kbdc_parsed_destroy(mds_kbdc_parsed_t* restrict this); /** + * Check whether a fatal errors has occurred + * + * @param this The parsing result + * @return Whether a fatal errors has occurred + */ +int mds_kbdc_parsed_is_fatal(mds_kbdc_parsed_t* restrict this) __attribute__((pure)); + +/** * Print all encountered errors * * @param this The parsing result diff --git a/src/mds-kbdc/simplify-tree.c b/src/mds-kbdc/simplify-tree.c index 8b8bf1d..87dd891 100644 --- a/src/mds-kbdc/simplify-tree.c +++ b/src/mds-kbdc/simplify-tree.c @@ -17,91 +17,34 @@ */ #include "simplify-tree.h" -#include <libmdsserver/macros.h> - #include <stdlib.h> #include <string.h> -/** - * Wrapper around `asprintf` that makes sure that first - * argument gets set to `NULL` on error and that zero is - * returned on success rather than the number of printed - * characters - * - * @param VAR:char** The output parameter for the string - * @param ...:const char*, ... The format string and arguments - * @return :int Zero on success, -1 on error - */ -#define xasprintf(VAR, ...) \ - (asprintf(&(VAR), __VA_ARGS__) < 0 ? (VAR = NULL, -1) : 0) - /** * Add an error the to error list * - * @param NODE:const mds_kbdc_tree_t* The node the triggered the error - * @param SEVERITY:identifier * in `MDS_KBDC_PARSE_ERROR_*` to indicate severity - * @param ...:const char*, ... Error description format string and arguments + * @param NODE:const mds_kbdc_tree_t* The node the triggered the error + * @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, SEVERITY, ...) \ - do \ - { \ - if (errors_ptr + 1 >= errors_size) \ - { \ - errors_size = errors_size ? (errors_size << 1) : 2; \ - fail_if (xxrealloc(old_errors, *errors, errors_size, mds_kbdc_parse_error_t*)); \ - old_errors = NULL; \ - } \ - fail_if (xcalloc(error, 1, mds_kbdc_parse_error_t)); \ - (*errors)[errors_ptr + 0] = error; \ - (*errors)[errors_ptr + 1] = NULL; \ - errors_ptr++; \ - error->line = (NODE)->loc_line; \ - error->severity = MDS_KBDC_PARSE_ERROR_##SEVERITY; \ - error->error_is_in_file = 1; \ - error->start = (NODE)->loc_start; \ - error->end = (NODE)->loc_end; \ - fail_if ((error->pathname = strdup(pathname)) == NULL); \ - fail_if ((error->code = strdup(source_code.real_lines[error->line])) == NULL); \ - fail_if (xasprintf(error->description, __VA_ARGS__)); \ - } \ - while (0) +#define NEW_ERROR(NODE, SEVERITY, ...) \ + NEW_ERROR_(result, SEVERITY, 1, (NODE)->loc_line, \ + (NODE)->loc_start, (NODE)->loc_end, 1, __VA_ARGS__) /** - * Temporary storage variable for the new error, - * it is made available so that it is easy to - * make adjustments to the error after calling - * `NEW_ERROR` + * Variable whether the latest created error is stored */ static mds_kbdc_parse_error_t* error; /** - * The number of elements allocated for `*errors` - */ -static size_t errors_size; - -/** - * The number of elements stored in `*errors` + * The parameter of `simplify_tree` */ -static size_t errors_ptr; - -/** - * Pointer to the list of errors - */ -static mds_kbdc_parse_error_t*** errors; - -/** - * The old `*errors` used temporary when reallocating `*errors` - */ -static mds_kbdc_parse_error_t** old_errors; - -/** - * The pathname of the file that have been parsed - */ -static char* pathname; +static mds_kbdc_parsed_t* restrict result; @@ -202,41 +145,16 @@ static int simplify(mds_kbdc_tree_t* restrict tree) /** * Simplify a tree and generate related warnings in the process * - * @param filename The filename of the tree that have been parsed - * @param tree The tree, it may be modified - * @param errors_ `NULL`-terminated list of found error, `NULL` if no errors were found or if -1 is returned - * @return -1 if an error occursed that cannot be stored in `*errors`, zero otherwise + * @param result_ `result` from `parse_to_tree`, same sematics, will be updated + * @return -1 if an error occursed that cannot be stored in `result`, zero otherwise */ -int simplify_tree(const char* restrict filename, mds_kbdc_tree_t* restrict tree, - mds_kbdc_parse_error_t*** restrict errors_) +int simplify_tree(mds_kbdc_parsed_t* restrict result_) { - int r, saved_errno; - - error = NULL; - errors_size = errors_ptr = 0; - errors = errors_; - *errors = NULL; - old_errors = NULL; - - /* Get a non-relative pathname for the file, relative filenames - * can be misleading as the program can have changed working - * directroy to be able to resolve filenames. */ - fail_if ((pathname = realpath(filename, NULL), pathname == NULL)); - - if (r = simplify(tree), !r) - return 0; - - pfail: - saved_errno = errno; - free(pathname); - mds_kbdc_parse_error_free_all(old_errors); - mds_kbdc_parse_error_free_all(*errors), *errors = NULL; - errno = saved_errno; - return r; + result = result_; + return simplify(result_->tree); } #undef NEW_ERROR -#undef xasprintf diff --git a/src/mds-kbdc/simplify-tree.h b/src/mds-kbdc/simplify-tree.h index 94e4f94..9db62ef 100644 --- a/src/mds-kbdc/simplify-tree.h +++ b/src/mds-kbdc/simplify-tree.h @@ -19,20 +19,16 @@ #define MDS_MDS_KBDC_SIMPLIFY_TREE_H -#include "tree.h" -#include "parse-error.h" +#include "parsed.h" /** * Simplify a tree and generate related warnings in the process * - * @param filename The filename of the tree that have been parsed - * @param tree The tree, it may be modified - * @param errors `NULL`-terminated list of found error, `NULL` if no errors were found or if -1 is returned - * @return -1 if an error occursed that cannot be stored in `*errors`, zero otherwise + * @param result `result` from `parse_to_tree`, same sematics, will be updated + * @return -1 if an error occursed that cannot be stored in `result`, zero otherwise */ -int simplify_tree(const char* restrict filename, mds_kbdc_tree_t* restrict tree, - mds_kbdc_parse_error_t*** restrict errors); +int simplify_tree(mds_kbdc_parsed_t* restrict result); #endif |