diff --git a/src/hammer.c b/src/hammer.c index 4d47ca069f12e3ec874f0a486c91ea8eebc7ae80..bc95f79aebec52301faa24a26f8976d6bc9c41bd 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -137,8 +137,14 @@ void h_free_backend_with_params(HParserBackendWithParams *be_with_params) { } } - h_free(be_with_params->name); - h_free(be_with_params->params_string); + if(be_with_params->name) { + h_free(be_with_params->name); + } + + if(be_with_params->params_string) { + h_free(be_with_params->params_string); + } + h_free(be_with_params); } } @@ -332,75 +338,77 @@ char * h_get_short_name_with_no_params(HAllocator *mm__, return h_get_backend_text_with_no_params(mm__, be, 0); } -char* get_params_as_string(char *remainder, char *end_paren, - char *params_as_string, HAllocator *mm__) { +size_t h_get_params_as_string(HParserBackendWithParams *be_with_params , char *remainder) { + HAllocator *mm__ = &system_allocator; + size_t params_len = 0; + char *after_open_paren = remainder + 1; + char *end_paren = NULL; + end_paren = strrchr(remainder, ')'); - size_t params_len = strlen(after_open_paren) - strlen(end_paren); + if (be_with_params->mm__) mm__ = be_with_params->mm__; - if(params_len > 0) { - params_as_string = h_new(char, params_len + 1); - memset(params_as_string, '\0', params_len + 1); - strncpy(params_as_string, after_open_paren, params_len); + if(end_paren != NULL) { + params_len = strlen(after_open_paren) - strlen(end_paren); - } - return params_as_string; + if(params_len > 0) { + be_with_params->params_string = h_new(char, params_len + 1); + memset(be_with_params->params_string, '\0', params_len + 1); + strncpy(be_with_params->params_string, after_open_paren, params_len); + } + } /* else error: to what degree do we care right now about enforcing format of the + * parameters section of the input, and how are we reporting usage errors like this? */ + + return params_len; } HParserBackendWithParams * h_get_backend_with_params_by_name(const char *name_with_params) { HAllocator *mm__ = &system_allocator; HParserBackendWithParams *result = NULL; HParserBackend be; - char *name_with_no_params = NULL; + char *remainder = NULL; - char *params_as_string = NULL; - char *end_paren = NULL; - size_t name_len, len; + size_t len, name_len, params_len; if(name_with_params != NULL) { result = h_new(HParserBackendWithParams, 1); + result->params_string = NULL; if (result) { + result->mm__ = mm__; + params_len = 0; len = strlen(name_with_params); remainder = strstr(name_with_params, "("); if(remainder != NULL) { name_len = len - strlen(remainder); - end_paren = strrchr(remainder, ')'); - if(end_paren != NULL && end_paren != remainder +1) { - params_as_string = get_params_as_string( - remainder, end_paren, params_as_string, mm__); - } /* else error */ + params_len = h_get_params_as_string(result, remainder); } else { name_len = len; } - name_with_no_params = h_new(char, name_len+1); - memset(name_with_no_params, '\0', name_len+1); - strncpy(name_with_no_params, name_with_params, name_len); + result->name = h_new(char, name_len+1); + memset(result->name, '\0', name_len+1); + strncpy(result->name, name_with_params, name_len); - be = h_query_backend_by_name(name_with_no_params); + be = h_query_backend_by_name(result->name); result->backend = be; - result->name = name_with_no_params; - result->params_string = params_as_string; - /* use the backend supplied method to extract any params from the input */ result->params = NULL; - if(params_as_string) { + if(params_len > 0) { if (be >= PB_MIN && be <= PB_MAX && be != PB_INVALID && backends[be] != backends[PB_INVALID]) { if (backends[be]->extract_params) { - backends[be]->extract_params(&(result->params), params_as_string); + backends[be]->extract_params(&(result->params), result->params_string); } } } } - } return result; @@ -451,17 +459,17 @@ bool h_not_regular(HRVMProg *prog, void *env) { return false; } -int h_compile_for_named_backend(HParser* parser, HParserBackendWithParams* be_with_params){ +int h_compile_for_backend_with_params(HParser* parser, HParserBackendWithParams* be_with_params){ HAllocator *mm__ = &system_allocator; if (be_with_params) { if (be_with_params->mm__) mm__ = be_with_params->mm__; } - return h_compile_for_named_backend__m(mm__, parser, be_with_params); + return h_compile_for_backend_with_params__m(mm__, parser, be_with_params); } -int h_compile_for_named_backend__m(HAllocator* mm__, HParser* parser, HParserBackendWithParams* be_with_params) { +int h_compile_for_backend_with_params__m(HAllocator* mm__, HParser* parser, HParserBackendWithParams* be_with_params) { return h_compile__m(mm__, parser, be_with_params->backend, be_with_params->params); } @@ -558,7 +566,7 @@ HParseResult* h_parse_finish(HSuspendedParser* s) { assert(s->done); } - // extract result + // extract be_with_params HParseResult *r = backends[s->parser->backend]->parse_finish(s); if(r) r->bit_length = s->pos * 8 + s->bit_offset; diff --git a/src/hammer.h b/src/hammer.h index 6cb92a83ca0b92fbab51fe74a9195ad6675cd608..10503f3584ee3bfad96d14b544e4ab97feabb7a2 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -55,7 +55,8 @@ typedef enum HParserBackend_ { } HParserBackend; typedef struct HParserBackendWithParams_ { - /* Name of backend (if called via string, will need to keep this for loading backends with dlopen) */ + /* Name of backend extracted from a string if the choice of backend was specified in a call using a string + * Note: we're not using this yet for anything further - we will need to use it in future for loading backends with dlopen. */ char *name; /* The backend (if backend is to be loaded from an external module set to invalid (?))*/ HParserBackend backend; @@ -66,6 +67,8 @@ typedef struct HParserBackendWithParams_ { * and PB_GLR take an integer cast to void * */ void *params; + /* parameters as string, as extracted if the choice of backend was specified in a call using a string + * Note: we're not using this yet for anything further - we will need to use it in future for using backends with dlopen/dlsym. */ char * params_string; /* Allocator to use to free this (and the params if necessary) */ HAllocator *mm__; @@ -898,7 +901,7 @@ void h_pprintln(FILE* stream, const HParsedToken* tok); * * Consult each backend for details. */ -HAMMER_FN_DECL(int, h_compile_for_named_backend, HParser* parser, HParserBackendWithParams *be_with_params); +HAMMER_FN_DECL(int, h_compile_for_backend_with_params, HParser* parser, HParserBackendWithParams *be_with_params); HAMMER_FN_DECL(int, h_compile, HParser* parser, HParserBackend backend, const void* params); diff --git a/src/t_names.c b/src/t_names.c index 5b91456eabd67b41fa5a7a547b29ea854110e67e..ee71e7f25561c6d8d68856b1207164c4b7d90cd0 100644 --- a/src/t_names.c +++ b/src/t_names.c @@ -58,64 +58,81 @@ static void test_tt_get_backend_with_params_by_name(void) { be_w_p = h_get_backend_with_params_by_name(packrat_name); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_PACKRAT); g_check_maybe_string_eq(be_w_p->name, packrat_name); + h_free_backend_with_params(be_w_p); be_w_p = h_get_backend_with_params_by_name(glr_name); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_GLR); g_check_maybe_string_eq(be_w_p->name, glr_name); + h_free_backend_with_params(be_w_p); /* request with params */ be_w_p = h_get_backend_with_params_by_name("glr(1)"); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_GLR); g_check_maybe_string_eq(be_w_p->name, glr_name); g_check_cmp_size((uintptr_t)be_w_p->params, ==, 1); + h_free_backend_with_params(be_w_p); /*request for default params - alternative possible style */ be_w_p = h_get_backend_with_params_by_name("glr()"); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_GLR); g_check_maybe_string_eq(be_w_p->name, glr_name); + h_free_backend_with_params(be_w_p); /*request for a backend not in the enum of backends included in hammer */ be_w_p = h_get_backend_with_params_by_name("llvm"); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_INVALID); g_check_maybe_string_eq(be_w_p->name, "llvm"); + h_free_backend_with_params(be_w_p); be_w_p = h_get_backend_with_params_by_name("packrat(0)"); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_PACKRAT); g_check_maybe_string_eq(be_w_p->name, packrat_name); + h_free_backend_with_params(be_w_p); be_w_p = h_get_backend_with_params_by_name("glr(1,2)"); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_GLR); g_check_maybe_string_eq(be_w_p->name, glr_name); g_check_cmp_size((uintptr_t)be_w_p->params, ==, 1); + h_free_backend_with_params(be_w_p); be_w_p = h_get_backend_with_params_by_name("glr(1 vnvnvn)"); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_GLR); g_check_maybe_string_eq(be_w_p->name, glr_name); g_check_cmp_size((uintptr_t)be_w_p->params, ==, 1); + h_free_backend_with_params(be_w_p); be_w_p = h_get_backend_with_params_by_name("glr("); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_GLR); g_check_maybe_string_eq(be_w_p->name, glr_name); + h_free_backend_with_params(be_w_p); be_w_p = h_get_backend_with_params_by_name("glr(2"); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_GLR); g_check_maybe_string_eq(be_w_p->name, glr_name); + h_free_backend_with_params(be_w_p); + + be_w_p = h_get_backend_with_params_by_name("("); + h_free_backend_with_params(be_w_p); + } /* test that we can request a backend with params from character * and compile a parser using it */ -static void test_tt_h_compile_for_named_backend(void) { +static void test_tt_h_compile_for_backend_with_params(void) { HParserBackendWithParams * be_w_p = NULL; - be_w_p = h_get_backend_with_params_by_name(llk_name); + be_w_p = h_get_backend_with_params_by_name("llk(1)"); g_check_inttype("%d", HParserBackend, be_w_p->backend, ==, PB_LLk); be_w_p->mm__ = &system_allocator; HParser *p = h_many(h_sequence(h_ch('A'), h_ch('B'), NULL)); - int r = h_compile_for_named_backend(p, be_w_p); + int r = h_compile_for_backend_with_params(p, be_w_p); + + h_free_backend_with_params(be_w_p); + if (r != 0) { g_test_message("Compile failed"); g_test_fail(); @@ -127,5 +144,5 @@ void register_names_tests(void) { g_test_add_func("/core/names/tt_backend_description", test_tt_backend_description); g_test_add_func("/core/names/tt_query_backend_by_name", test_tt_query_backend_by_name); g_test_add_func("/core/names/tt_get_backend_with_params_by_name", test_tt_get_backend_with_params_by_name); - g_test_add_func("/core/names/tt_h_compile_for_named_backend", test_tt_h_compile_for_named_backend); + g_test_add_func("/core/names/tt_h_compile_for_backend_with_params", test_tt_h_compile_for_backend_with_params); }