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)