cocci.inria.fr archive mirror
 help / color / mirror / Atom feed
* [Cocci] how to make substitutions at the end of the function, vs. the end of the block ?
@ 2021-07-16  9:31 Andrew 👽  Yourtchenko
  2021-07-31 19:20 ` Mansour Moufid
  0 siblings, 1 reply; 2+ messages in thread
From: Andrew 👽  Yourtchenko @ 2021-07-16  9:31 UTC (permalink / raw)
  To: cocci

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

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Cocci] how to make substitutions at the end of the function, vs. the end of the block ?
  2021-07-16  9:31 [Cocci] how to make substitutions at the end of the function, vs. the end of the block ? Andrew 👽  Yourtchenko
@ 2021-07-31 19:20 ` Mansour Moufid
  0 siblings, 0 replies; 2+ messages in thread
From: Mansour Moufid @ 2021-07-31 19:20 UTC (permalink / raw)
  To: Andrew 👽 Yourtchenko; +Cc: cocci

On Fri, Jul 30, 2021 at 7:00 AM Andrew 👽 Yourtchenko
<ayourtch@gmail.com> wrote:
>
> However, when I run it, the "done: " label, etc. gets inserted twice:

Every return statement is the end of a function. ;)

I don't know of a way to match only the "last" return statement in a
function, maybe with scripting...
_______________________________________________
Cocci mailing list
Cocci@systeme.lip6.fr
https://systeme.lip6.fr/mailman/listinfo/cocci

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-07-31 19:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-16  9:31 [Cocci] how to make substitutions at the end of the function, vs. the end of the block ? Andrew 👽  Yourtchenko
2021-07-31 19:20 ` Mansour Moufid

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).