From d367918916baf9290816aa8657cc78878b68c1ef Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 22 Nov 2014 12:10:37 +0100 Subject: Starting on some rework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/mds-kbdc/make-tree.c | 25 ++------ src/mds-kbdc/mds-kbdc.c | 1 - src/mds-kbdc/parsed.c | 121 ++++++++++++++++++++++++++++++++++++ src/mds-kbdc/parsed.h | 144 +++++++++++++++++++++++++++++++++++++++++++ src/mds-kbdc/raw-data.c | 20 +++--- src/mds-kbdc/raw-data.h | 24 ++++---- src/mds-kbdc/simplify-tree.c | 109 ++++++++++++++++++++++++-------- src/mds-kbdc/simplify-tree.h | 10 +-- 8 files changed, 381 insertions(+), 73 deletions(-) create mode 100644 src/mds-kbdc/parsed.c create mode 100644 src/mds-kbdc/parsed.h (limited to 'src/mds-kbdc') diff --git a/src/mds-kbdc/make-tree.c b/src/mds-kbdc/make-tree.c index 72a50df..2e3668c 100644 --- a/src/mds-kbdc/make-tree.c +++ b/src/mds-kbdc/make-tree.c @@ -54,20 +54,6 @@ while (0) -/** - * 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) - - /** * Check whether a value is inside a closed range * @@ -698,7 +684,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu mds_kbdc_parse_error_t* error; mds_kbdc_parse_error_t** old_errors = NULL; char* pathname; - source_code_t source_code; + mds_kbdc_source_code_t source_code; size_t errors_size = 0; size_t errors_ptr = 0; size_t line_i, line_n; @@ -709,11 +695,11 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu *result = NULL; *errors = NULL; - source_code_initialise(&source_code); + mds_kbdc_source_code_initialise(&source_code); /* 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. */ + * directory to be able to resolve filenames. */ pathname = realpath(filename, NULL); fail_if (pathname == NULL); @@ -1076,7 +1062,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu free(pathname); free(keyword_stack); free(tree_stack); - source_code_destroy(&source_code); + mds_kbdc_source_code_destroy(&source_code); return 0; pfail: @@ -1084,7 +1070,7 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu free(pathname); free(keyword_stack); free(tree_stack); - source_code_destroy(&source_code); + 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; @@ -1117,7 +1103,6 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_tree_t** restrict resu #undef LINE #undef is_name_char #undef in_range -#undef xasprintf #undef PRINT_STACK #undef DEBUG_PROC diff --git a/src/mds-kbdc/mds-kbdc.c b/src/mds-kbdc/mds-kbdc.c index 34b2002..dc3327f 100644 --- a/src/mds-kbdc/mds-kbdc.c +++ b/src/mds-kbdc/mds-kbdc.c @@ -55,7 +55,6 @@ int main(int argc_, char** argv_) if ((*errors)->severity >= MDS_KBDC_PARSE_ERROR_ERROR) fatal = 1; mds_kbdc_parse_error_print(*errors++, stderr); - errors++; } mds_kbdc_parse_error_free_all(parse_errors); if (fatal) diff --git a/src/mds-kbdc/parsed.c b/src/mds-kbdc/parsed.c new file mode 100644 index 0000000..e7d821b --- /dev/null +++ b/src/mds-kbdc/parsed.c @@ -0,0 +1,121 @@ +/** + * 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 . + */ +#include "parsed.h" + +#include +#include + + + +/** + * Initialise a `mds_kbdc_parsed_t*` + * + * @param this The `mds_kbdc_parsed_t*` + */ +void mds_kbdc_parsed_initialise(mds_kbdc_parsed_t* restrict this) +{ + memset(this, 0, sizeof(mds_kbdc_parsed_t)); +} + + +/** + * Release all resources allocated in a `mds_kbdc_parsed_t*` + * + * @param this The `mds_kbdc_parsed_t*` + */ +void mds_kbdc_parsed_destroy(mds_kbdc_parsed_t* restrict this) +{ + mds_kbdc_tree_free(this->tree); + mds_kbdc_source_code_destroy(this->source_code); + free(this->pathname); + mds_kbdc_parse_error_free_all(this->errors); + memset(this, 0, sizeof(mds_kbdc_parsed_t)); +} + + +/** + * Print all encountered errors + * + * @param this The parsing result + * @param output The output file + */ +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); +} + + +/** + * Add a new error to the list + * + * @param this The parsing result + * @param severity A `MDS_KBDC_PARSE_ERROR_*` to indicate severity + * @param error_is_in_file Whether the error is in the layout code + * @param line The line where the error occurred, zero-based + * @param start The byte where the error started, on the line, inclusive, zero-based + * @param end The byte where the error ended, on the line, exclusive, zero-based + * @return The new error on success, `NULL` on error + */ +mds_kbdc_parse_error_t* mds_kbdc_parsed_new_error(mds_kbdc_parsed_t* restrict this, int severity, + 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; + + if (this->errors_ptr + 1 >= this->errors_size) + { + size_t new_errors_size = this->errors_size ? (this->errors_size << 1) : 2; + mds_kbdc_parse_error_t** new_errors = this->errors; + + fail_if (xrealloc(new_errors, new_errors_size, mds_kbdc_parse_error_t*)); + this->errors = new_errors; + this->errors_size = new_errors_size; + } + + fail_if (xcalloc(error, 1, mds_kbdc_parse_error_t)); + this->errors[this->errors_ptr + 0] = error; + this->errors[this->errors_ptr + 1] = NULL; + this->errors_ptr++; + + error->severity = severity; + if (this->severest_error_level < severity) + this->severest_error_level = severity; + + fail_if ((error->pathname = strdup(this->pathname)) == NULL); + + if ((error->error_is_in_file = error_is_in_file)) + { + error->line = line; + error->start = start; + error->end = end; + error->code = strdup(this->source_code.real_lines[line]); + fail_if (error->code == NULL); + } + + return error; + pfail: + saved_errno = errno; + free(error); + this->errors_ptr = old_errors_ptr; + this->errors[this->errors_ptr] = NULL; + errno = saved_errno; + return NULL; +} + diff --git a/src/mds-kbdc/parsed.h b/src/mds-kbdc/parsed.h new file mode 100644 index 0000000..d16af62 --- /dev/null +++ b/src/mds-kbdc/parsed.h @@ -0,0 +1,144 @@ +/** + * 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 . + */ +#ifndef MDS_MDS_KBDC_PARSED_H +#define MDS_MDS_KBDC_PARSED_H + + +#include "tree.h" +#include "raw-data.h" +#include "parse-error.h" + +#include + +#include +#include + + + + +/** + * @param RESULT:mds_kbdc_parsed_t* The parsing result + * @param SEVERITY:int * in `MDS_KBDC_PARSE_ERROR_*` to indicate severity + * @param ERROR_IS_IN_FILE:int Whether the error is in the layout code + * @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 ...: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__)); \ + } \ + while (0) + + + +/** + * Structure with parsed tree, error list + * source code and the file's pathname + */ +typedef struct mds_kbdc_parsed +{ + /** + * The parsed tree + */ + mds_kbdc_tree_t* tree; + + /** + * The source code of the parsed file + */ + mds_kbdc_source_code_t* source_code; + + /** + * A non-relative pathname to the parsed file. + * Relative filenames can be misleading as the + * program can have changed working directory + * to be able to resolve filenames. + */ + char* pathname; + + /** + * `NULL`-terminated list of found errors + * `NULL` if no errors that could be listed + * were found + */ + mds_kbdc_parse_error_t** errors; + + /** + * The number of elements allocated to `errors` + */ + size_t errors_size; + + /** + * The number of elements stored in `errors` + */ + size_t errors_ptr; + + /** + * The level of the severest countered error, + * 0 if none has been encountered. + */ + int severest_error_level; + +} mds_kbdc_parsed_t; + + + +/** + * Initialise a `mds_kbdc_parsed_t*` + * + * @param this The `mds_kbdc_parsed_t*` + */ +void mds_kbdc_parsed_initialise(mds_kbdc_parsed_t* restrict this); + +/** + * Release all resources allocated in a `mds_kbdc_parsed_t*` + * + * @param this The `mds_kbdc_parsed_t*` + */ +void mds_kbdc_parsed_destroy(mds_kbdc_parsed_t* restrict this); + +/** + * Print all encountered errors + * + * @param this The parsing result + * @param output The output file + */ +void mds_kbdc_parsed_print_errors(mds_kbdc_parsed_t* restrict this, FILE* output); + +/** + * Add a new error to the list + * + * @param this The parsing result + * @param severity A `MDS_KBDC_PARSE_ERROR_*` to indicate severity + * @param error_is_in_file Whether the error is in the layout code + * @param line The line where the error occurred, zero-based + * @param start The byte where the error started, on the line, inclusive, zero-based + * @param end The byte where the error ended, on the line, exclusive, zero-based + * @return The new error on success, `NULL` on error + */ +mds_kbdc_parse_error_t* mds_kbdc_parsed_new_error(mds_kbdc_parsed_t* restrict this, int severity, + int error_is_in_file, size_t line, size_t start, size_t end); + + +#endif + diff --git a/src/mds-kbdc/raw-data.c b/src/mds-kbdc/raw-data.c index 60c3e17..a1f8ec3 100644 --- a/src/mds-kbdc/raw-data.c +++ b/src/mds-kbdc/raw-data.c @@ -33,11 +33,11 @@ /** - * Initialise a `source_code_t*` + * Initialise a `mds_kbdc_source_code_t*` * - * @param this The `source_code_t*` + * @param this The `mds_kbdc_source_code_t*` */ -void source_code_initialise(source_code_t* restrict this) +void mds_kbdc_source_code_initialise(mds_kbdc_source_code_t* restrict this) { this->lines = NULL; this->real_lines = NULL; @@ -48,11 +48,11 @@ void source_code_initialise(source_code_t* restrict this) /** - * Release all data in a `source_code_t*` + * Release all data in a `mds_kbdc_source_code_t*` * - * @param this The `source_code_t*` + * @param this The `mds_kbdc_source_code_t*` */ -void source_code_destroy(source_code_t* restrict this) +void mds_kbdc_source_code_destroy(mds_kbdc_source_code_t* restrict this) { free(this->lines), this->lines = NULL; free(this->real_lines), this->real_lines = NULL; @@ -62,11 +62,11 @@ void source_code_destroy(source_code_t* restrict this) /** - * Release all data in a `source_code_t*`, and free it + * Release all data in a `mds_kbdc_source_code_t*`, and free it * - * @param this The `source_code_t*` + * @param this The `mds_kbdc_source_code_t*` */ -void source_code_free(source_code_t* restrict this) +void mds_kbdc_source_code_free(mds_kbdc_source_code_t* restrict this) { free(this->lines); free(this->real_lines); @@ -316,7 +316,7 @@ static char** line_split(char* content, size_t length) * @param source_code Output parameter for read data * @return Zero on success, -1 on error */ -int read_source_lines(const char* restrict pathname, source_code_t* restrict source_code) +int read_source_lines(const char* restrict pathname, mds_kbdc_source_code_t* restrict source_code) { char* content = NULL; char* real_content = NULL; diff --git a/src/mds-kbdc/raw-data.h b/src/mds-kbdc/raw-data.h index 335afc6..4bc7355 100644 --- a/src/mds-kbdc/raw-data.h +++ b/src/mds-kbdc/raw-data.h @@ -25,7 +25,7 @@ /** * Source code by lines, with and without comments */ -typedef struct source_code +typedef struct mds_kbdc_source_code { /** * Source code by lines without comments, @@ -55,29 +55,29 @@ typedef struct source_code */ size_t line_count; -} source_code_t; +} mds_kbdc_source_code_t; /** - * Initialise a `source_code_t*` + * Initialise a `mds_kbdc_source_code_t*` * - * @param this The `source_code_t*` + * @param this The `mds_kbdc_source_code_t*` */ -void source_code_initialise(source_code_t* restrict this); +void mds_kbdc_source_code_initialise(mds_kbdc_source_code_t* restrict this); /** - * Release all data in a `source_code_t*` + * Release all data in a `mds_kbdc_source_code_t*` * - * @param this The `source_code_t*` + * @param this The `mds_kbdc_source_code_t*` */ -void source_code_destroy(source_code_t* restrict this); +void mds_kbdc_source_code_destroy(mds_kbdc_source_code_t* restrict this); /** - * Release all data in a `source_code_t*`, and free it + * Release all data in a `mds_kbdc_source_code_t*`, and free it * - * @param this The `source_code_t*` + * @param this The `mds_kbdc_source_code_t*` */ -void source_code_free(source_code_t* restrict this); +void mds_kbdc_source_code_free(mds_kbdc_source_code_t* restrict this); /** @@ -101,7 +101,7 @@ size_t get_end_of_call(char* restrict content, size_t offset, size_t size) __att * @param source_code Output parameter for read data * @return Zero on success, -1 on error */ -int read_source_lines(const char* restrict pathname, source_code_t* restrict source_code); +int read_source_lines(const char* restrict pathname, mds_kbdc_source_code_t* restrict source_code); #endif diff --git a/src/mds-kbdc/simplify-tree.c b/src/mds-kbdc/simplify-tree.c index 83eb013..8b8bf1d 100644 --- a/src/mds-kbdc/simplify-tree.c +++ b/src/mds-kbdc/simplify-tree.c @@ -19,6 +19,9 @@ #include +#include +#include + /** * Wrapper around `asprintf` that makes sure that first @@ -34,21 +37,14 @@ (asprintf(&(VAR), __VA_ARGS__) < 0 ? (VAR = NULL, -1) : 0) -/** - * Pointer to the beginning of the current line - */ -#define LINE \ - (source_code.lines[line_i]) - - /** * 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 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 */ -#define NEW_ERROR(ERROR_IS_IN_FILE, SEVERITY, ...) \ +#define NEW_ERROR(NODE, SEVERITY, ...) \ do \ { \ if (errors_ptr + 1 >= errors_size) \ @@ -61,14 +57,13 @@ (*errors)[errors_ptr + 0] = error; \ (*errors)[errors_ptr + 1] = NULL; \ errors_ptr++; \ - error->line = line_i; \ + error->line = (NODE)->loc_line; \ 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); \ + error->error_is_in_file = 1; \ + error->start = (NODE)->loc_start; \ + error->end = (NODE)->loc_end; \ 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 ((error->code = strdup(source_code.real_lines[error->line])) == NULL); \ fail_if (xasprintf(error->description, __VA_ARGS__)); \ } \ while (0) @@ -81,17 +76,17 @@ * make adjustments to the error after calling * `NEW_ERROR` */ -static mds_kbdc_parse_error_t* error = NULL; +static mds_kbdc_parse_error_t* error; /** * The number of elements allocated for `*errors` */ -static size_t errors_size = 0; +static size_t errors_size; /** * The number of elements stored in `*errors` */ -static size_t errors_ptr = 0; +static size_t errors_ptr; /** * Pointer to the list of errors @@ -101,8 +96,54 @@ static mds_kbdc_parse_error_t*** errors; /** * The old `*errors` used temporary when reallocating `*errors` */ -static mds_kbdc_parse_error_t** old_errors = NULL; +static mds_kbdc_parse_error_t** old_errors; + +/** + * The pathname of the file that have been parsed + */ +static char* pathname; + + + +/** + * Simplify a subtree + * + * @param tree The tree + * @return Zero on success, -1 on error + */ +static int simplify(mds_kbdc_tree_t* restrict tree); + +/** + * Simplify a macro call-subtree + * + * @param tree The macro call-subtree + * @return Zero on success, -1 on error + */ +static int simplify_macro_call(mds_kbdc_tree_macro_call_t* restrict tree) +{ + mds_kbdc_tree_t* argument = tree->arguments; + mds_kbdc_tree_t** here; + + /* Simplify arguments. */ + for (argument = tree->arguments; argument; argument = argument->next) + simplify(argument); + + /* Remove ‘.’:s. */ + for (here = &(tree->arguments); *here; here = &((*here)->next)) + while (*here && (*here)->type == MDS_KBDC_TREE_TYPE_NOTHING) + { + mds_kbdc_tree_t* temp = (*here)->next; + (*here)->next = NULL; + NEW_ERROR(*here, WARNING, "‘.’ outside alternation has no effect"); + mds_kbdc_tree_free(*here); + *here = temp; + } + + return 0; + pfail: + return -1; +} /** @@ -132,15 +173,20 @@ static int simplify(mds_kbdc_tree_t* restrict tree) break; case MDS_KBDC_TREE_TYPE_MAP: + /* TODO */ break; case MDS_KBDC_TREE_TYPE_ALTERNATION: + /* TODO find alternations inside alternations */ break; case MDS_KBDC_TREE_TYPE_UNORDERED: + /* TODO find unordered and nothing inside unordered */ break; case MDS_KBDC_TREE_TYPE_MACRO_CALL: + if ((r = simplify_macro_call(&(tree->macro_call)))) + return r; break; default: @@ -156,21 +202,33 @@ static int simplify(mds_kbdc_tree_t* restrict tree) /** * Simplify a tree and generate related warnings in the process * - * @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 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 */ -int simplify_tree(mds_kbdc_tree_t* restrict tree, mds_kbdc_parse_error_t*** restrict errors_) +int simplify_tree(const char* restrict filename, mds_kbdc_tree_t* restrict tree, + mds_kbdc_parse_error_t*** restrict errors_) { 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; @@ -180,6 +238,5 @@ int simplify_tree(mds_kbdc_tree_t* restrict tree, mds_kbdc_parse_error_t*** rest #undef NEW_ERROR -#undef LINE #undef xasprintf diff --git a/src/mds-kbdc/simplify-tree.h b/src/mds-kbdc/simplify-tree.h index c45f1de..94e4f94 100644 --- a/src/mds-kbdc/simplify-tree.h +++ b/src/mds-kbdc/simplify-tree.h @@ -26,11 +26,13 @@ /** * Simplify a tree and generate related warnings in the process * - * @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 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 */ -int simplify_tree(mds_kbdc_tree_t* restrict tree, mds_kbdc_parse_error_t*** restrict errors); +int simplify_tree(const char* restrict filename, mds_kbdc_tree_t* restrict tree, + mds_kbdc_parse_error_t*** restrict errors); #endif -- cgit v1.2.3-70-g09d2