Often it is useful to have several semantic patches that have a similar structure, but that use different concrete variable names. For example, one could have a collection of semantic patches for finding or fixing memory leaks. These might all have the same structure, but differ in the names of the allocation and deallocation functions. To address this case, it is possible (starting in version 0.2.1) to parameterize a rule using virtual identifiers. Any identifier metavariable can be declared a being inherited from the rule virtual (which thus is not a valid rule name), in which case the value of the variable comes from the corresponding -D option on the command line, if any.
An example is as follows (demos/vm.cocci):
@r@
identifier virtual.alloc, virtual.free;
expression x;
position p1,p2;
@@
x = alloc@p1(...);
...
free@p2(x);
@script:python@
p1 << r.p1;
p2 << r.p2;
alloc << virtual.alloc;
@@
cocci.print_main(alloc,p1);
cocci.print_secs("free",p2);
Given the following C file (demos/vm.c):
int main () {
x = kmalloc();
r = 15;
kfree(x);
}
The semantic patch prints a message if run as:
spatch -sp_file demos/vm.cocci demos/vm.c -D alloc=kmalloc -D free=kfree
Note that there is no space around the =. On the other hand there is no message if the semantic patch is run as, eg:
spatch -sp_file demos/vm.cocci demos/vm.c -D alloc=kmalloc
because a binding for free is needed for the first rule to match, and none is provided. Similarly there is no match for eg:
spatch -sp_file demos/vm.cocci demos/vm.c -D alloc=malloc -D free=free
because the C file contains kmalloc and kfree, not malloc and free.