diff options
Diffstat (limited to 'Utilities/cmllpkgc/llpkgc.c')
-rw-r--r-- | Utilities/cmllpkgc/llpkgc.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/Utilities/cmllpkgc/llpkgc.c b/Utilities/cmllpkgc/llpkgc.c new file mode 100644 index 0000000..33c9043 --- /dev/null +++ b/Utilities/cmllpkgc/llpkgc.c @@ -0,0 +1,205 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include <stdlib.h> +#include <string.h> + +#include "llpkgc.h" + +#define CALLBACK_MAYBE(PARSER, NAME) \ + do { \ + const llpkgc_settings_t* settings; \ + settings = (const llpkgc_settings_t*) (PARSER)->settings; \ + if(settings == NULL || settings->NAME == NULL) { \ + err = 0; \ + break; \ + } \ + err = settings->NAME((PARSER)); \ + } while(0) + +#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \ + do { \ + const llpkgc_settings_t* settings; \ + settings = (const llpkgc_settings_t*) (PARSER)->settings; \ + if(settings == NULL || settings->NAME == NULL) { \ + err = 0; \ + break; \ + } \ + err = settings->NAME((PARSER), (START), (LEN)); \ + if(err == -1) { \ + err = PCE_USER; \ + llpkgc_set_error_reason((PARSER), "Span callback error in " #NAME); \ + } \ + } while(0) + +void llpkgc_init(llpkgc_t* parser, const llpkgc_settings_t* settings) { + llpkgc__internal_init(parser); + + parser->settings = (void*) settings; +} + +void llpkgc_reset(llpkgc_t* parser) { + llpkgc_settings_t* settings = parser->settings; + void* data = parser->data; + + llpkgc__internal_init(parser); + + parser->settings = settings; + parser->data = data; +} + +void llpkgc_settings_init(llpkgc_settings_t* settings) { + memset(settings, 0, sizeof(*settings)); +} + +llpkgc_errno_t llpkgc_execute(llpkgc_t* parser, const char* data, size_t len) { + return llpkgc__internal_execute(parser, data, data + len); +} + +llpkgc_errno_t llpkgc_finish(llpkgc_t* parser) { + if(parser->error != 0) + return parser->error; + + int err; + // ToDo: Better handling of user callback errors here + if(parser->unfinished_ == 1) { + parser->reason = "Invalid EOF state"; + parser->error = PCE_UNFINISHED; + return PCE_UNFINISHED; + } else if(parser->unfinished_ == 2) { + CALLBACK_MAYBE(parser, on_value_literal_complete); + if(err != PCE_OK) { + parser->error = err; + return err; + } + CALLBACK_MAYBE(parser, on_value_complete); + if(err != PCE_OK) { + parser->error = err; + return err; + } + } else if(parser->unfinished_ == 3) { + CALLBACK_MAYBE(parser, on_value_complete); + if(err != PCE_OK) { + parser->error = err; + return err; + } + } + + CALLBACK_MAYBE(parser, on_pkgc_complete); + return err; +} + +void llpkgc_pause(llpkgc_t* parser) { + if(parser->error != PCE_OK) { + return; + } + + parser->error = PCE_PAUSED; + parser->reason = "Paused"; +} + +void llpkgc_resume(llpkgc_t* parser) { + if(parser->error != PCE_PAUSED) { + return; + } + + parser->error = 0; +} + +llpkgc_errno_t llpkgc_get_errno(const llpkgc_t* parser) { + return parser->error; +} + +const char* llpkgc_get_error_reason(const llpkgc_t* parser) { + return parser->reason; +} + +void llpkgc_set_error_reason(llpkgc_t* parser, const char* reason) { + parser->reason = reason; +} + +const char* llpkgc_get_error_pos(const llpkgc_t* parser) { + return parser->error_pos; +} + +const char* llpkgc_errno_name(llpkgc_errno_t err) { + switch(err) { + case PCE_OK: + return "PCE_OK"; + case PCE_INTERNAL: + return "PCE_INTERNAL"; + case PCE_PAUSED: + return "PCE_PAUSED"; + case PCE_USER: + return "PCE_USER"; + case PCE_UNFINISHED: + return "PCE_UNFINISHED"; + } + return "INVALID_ERRNO"; +} + +int llpkgc__line_begin(llpkgc_t* s, const char* p, const char* endp) { + int err; + s->unfinished_ = 1; + CALLBACK_MAYBE(s, on_line_begin); + return err; +} + +int llpkgc__key_span(llpkgc_t* s, const char* p, const char* endp) { + int err; + SPAN_CALLBACK_MAYBE(s, on_key, p, endp - p); + return err; +} + +int llpkgc__keyword_complete(llpkgc_t* s, const char* p, const char* endp) { + int err; + s->unfinished_ = 3; + CALLBACK_MAYBE(s, on_keyword_complete); + return err; +} + +int llpkgc__variable_complete(llpkgc_t* s, const char* p, const char* endp) { + int err; + s->unfinished_ = 3; + CALLBACK_MAYBE(s, on_variable_complete); + return err; +} + +int llpkgc__vallit_span(llpkgc_t* s, const char* p, const char* endp) { + int err; + if(s->escaped_) { + --endp; + s->escaped_ = 0; + } + s->unfinished_ = 2; + SPAN_CALLBACK_MAYBE(s, on_value_literal, p, endp - p); + return err; +} + +int llpkgc__vallit_complete(llpkgc_t* s, const char* p, const char* endp) { + int err; + s->unfinished_ = 3; + CALLBACK_MAYBE(s, on_value_literal_complete); + return err; +} + +int llpkgc__valvar_span(llpkgc_t* s, const char* p, const char* endp) { + int err; + s->unfinished_ = 1; + SPAN_CALLBACK_MAYBE(s, on_value_variable, p, endp - p); + return err; +} + +int llpkgc__valvar_complete(llpkgc_t* s, const char* p, const char* endp) { + int err; + s->unfinished_ = 3; + CALLBACK_MAYBE(s, on_value_variable_complete); + return err; +} + +int llpkgc__value_complete(llpkgc_t* s, const char* p, const char* endp) { + int err; + s->unfinished_ = 0; + CALLBACK_MAYBE(s, on_value_complete); + return err; +} |