On Sun, 13 Jun 2010, Josh Triplett wrote:

> Hello,
> 
> I've just started trying to use Coccinelle to rewrite code written for
> Xlib to use our replacement library XCB instead.
> 
> In trying some simple test patches and learning Coccinelle, I
> encountered this error:
> 
> """
> HANDLING: /tmp/bug.c
> 
> previous modification:
> MINUS
>   >>> xcb_disconnect(conn);
> 
> According to environment 0:
> 
> 
> current modification:
> MINUS
> According to environment 0:
> 
> 
> Fatal error: exception Failure("rule starting on line 1: already tagged token:
> C code context
> File "/tmp/bug.c", line 5, column 1,  charpos = 45
>     around = 'XCloseDisplay', whole content =   XCloseDisplay (dpy);")
> """

In general, what the error means is that it found two different things to 
do for a token in the source program; once to remove it and add something 
and another time just to remove it.

> I reduced the semantic patch and the source file to minimal test cases.
> The semantic patch:
> 
> @@
> identifier dpy;
> @@
> (
> -if (dpy) { XCloseDisplay(dpy); }
> +xcb_disconnect(conn);
> |
> -XCloseDisplay(dpy);
> +xcb_disconnect(conn);
> )

First point: if (dpy) { XCloseDisplay(dpy); } is also considered to match 
if (dpy) XCloseDisplay(dpy); by an isomorphism.

Then, the basic idea of ( | ) is that it works from top to bottom; if the 
first branch matches the second one should not be applied.  But the more 
precise semantics is that this is what happens at the node level.  If you 
look at the control-flow graph for your source program, which you can see 
with the option -control_flow and just the name of the C file, you will 
see that the header of an if statement and the branch are different nodes.

Since the root node matched by the if (dpy) XCloseDisplay(dpy); pattern is 
different fro the root node matched by the XCloseDisplay(dpy); pattern, 
they are just considered to be disjoint matches, and the top to bottom 
semantics of ( | ) doesn't help.  Thus there are two possible and 
conflicting matches.

The solution is to separate the semantic patch into two rules, with the 
first rule taking care of the if case and the second rule taking care of 
any calls to XCloseDisplay(dpy); that are left over.

In this case there is no ambiguity, because the first rule will delete the 
part of the code that might be matched by the second rule.  If this were 
not the case, you could use position variables to ensure that the second 
rule does not match the same calls that the first one does.  For example:

 @r@
 identifier dpy;
 position p;
 @@
 if (dpy) { xclosedisp...@p(dpy); }
 +xcb_disconnect(conn);

 @@
 identifier dpy;
 position p != r.p;
 @@
 xclosedisp...@p(dpy);
 +xcb_disconnect(conn);

If neither is sufficient for your actual problem, feel free to write back.

julia
_______________________________________________
Cocci mailing list
[email protected]
http://lists.diku.dk/mailman/listinfo/cocci
(Web access from inside DIKUs LAN only)

Reply via email to