From 6716e23ae6d534db0d3f2af2d1610f17444fb5a9 Mon Sep 17 00:00:00 2001 From: Emanuele Torre Date: Mon, 31 Jul 2023 21:56:15 +0200 Subject: [PATCH] Declare cfunction.fptr as jv (*)() to avoid having to cast everywhere You only need to specify the return type in a function pointer declaration in C. If you use () in the declaration, the function pointer can be called with any arguments, and the type of the arguments is decided for each function call based on the types of the arguments used for the call. (To declare a function pointer for a function with no arguments, you use `(void)'.) Since all the cfunction structs have a fptr that points to a functions that return jv, not void, we can we can just declare cfunction.fptr as jv (*)() and avoid having those annoying and technically not C-standard compliant casts everywhere. --- Makefile.am | 3 +- src/builtin.c | 148 ++++++++++++++++++++++++------------------------- src/bytecode.h | 3 +- src/execute.c | 15 ++--- 4 files changed, 81 insertions(+), 88 deletions(-) diff --git a/Makefile.am b/Makefile.am index 00133f6d..79015775 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,8 +20,7 @@ LIBJQ_SRC = src/builtin.c src/bytecode.c src/compile.c src/execute.c \ ### C build options AM_CFLAGS = -Wextra -Wall -Wno-missing-field-initializers \ - -Wno-unused-parameter -Wno-unused-function \ - -Wno-cast-function-type + -Wno-unused-parameter -Wno-unused-function if WIN32 AM_CFLAGS += -municode diff --git a/src/builtin.c b/src/builtin.c index 09ffc041..26205f91 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -1704,96 +1704,96 @@ static jv f_current_line(jq_state *jq, jv a) { } #define LIBM_DD(name) \ - {(cfunction_ptr)f_ ## name, #name, 1}, + {f_ ## name, #name, 1}, #define LIBM_DD_NO(name) #define LIBM_DDD(name) \ - {(cfunction_ptr)f_ ## name, #name, 3}, + {f_ ## name, #name, 3}, #define LIBM_DDD_NO(name) #define LIBM_DDDD(name) \ - {(cfunction_ptr)f_ ## name, #name, 4}, + {f_ ## name, #name, 4}, #define LIBM_DDDD_NO(name) static const struct cfunction function_list[] = { #include "libm.h" #ifdef HAVE_FREXP - {(cfunction_ptr)f_frexp,"frexp", 1}, + {f_frexp,"frexp", 1}, #endif #ifdef HAVE_MODF - {(cfunction_ptr)f_modf,"modf", 1}, + {f_modf,"modf", 1}, #endif #ifdef HAVE_LGAMMA_R - {(cfunction_ptr)f_lgamma_r,"lgamma_r", 1}, + {f_lgamma_r,"lgamma_r", 1}, #endif - {(cfunction_ptr)f_plus, "_plus", 3}, - {(cfunction_ptr)f_negate, "_negate", 1}, - {(cfunction_ptr)f_minus, "_minus", 3}, - {(cfunction_ptr)f_multiply, "_multiply", 3}, - {(cfunction_ptr)f_divide, "_divide", 3}, - {(cfunction_ptr)f_mod, "_mod", 3}, - {(cfunction_ptr)f_dump, "tojson", 1}, - {(cfunction_ptr)f_json_parse, "fromjson", 1}, - {(cfunction_ptr)f_tonumber, "tonumber", 1}, - {(cfunction_ptr)f_tostring, "tostring", 1}, - {(cfunction_ptr)f_keys, "keys", 1}, - {(cfunction_ptr)f_keys_unsorted, "keys_unsorted", 1}, - {(cfunction_ptr)f_startswith, "startswith", 2}, - {(cfunction_ptr)f_endswith, "endswith", 2}, - {(cfunction_ptr)f_ltrimstr, "ltrimstr", 2}, - {(cfunction_ptr)f_rtrimstr, "rtrimstr", 2}, - {(cfunction_ptr)f_string_split, "split", 2}, - {(cfunction_ptr)f_string_explode, "explode", 1}, - {(cfunction_ptr)f_string_implode, "implode", 1}, - {(cfunction_ptr)f_string_indexes, "_strindices", 2}, - {(cfunction_ptr)f_setpath, "setpath", 3}, // FIXME typechecking - {(cfunction_ptr)f_getpath, "getpath", 2}, - {(cfunction_ptr)f_delpaths, "delpaths", 2}, - {(cfunction_ptr)f_has, "has", 2}, - {(cfunction_ptr)f_equal, "_equal", 3}, - {(cfunction_ptr)f_notequal, "_notequal", 3}, - {(cfunction_ptr)f_less, "_less", 3}, - {(cfunction_ptr)f_greater, "_greater", 3}, - {(cfunction_ptr)f_lesseq, "_lesseq", 3}, - {(cfunction_ptr)f_greatereq, "_greatereq", 3}, - {(cfunction_ptr)f_contains, "contains", 2}, - {(cfunction_ptr)f_length, "length", 1}, - {(cfunction_ptr)f_utf8bytelength, "utf8bytelength", 1}, - {(cfunction_ptr)f_type, "type", 1}, - {(cfunction_ptr)f_isinfinite, "isinfinite", 1}, - {(cfunction_ptr)f_isnan, "isnan", 1}, - {(cfunction_ptr)f_isnormal, "isnormal", 1}, - {(cfunction_ptr)f_infinite, "infinite", 1}, - {(cfunction_ptr)f_nan, "nan", 1}, - {(cfunction_ptr)f_sort, "sort", 1}, - {(cfunction_ptr)f_sort_by_impl, "_sort_by_impl", 2}, - {(cfunction_ptr)f_group_by_impl, "_group_by_impl", 2}, - {(cfunction_ptr)f_min, "min", 1}, - {(cfunction_ptr)f_max, "max", 1}, - {(cfunction_ptr)f_min_by_impl, "_min_by_impl", 2}, - {(cfunction_ptr)f_max_by_impl, "_max_by_impl", 2}, - {(cfunction_ptr)f_error, "error", 1}, - {(cfunction_ptr)f_format, "format", 2}, - {(cfunction_ptr)f_env, "env", 1}, - {(cfunction_ptr)f_halt, "halt", 1}, - {(cfunction_ptr)f_halt_error, "halt_error", 2}, - {(cfunction_ptr)f_get_search_list, "get_search_list", 1}, - {(cfunction_ptr)f_get_prog_origin, "get_prog_origin", 1}, - {(cfunction_ptr)f_get_jq_origin, "get_jq_origin", 1}, - {(cfunction_ptr)f_match, "_match_impl", 4}, - {(cfunction_ptr)f_modulemeta, "modulemeta", 1}, - {(cfunction_ptr)f_input, "input", 1}, - {(cfunction_ptr)f_debug, "debug", 1}, - {(cfunction_ptr)f_stderr, "stderr", 1}, - {(cfunction_ptr)f_strptime, "strptime", 2}, - {(cfunction_ptr)f_strftime, "strftime", 2}, - {(cfunction_ptr)f_strflocaltime, "strflocaltime", 2}, - {(cfunction_ptr)f_mktime, "mktime", 1}, - {(cfunction_ptr)f_gmtime, "gmtime", 1}, - {(cfunction_ptr)f_localtime, "localtime", 1}, - {(cfunction_ptr)f_now, "now", 1}, - {(cfunction_ptr)f_current_filename, "input_filename", 1}, - {(cfunction_ptr)f_current_line, "input_line_number", 1}, + {f_plus, "_plus", 3}, + {f_negate, "_negate", 1}, + {f_minus, "_minus", 3}, + {f_multiply, "_multiply", 3}, + {f_divide, "_divide", 3}, + {f_mod, "_mod", 3}, + {f_dump, "tojson", 1}, + {f_json_parse, "fromjson", 1}, + {f_tonumber, "tonumber", 1}, + {f_tostring, "tostring", 1}, + {f_keys, "keys", 1}, + {f_keys_unsorted, "keys_unsorted", 1}, + {f_startswith, "startswith", 2}, + {f_endswith, "endswith", 2}, + {f_ltrimstr, "ltrimstr", 2}, + {f_rtrimstr, "rtrimstr", 2}, + {f_string_split, "split", 2}, + {f_string_explode, "explode", 1}, + {f_string_implode, "implode", 1}, + {f_string_indexes, "_strindices", 2}, + {f_setpath, "setpath", 3}, // FIXME typechecking + {f_getpath, "getpath", 2}, + {f_delpaths, "delpaths", 2}, + {f_has, "has", 2}, + {f_equal, "_equal", 3}, + {f_notequal, "_notequal", 3}, + {f_less, "_less", 3}, + {f_greater, "_greater", 3}, + {f_lesseq, "_lesseq", 3}, + {f_greatereq, "_greatereq", 3}, + {f_contains, "contains", 2}, + {f_length, "length", 1}, + {f_utf8bytelength, "utf8bytelength", 1}, + {f_type, "type", 1}, + {f_isinfinite, "isinfinite", 1}, + {f_isnan, "isnan", 1}, + {f_isnormal, "isnormal", 1}, + {f_infinite, "infinite", 1}, + {f_nan, "nan", 1}, + {f_sort, "sort", 1}, + {f_sort_by_impl, "_sort_by_impl", 2}, + {f_group_by_impl, "_group_by_impl", 2}, + {f_min, "min", 1}, + {f_max, "max", 1}, + {f_min_by_impl, "_min_by_impl", 2}, + {f_max_by_impl, "_max_by_impl", 2}, + {f_error, "error", 1}, + {f_format, "format", 2}, + {f_env, "env", 1}, + {f_halt, "halt", 1}, + {f_halt_error, "halt_error", 2}, + {f_get_search_list, "get_search_list", 1}, + {f_get_prog_origin, "get_prog_origin", 1}, + {f_get_jq_origin, "get_jq_origin", 1}, + {f_match, "_match_impl", 4}, + {f_modulemeta, "modulemeta", 1}, + {f_input, "input", 1}, + {f_debug, "debug", 1}, + {f_stderr, "stderr", 1}, + {f_strptime, "strptime", 2}, + {f_strftime, "strftime", 2}, + {f_strflocaltime, "strflocaltime", 2}, + {f_mktime, "mktime", 1}, + {f_gmtime, "gmtime", 1}, + {f_localtime, "localtime", 1}, + {f_now, "now", 1}, + {f_current_filename, "input_filename", 1}, + {f_current_line, "input_line_number", 1}, }; #undef LIBM_DDDD_NO #undef LIBM_DDD_NO diff --git a/src/bytecode.h b/src/bytecode.h index 6cb49f7a..15019852 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -45,9 +45,8 @@ const struct opcode_description* opcode_describe(opcode op); #define MAX_CFUNCTION_ARGS 10 -typedef void (*cfunction_ptr)(); struct cfunction { - cfunction_ptr fptr; + jv (*fptr)(); const char* name; int nargs; }; diff --git a/src/execute.c b/src/execute.c index 78910077..86def927 100644 --- a/src/execute.c +++ b/src/execute.c @@ -914,17 +914,12 @@ jv jq_next(jq_state *jq) { in[i] = stack_pop(jq); } struct cfunction* function = &frame_current(jq)->bc->globals->cfunctions[*pc++]; - typedef jv (*func_1)(jq_state*,jv); - typedef jv (*func_2)(jq_state*,jv,jv); - typedef jv (*func_3)(jq_state*,jv,jv,jv); - typedef jv (*func_4)(jq_state*,jv,jv,jv,jv); - typedef jv (*func_5)(jq_state*,jv,jv,jv,jv,jv); switch (function->nargs) { - case 1: top = ((func_1)function->fptr)(jq, in[0]); break; - case 2: top = ((func_2)function->fptr)(jq, in[0], in[1]); break; - case 3: top = ((func_3)function->fptr)(jq, in[0], in[1], in[2]); break; - case 4: top = ((func_4)function->fptr)(jq, in[0], in[1], in[2], in[3]); break; - case 5: top = ((func_5)function->fptr)(jq, in[0], in[1], in[2], in[3], in[4]); break; + case 1: top = function->fptr(jq, in[0]); break; + case 2: top = function->fptr(jq, in[0], in[1]); break; + case 3: top = function->fptr(jq, in[0], in[1], in[2]); break; + case 4: top = function->fptr(jq, in[0], in[1], in[2], in[3]); break; + case 5: top = function->fptr(jq, in[0], in[1], in[2], in[3], in[4]); break; // FIXME: a) up to 7 arguments (input + 6), b) should assert // because the compiler should not generate this error. default: return jv_invalid_with_msg(jv_string("Function takes too many arguments"));