For more information, see the following thread http://lists.diku.dk/pipermail/cocci/2009-June/000275.html
First, we update the inner function
@haslocalflash@
identifier f;
identifier flash;
expression V1, V2, V3;
@@
f(...)
{
struct flashchip *flash;
<+...
(
-chip_readb(V1)
+chip_readb(flash,V1)
|
-chip_writeb(V2, V3)
+chip_writeb(flash,V2, V3)
)
...+>
}
@hasflash depends on !haslocalflash@
identifier f;
identifier flash;
parameter list[n] AS;
expression V1, V2, V3;
@@
f(struct flashchip *flash, AS)
{
<+...
(
-chip_readb(V1)
+chip_readb(flash,V1)
|
-chip_writeb(V2, V3)
+chip_writeb(flash,V2, V3)
)
...+>
}
@toupdate depends on !hasflash && !haslocalflash@
identifier f;
parameter list[n] AS;
expression V1, V2, V3;
@@
f(
+struct flashchip *flash,
AS)
{
<+...
(
-chip_readb(V1)
+chip_readb(flash,V1)
|
-chip_writeb(V2, V3)
+chip_writeb(flash,V2, V3)
)
...+>
}
@toupdate2@
identifier f;
expression V1, V2, V3;
@@
f(
-void
+struct flashchip *flash
)
{
<+...
(
-chip_readb(V1)
+chip_readb(flash,V1)
|
-chip_writeb(V2, V3)
+chip_writeb(flash,V2, V3)
)
...+>
}
In the hasflash rule, we identify names of functions to update.
The Python code then generates a cocci rule for each of them.
The generated rules update the function call and change the parameter
of the outer function. By apply recursively this cocci file and
the generated rules, the user eventually reaches a state where
the new parameter is present in the whole call chain.
@hasflash@
identifier f;
identifier flash;
parameter list ARGS;
@@
f(struct flashchip *flash, ARGS)
{
...
}
@script:python@
f << hasflash.f;
@@
// This is the generation pattern
print """
[...]
@toupdate2@
identifier f;
expression list ES;
@@
f(
-void
+struct flashchip *flash
)
{
<+...
-%s(ES)
+%s(flash, ES)
...+>
}
""" % (f, f)