ids ::= COMMA_LIST(pmid)
pmid ::= id
| mid
mid ::= rulename_id.id
pmid_with_regexp ::= pmid =˜ regexp
| pmid !˜ regexp
pmid_with_not_eq ::= pmid [!= id_or_meta]
| pmid [!= { COMMA_LIST(id_or_meta) }]
pmid_with_virt_or_not_eq ::= virtual.id
| pmid_with_not_eq
pmid_with_not_ceq ::= pmid [!= id_or_cst]
| pmid [!= { COMMA_LIST(id_or_cst) }]
id_or_cst ::= id
| integer
id_or_meta ::= id
| rulename_id.id
pmid_with_not_eq_mid ::= pmid [ANDAND_LIST(pos_constraint)]
pos_constraint ::= != mid
| != { COMMA_LIST(mid) }
| : script:ocaml (COMMA_LIST( mid )) {expr }
ANDAND_LIST(X) ::= X
| X && ANDAND_LIST(X)
Subsequently, we refer to arbitrary metavariables as metaid
ty
, where ty indicates the metakind used in the decla-
ration of the variable. For example, metaid
Type
refers to a metavariable that was declared using type and stands for
any type.
metavariable declares a metavariable for which the parser tried to figure out the metavariable type based
on the usage context. Such a metavariable must be used consistently. These metavariables cannot be used in all
contexts; specifically, they cannot be used in context that would make the parsing ambiguous. Some examples are the
leftmost term of an expression, such as the left-hand side of an assignment, or the type in a variable declaration. These
restrictions may seems somewhat arbitrary from the user’s point of view. Thus, it is better to use metavariables with
metavariable types. If Coccinelle is given the argument -parse_cocci, it will print information about the type that
is inferred for each metavariable.
The ctype and ctypes nonterminals are used by both the grammar of metavariable declarations and the grammar of
transformations, and are defined on page 15.
An identifier metavariable with virtual as its “rule name” is given a value on the command line. For example,
if a semantic patch contains a rule that declares an identifier metavariable with the name virtual.alloc, then
the command line could contain -D alloc=kmalloc. There should not be space around the =. An example is in
demos/vm.cocci and demos/vm.c.
It is possible to give an identifier metavariable a list of constraints that it should or should not be equal to. If the
constraint is a list of (unquoted) strings, then the value of the metavariable should be the same as one of the strings, in
the case of an equality constraint, or different from all of the strings, in the case of an inequality constraint. It is also
possible to include inherited identifier metavariables among the constraints. In the case of a positive constraint, things
work in the same way, but not with respect to the inherited value of the metavariable. On the other hand, an inequality
constraint does not work so well, because the only value available is the one available in the current environment. If
the proposed value is different from the one in the current environment, but perhaps the same as the one in some other
environment, the match will still succeed.
Position metavariables can be associated with constraints implemented as OCaml script code. The code must have
the form of a single C expression, typically a function call with a tuple of arguments. This expression must have
type bool. The script code can be parameterized by any inherited metavariables. It is implicitly parameterized by the
metavariable being declared. In the script, the inherited variable parameters are referred to by their variable names,
without the associated rule name. The variable being declared is also referenced by its name. All parameters, except
6