]> git.ipfire.org Git - pakfire.git/commitdiff
parser: Create an error object when parsing failed
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 1 Mar 2021 15:12:06 +0000 (15:12 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 1 Mar 2021 15:12:06 +0000 (15:12 +0000)
This can be used to report more details about the parsing error to the
user

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/parser.c
src/libpakfire/archive.c
src/libpakfire/include/pakfire/parser.h
src/libpakfire/libpakfire.sym
src/libpakfire/parser.c
src/libpakfire/parser/grammar.y
tests/libpakfire/makefile.c
tests/libpakfire/parser.c

index ddeb1e86226b3a6381b33ab4e1f4d6eb816bd856..25c1997198f33f1cde0a38844007c472eda313f4 100644 (file)
@@ -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) {
index cdb8ee96f2551089cb8dd8edb878db12c0b8b92a..515f774d43d3effbc0f35c0b5d55bb6415f56a75 100644 (file)
@@ -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;
index 7d751f18977c39894693a1d88b3e7317b6866f78..7e2ae52a45a7962050cd22de27ce50cedbc6adb0 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <pakfire/types.h>
 
+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 */
 
index 8c113517a38dce30ecd28f14bb3ffc5aa86c7fae..905c9a0fb5f8154f76cebc9998252908e8eb0d02 100644 (file)
@@ -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;
index 70b667ab9588b2f98e5b65ec912eaff29da8df0e..699f4bdf787178267af8ffdbcb26eb3e1bf6bd3e 100644 (file)
@@ -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;
+}
index dd8154737b264674b184910e8d3927b62e1e5812..68c52e61a9d873cf037aaeafbf4c7c02d3aa7724 100644 (file)
@@ -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) {
index 64a0a337c1271279f3d93dbb3cc7417e5694668d..22eb8eb9c5bd085e2088e5bf6c4470829230d21d 100644 (file)
@@ -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);
        }
 
index 4f4f2deccb62c0243542dfa5c8412065680a4bb4..efe7e0ecac0d3cdafa285b3f885ac2d98e3386ad 100644 (file)
@@ -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;