Commit Graph
3 Commits
Author SHA1 Message Date
Emanuele Torre 0b82b3841b builtin.c: typecheck builtin cfunctions in function_list
In C23 (default C standard used by GCC 15),  jv (*fptr)();  has become
equivalent to  jv (*fptr)(void);  so we can no longer assign builtin
implemenations directly to the fptr member of cfunctions without
generating a compile error.

Since there does not seem to be any straight-forward way to tell
autoconf to force the compiler to use C99 short of explicitly adding
-std=c99 to CFLAGS, it is probably a cleaner solution to just make the
code C23 compatible.

A possible solution could have been to just redeclare  cfunction.fptr
as void*, but then the functions' return type would not have been type
checked (e.g. if you tried to add a {printf, "printf", 2}, where printf
is a function that does not return jv, the compiler wouldn't have
complained.)
We were already not typechecking the arguments of the functions, so e.g.
  {binop_plus, "_plus", 3},  /* instead of {f_plus, "_plus, 3},       */
  {f_setpath, "setpath", 4}, /* instead of {f_setpath, "setpath", 3}, */
compile without errors despite not having the correct prototype.

So I thought of instead improving the situation by redefining
cfunction.fptr as a union of function pointers with the prototypes that
the jq bytecode interpreter can call, and use a macro to add the builtin
functions to function_list using to the arity argument to assign the
implementation function to the appropriate union member.

Now the code won't compile if the wrong arity, or an arity not supported
by the bytecode interpreter (>5 = 1input+4arguments), or a prototype not
jallable by the bytecode interpreter (e.g. binop_plus that doesn't
expect a  jq_state*  argument).

Also, the code now compiles with gcc -std=c23.

Fixes #3206
2024-12-01 11:49:44 +01:00
Emanuele Torre 6716e23ae6 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.
2023-07-31 15:28:01 -05:00
David Tolnay 0c93eb3379 Move source files to src/ 2015-08-23 20:36:11 -07:00