Hi all, I work on the VPP project (http://fd.io/ - open source software dataplane), and yesterday tried to use coccinelle to make a relatively non-trivial change as in the mail https://lists.fd.io/g/vpp-dev/message/17532 - it seemed to be a very good candidate - boring enough to be painful to do by hand, complex enough to make sed inadequate for it.
I came up with this semantic patch: @ detect_func @ identifier CLI_FN, AVM, AIN, ACMD; fresh identifier LAIN = "line_" ## AIN; statement S1; typedef clib_error_t, vlib_main_t, unformat_input_t, vlib_cli_command_t; @@ static clib_error_t *CLI_FN (vlib_main_t * AVM, unformat_input_t * AIN, vlib_cli_command_t * ACMD) { + clib_error_t *e = 0; + unformat_input_t *LAIN; ... + if (!unformat_user (AIN, unformat_line_input, LAIN)) { + return 0; + } + - while (unformat_check_input (AIN) != UNFORMAT_END_OF_INPUT) + while (unformat_check_input (LAIN) != UNFORMAT_END_OF_INPUT) S1 <... - return ERR; + e = ERR; + goto done; ...> +done: + unformat_free(LAIN); + return e; } I attempt to run it on this test file: ubuntu@vpp-dev:~$ cat ~/test.c static clib_error_t * syn_filter_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ~0; int enable_disable = 1; int rv; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "disable")) enable_disable = 0; else if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) ; else break; } if (sw_if_index == ~0) return clib_error_return (0, "Please specify an interface..."); rv = syn_filter_enable_disable (sw_if_index, enable_disable); switch (rv) { case 0: break; case VNET_API_ERROR_INVALID_SW_IF_INDEX: return clib_error_return (0, "Invalid interface, only works on physical ports"); break; case VNET_API_ERROR_UNIMPLEMENTED: return clib_error_return (0, "Device driver doesn't support redirection"); break; case VNET_API_ERROR_INVALID_VALUE: return clib_error_return (0, "feature arc not found"); case VNET_API_ERROR_INVALID_VALUE_2: return clib_error_return (0, "feature node not found"); default: return clib_error_return (0, "syn_filter_enable_disable returned %d", rv); } return 0; } ubuntu@vpp-dev:~$ However, when I run it, the "done: " label, etc. gets inserted twice: ubuntu@vpp-dev:~$ spatch --sp-file /tmp/rules.sp --allow-inconsistent-paths ~/test.c init_defs_builtins: /usr/bin/../lib/coccinelle/standard.h HANDLING: /home/ubuntu/test.c diff = --- /home/ubuntu/test.c +++ /tmp/cocci-output-56896-8f35c5-test.c @@ -3,12 +3,18 @@ syn_filter_enable_disable_command_fn (vl unformat_input_t * input, vlib_cli_command_t * cmd) { + clib_error_t *e = 0; + unformat_input_t *line_input; vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ~0; int enable_disable = 1; int rv; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + if (!unformat_user(input, unformat_line_input, line_input)) { + return 0; + } + +while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "disable")) enable_disable = 0; @@ -48,6 +54,12 @@ syn_filter_enable_disable_command_fn (vl default: return clib_error_return (0, "syn_filter_enable_disable returned %d", rv); - } + done: + unformat_free(line_input); + return e; + } return 0; +done: + unformat_free(line_input); + return e; } ubuntu@vpp-dev:~$ I get a feeling I am missing something fundamental - but RTFM did not help much... Could anyone please nudge me in the correct direction ? Thanks a lot! --a _______________________________________________ Cocci mailing list Cocci@systeme.lip6.fr https://systeme.lip6.fr/mailman/listinfo/cocci