From: Michael Tremer Date: Mon, 1 Mar 2021 15:12:06 +0000 (+0000) Subject: parser: Create an error object when parsing failed X-Git-Tag: 0.9.28~1285^2~678 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b7699d9c8172a4d236bf257f1b0a0f03d6ca6bc;p=pakfire.git parser: Create an error object when parsing failed This can be used to report more details about the parsing error to the user Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/parser.c b/src/_pakfire/parser.c index ddeb1e862..25c199719 100644 --- a/src/_pakfire/parser.c +++ b/src/_pakfire/parser.c @@ -94,7 +94,7 @@ static PyObject* Parser_parse(ParserObject* self, PyObject* args) { if (!PyArg_ParseTuple(args, "s", &data)) return NULL; - int r = pakfire_parser_parse(self->parser, data, strlen(data)); + int r = pakfire_parser_parse(self->parser, data, strlen(data), NULL); if (r) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -115,7 +115,7 @@ static PyObject* Parser_read(ParserObject* self, PyObject* args) { return NULL; } - int r = pakfire_parser_read(self->parser, f); + int r = pakfire_parser_read(self->parser, f, NULL); fclose(f); if (r) { diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index cdb8ee96f..515f774d4 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -410,7 +410,7 @@ static int pakfire_archive_parse_entry_metadata(PakfireArchive archive, return r; // Parse metadata file - r = pakfire_parser_parse_data(archive->parser, (const char*)data, data_size); + r = pakfire_parser_parse_data(archive->parser, (const char*)data, data_size, NULL); free(data); return r; diff --git a/src/libpakfire/include/pakfire/parser.h b/src/libpakfire/include/pakfire/parser.h index 7d751f189..7e2ae52a4 100644 --- a/src/libpakfire/include/pakfire/parser.h +++ b/src/libpakfire/include/pakfire/parser.h @@ -25,6 +25,8 @@ #include +struct pakfire_parser_error; + PakfireParser pakfire_parser_create(Pakfire pakfire, PakfireParser parser, const char* namespace); PakfireParser pakfire_parser_create_child(PakfireParser parser, @@ -43,14 +45,26 @@ char* pakfire_parser_get(PakfireParser parser, const char* name); PakfireParser pakfire_parser_merge(PakfireParser parser1, PakfireParser parser2); -int pakfire_parser_read(PakfireParser parser, FILE* f); -int pakfire_parser_read_file(PakfireParser parser, const char* path); -int pakfire_parser_parse(PakfireParser parser, const char* data, size_t size); +int pakfire_parser_read(PakfireParser parser, FILE* f, struct pakfire_parser_error** error); +int pakfire_parser_read_file(PakfireParser parser, const char* path, + struct pakfire_parser_error** error); +int pakfire_parser_parse(PakfireParser parser, const char* data, size_t size, + struct pakfire_parser_error** error); char* pakfire_parser_dump(PakfireParser parser); const char* pakfire_parser_get_namespace(PakfireParser parser); int pakfire_parser_set_namespace(PakfireParser parser, const char* namespace); +// Errors +int pakfire_parser_error_create(struct pakfire_parser_error** error, + PakfireParser parser, const char* filename, int line, const char* message); +struct pakfire_parser_error* pakfire_parser_error_ref(struct pakfire_parser_error* error); +struct pakfire_parser_error* pakfire_parser_error_unref(struct pakfire_parser_error* error); + +const char* pakfire_parser_error_get_filename(struct pakfire_parser_error* error); +int pakfire_parser_error_get_line(struct pakfire_parser_error* error); +const char* pakfire_parser_error_get_message(struct pakfire_parser_error* error); + #ifdef PAKFIRE_PRIVATE Pakfire pakfire_parser_get_pakfire(PakfireParser parser); @@ -63,7 +77,8 @@ struct pakfire_parser_declaration { int pakfire_parser_apply_declaration( PakfireParser parser, struct pakfire_parser_declaration* declaration); -int pakfire_parser_parse_data(PakfireParser parser, const char* data, size_t len); +int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len, + struct pakfire_parser_error** error); #endif /* PAKFIRE_PRIVATE */ diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym index 8c113517a..905c9a0fb 100644 --- a/src/libpakfire/libpakfire.sym +++ b/src/libpakfire/libpakfire.sym @@ -263,6 +263,14 @@ global: pakfire_parser_set_namespace; pakfire_parser_unref; + # parser error + pakfire_parser_error_create; + pakfire_parser_error_get_filename; + pakfire_parser_error_get_line; + pakfire_parser_error_get_message; + pakfire_parser_error_ref; + pakfire_parser_error_unref; + # problem pakfire_problem_append; pakfire_problem_create; diff --git a/src/libpakfire/parser.c b/src/libpakfire/parser.c index 70b667ab9..699f4bdf7 100644 --- a/src/libpakfire/parser.c +++ b/src/libpakfire/parser.c @@ -452,7 +452,8 @@ PAKFIRE_EXPORT PakfireParser pakfire_parser_merge(PakfireParser parser1, Pakfire return parser1; } -PAKFIRE_EXPORT int pakfire_parser_read(PakfireParser parser, FILE* f) { +PAKFIRE_EXPORT int pakfire_parser_read(PakfireParser parser, FILE* f, + struct pakfire_parser_error** error) { char* data; size_t len; @@ -460,7 +461,7 @@ PAKFIRE_EXPORT int pakfire_parser_read(PakfireParser parser, FILE* f) { if (r) return r; - r = pakfire_parser_parse_data(parser, data, len); + r = pakfire_parser_parse_data(parser, data, len, error); if (data) free(data); @@ -468,19 +469,21 @@ PAKFIRE_EXPORT int pakfire_parser_read(PakfireParser parser, FILE* f) { return r; } -PAKFIRE_EXPORT int pakfire_parser_read_file(PakfireParser parser, const char* path) { +PAKFIRE_EXPORT int pakfire_parser_read_file(PakfireParser parser, const char* path, + struct pakfire_parser_error** error) { FILE* f = fopen(path, "r"); if (!f) return 1; - int r = pakfire_parser_read(parser, f); + int r = pakfire_parser_read(parser, f, error); fclose(f); return r; } -PAKFIRE_EXPORT int pakfire_parser_parse(PakfireParser parser, const char* data, size_t size) { - return pakfire_parser_parse_data(parser, data, size); +PAKFIRE_EXPORT int pakfire_parser_parse(PakfireParser parser, + const char* data, size_t size, struct pakfire_parser_error** error) { + return pakfire_parser_parse_data(parser, data, size, error); } PAKFIRE_EXPORT char* pakfire_parser_dump(PakfireParser parser) { @@ -517,3 +520,82 @@ PAKFIRE_EXPORT int pakfire_parser_set_namespace(PakfireParser parser, const char return 0; } + +// Error + +struct pakfire_parser_error { + PakfireParser parser; + int nrefs; + + char* filename; + int line; + char* message; +}; + +PAKFIRE_EXPORT int pakfire_parser_error_create(struct pakfire_parser_error** error, + PakfireParser parser, const char* filename, int line, const char* message) { + struct pakfire_parser_error* e = calloc(1, sizeof(*e)); + if (!e) + return ENOMEM; + + // Initialize reference counter + e->nrefs = 1; + + e->parser = pakfire_parser_ref(parser); + + // Copy all input values + if (filename) + e->filename = strdup(filename); + + e->line = line; + + if (message) + e->message = strdup(message); + + *error = e; + + return 0; +} + +PAKFIRE_EXPORT struct pakfire_parser_error* pakfire_parser_error_ref( + struct pakfire_parser_error* error) { + ++error->nrefs; + + return error; +} + +static void pakfire_parser_error_free(struct pakfire_parser_error* error) { + pakfire_parser_unref(error->parser); + + if (error->filename) + free(error->filename); + + if (error->message) + free(error->message); + + free(error); +} + +PAKFIRE_EXPORT struct pakfire_parser_error* pakfire_parser_error_unref( + struct pakfire_parser_error* error) { + if (--error->nrefs > 0) + return error; + + pakfire_parser_error_free(error); + + return NULL; +} + +PAKFIRE_EXPORT const char* pakfire_parser_error_get_filename( + struct pakfire_parser_error* error) { + return error->filename; +} + +PAKFIRE_EXPORT int pakfire_parser_error_get_line(struct pakfire_parser_error* error) { + return error->line; +} + +PAKFIRE_EXPORT const char* pakfire_parser_error_get_message( + struct pakfire_parser_error* error) { + return error->message; +} diff --git a/src/libpakfire/parser/grammar.y b/src/libpakfire/parser/grammar.y index dd8154737..68c52e61a 100644 --- a/src/libpakfire/parser/grammar.y +++ b/src/libpakfire/parser/grammar.y @@ -18,7 +18,7 @@ # # #############################################################################*/ -%parse-param {Pakfire pakfire} {PakfireParser* result} +%parse-param {Pakfire pakfire} {PakfireParser* result} {struct pakfire_parser_error** error} // Generate verbose error messages %define parse.error verbose @@ -52,7 +52,6 @@ extern int yylex(); extern int yyparse(); extern int num_lines; -static void yyerror(Pakfire pakfire, PakfireParser* result, const char* s); #define ABORT do { YYABORT; } while (0); @@ -60,6 +59,19 @@ enum operator { OP_EQUALS = 0, }; +static void yyerror(Pakfire pakfire, PakfireParser* result, + struct pakfire_parser_error** error, const char* s) { + ERROR(pakfire, "Error (line %d): %s\n", num_lines, s); + + // Create a new error object + if (error) { + int r = pakfire_parser_error_create(error, *result, NULL, num_lines, s); + if (r) { + ERROR(pakfire, "Could not create error object: %s\n", strerror(errno)); + } + } +} + static PakfireParser make_if_stmt(Pakfire pakfire, PakfireParser* parser, const enum operator op, const char* val1, const char* val2, PakfireParser if_block, PakfireParser else_block); @@ -300,7 +312,8 @@ else_stmt : T_ELSE T_EOL subgrammar %% -int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len) { +int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len, + struct pakfire_parser_error** error) { Pakfire pakfire = pakfire_parser_get_pakfire(parent); #ifdef ENABLE_DEBUG @@ -317,7 +330,7 @@ int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len num_lines = 1; YY_BUFFER_STATE buffer = yy_scan_bytes(data, len); - int r = yyparse(pakfire, &parser); + int r = yyparse(pakfire, &parser, error); yy_delete_buffer(buffer); // If everything was parsed successfully, we merge the sub-parser into @@ -351,10 +364,6 @@ int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len return r; } -void yyerror(Pakfire pakfire, PakfireParser* result, const char* s) { - ERROR(pakfire, "Error (line %d): %s\n", num_lines, s); -} - static PakfireParser make_if_stmt(Pakfire pakfire, PakfireParser* parser, const enum operator op, const char* val1, const char* val2, PakfireParser if_block, PakfireParser else_block) { switch (op) { diff --git a/tests/libpakfire/makefile.c b/tests/libpakfire/makefile.c index 64a0a337c..22eb8eb9c 100644 --- a/tests/libpakfire/makefile.c +++ b/tests/libpakfire/makefile.c @@ -45,7 +45,7 @@ static int test_parse(const struct test* t) { PakfireParser parser = pakfire_parser_create(t->pakfire, NULL, NULL); - int r = pakfire_parser_read(parser, f); + int r = pakfire_parser_read(parser, f, NULL); ASSERT(r == 0); pakfire_parser_unref(parser); @@ -71,7 +71,7 @@ static int test_macros(const struct test* t) { ASSERT(parser); for (unsigned int i = 0; i < buffer.gl_pathc; i++) { - r = pakfire_parser_read_file(parser, buffer.gl_pathv[i]); + r = pakfire_parser_read_file(parser, buffer.gl_pathv[i], NULL); ASSERT(r == 0); } diff --git a/tests/libpakfire/parser.c b/tests/libpakfire/parser.c index 4f4f2decc..efe7e0eca 100644 --- a/tests/libpakfire/parser.c +++ b/tests/libpakfire/parser.c @@ -127,7 +127,7 @@ static int test_parser_files(const struct test* t) { FILE* f = fopen(path, "r"); ASSERT(f); - int r = pakfire_parser_read(parser, f); + int r = pakfire_parser_read(parser, f, NULL); if (r) { fprintf(stderr, "Could not parse %s\n", path); return EXIT_FAILURE;