This perhaps is not the best demo for use of ++ but it
should suffice. This adds some basic documentation for it
and a demo.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
 demos/vars1.c                |  26 ++++++++
 demos/vars1.cocci            |  28 +++++++++
 demos/vars1.res              |  26 ++++++++
 demos/vars2.c                |  28 +++++++++
 demos/vars2.cocci            |  36 ++++++++++++
 demos/vars2.res              |  28 +++++++++
 docs/manual/cocci_syntax.tex | 137 +++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 309 insertions(+)
 create mode 100644 demos/vars1.c
 create mode 100644 demos/vars1.cocci
 create mode 100644 demos/vars1.res
 create mode 100644 demos/vars2.c
 create mode 100644 demos/vars2.cocci
 create mode 100644 demos/vars2.res

diff --git a/demos/vars1.c b/demos/vars1.c
new file mode 100644
index 000000000000..b308c05b2013
--- /dev/null
+++ b/demos/vars1.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+struct foo {
+       int a;
+       int b;
+       int c;
+};
+
+struct foo stuff {
+       a = 1,
+       b = 2,
+       c = 3,
+};
+
+int main(void)
+{
+       struct foo *bar = &stuff;
+       int copy_a = bar->a;
+
+       if (true) {
+               printf("copy_a: %d\n", copy_a);
+       }
+
+       return 0;
+}
diff --git a/demos/vars1.cocci b/demos/vars1.cocci
new file mode 100644
index 000000000000..055afbc34688
--- /dev/null
+++ b/demos/vars1.cocci
@@ -0,0 +1,28 @@
+/*
+ * This can move unused variables declaration and assignment
+ * which is only used in the branch into the branch. Its
+ * resticted however to only apply to code where this happens
+ * only once. Refer to vars2.[c|cocci] for handling multiple
+ * cases.
+ */
+
+@simpleplus@
+identifier f, x, i, var;
+expression e1;
+type T;
+@@
+
+f (...) {
+ ... when != x
+     when any
+-T x = i->var;
+ ... when != x
+     when != i = e1
+     when any
+ if (...) {
++  T x = var;
+   <+...x...+>
+  }
+... when != x
+    when any
+}
diff --git a/demos/vars1.res b/demos/vars1.res
new file mode 100644
index 000000000000..98270324eea5
--- /dev/null
+++ b/demos/vars1.res
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+struct foo {
+       int a;
+       int b;
+       int c;
+};
+
+struct foo stuff {
+       a = 1,
+       b = 2,
+       c = 3,
+};
+
+int main(void)
+{
+       struct foo *bar = &stuff;
+
+       if (true) {
+               int copy_a = bar->a;
+               printf("copy_a: %d\n", copy_a);
+       }
+
+       return 0;
+}
diff --git a/demos/vars2.c b/demos/vars2.c
new file mode 100644
index 000000000000..b58bb467b388
--- /dev/null
+++ b/demos/vars2.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+struct foo {
+       int a;
+       int b;
+       int c;
+};
+
+struct foo stuff {
+       a = 1,
+       b = 2,
+       c = 3,
+};
+
+int main(void)
+{
+       struct foo *bar = &stuff;
+       int copy_a = bar->a;
+       int copy_b = bar->b;
+
+       if (true) {
+               printf("copy_a: %d\n", copy_a);
+               printf("copy_b: %d\n", copy_b);
+       }
+
+       return 0;
+}
diff --git a/demos/vars2.cocci b/demos/vars2.cocci
new file mode 100644
index 000000000000..d42b4acbcb5a
--- /dev/null
+++ b/demos/vars2.cocci
@@ -0,0 +1,36 @@
+/*
+ * This can move more than one unused variables declaration and assignment
+ * which is only used in the branch into the branch.
+ *
+ * This uses ++ to support the fact that the rule may be working
+ * with multiple variables that we need to modify and that order
+ * doe snot matter.
+ *
+ * If you don't use "++" you'll get "already tagged token" error since
+ * Coccinelle is concerned that the user has no way of specifying the order
+ * in which they should appear. By using "++" you are telling Coccinelle
+ *
+ *   "I know that a lot of things can collect here, and I'm OK
+ *    with that.  I'm also OK with things getting added out of order.
+ */
+
+@plusplus@
+identifier f, x, i, var;
+expression e1;
+type T;
+@@
+
+f (...) {
+ ... when != x
+     when any
+-T x = i->var;
+ ... when != x
+     when != i = e1
+     when any
+ if (...) {
+++  T x = var;
+   <+...x...+>
+  }
+... when != x
+    when any
+}
diff --git a/demos/vars2.res b/demos/vars2.res
new file mode 100644
index 000000000000..e798c8f54529
--- /dev/null
+++ b/demos/vars2.res
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdbool.h>
+
+struct foo {
+       int a;
+       int b;
+       int c;
+};
+
+struct foo stuff {
+       a = 1,
+       b = 2,
+       c = 3,
+};
+
+int main(void)
+{
+       struct foo *bar = &stuff;
+
+       if (true) {
+               int copy_a = bar->a;
+               int copy_b = bar->b;
+               printf("copy_a: %d\n", copy_a);
+               printf("copy_b: %d\n", copy_b);
+       }
+
+       return 0;
+}
diff --git a/docs/manual/cocci_syntax.tex b/docs/manual/cocci_syntax.tex
index e8d74a7d015f..7cbbc9d0d74f 100644
--- a/docs/manual/cocci_syntax.tex
+++ b/docs/manual/cocci_syntax.tex
@@ -851,6 +851,11 @@ rule should apply if rule XXX was never matched at all.
 
 \section{Transformation}
 
+Coccinelle allows for transformations to enable modifying C code using
+very precise grammar.
+
+\subsection{Basic transformations}
+
 The transformation specification essentially has the form of C code, except
 that lines to remove are annotated with \verb+-+ in the first column, and
 lines to add are annotated with \verb-+-.  A transformation specification
@@ -1100,6 +1105,138 @@ write
 Some kinds of terms can only appear in + code.  These include comments,
 ifdefs, and attributes (\texttt{\_\_attribute\_\_((...))}).
 
+\subsection{Advanced transformations}
+
+You may run into the situation where grammar you specificy for
+transformations might associate itself with a few consecutive tokens
+in code, in such cases Coccinelle cannot gaurantee order when making
+additions. If you are sure that order does not matter you can use the
+optional double addition token \texttt{++} to annotate that Coccinelle
+may add things out of order. For instance, the following rule helps
+move unused variable declaration into the branch if its only used
+there.
+
+\begin{lstlisting}[language=Cocci]
+@simpleplus@
+identifier f, x, i, var;
+expression e1;
+type T;
+@@
+
+f (...) {
+ ... when != x
+     when any
+-T x = i->var;
+ ... when != x
+     when != i = e1
+     when any
+ if (...) {
++  T x = var;
+   <+...x...+>
+  }
+... when != x
+    when any
+}
+\end{lstlisting}
+
+This simpleplus rule transformation works well when only one token is being
+modified in code. For instance if we had simpleplus.c:
+
+\begin{lstlisting}[language=C]
+#include <stdio.h>
+#include <stdbool.h>
+
+struct foo {
+       int a;
+       int b;
+       int c;
+};
+
+struct foo stuff {
+       a = 1,
+       b = 2,
+       c = 3,
+};
+
+int main(void)
+{
+       struct foo *bar = &stuff;
+       int copy_a = bar->a;
+
+       if (true) {
+               printf("copy_a: %d\n", copy_a);
+       }
+
+       return 0;
+}
+\end{lstlisting}
+
+If however you have two consecutive tokens that Coccinelle
+can transform order cannot be guaranteed for how Coccinelle
+makes additions. If you are sure order does not matter for
+the transformation you may use \texttt{++} instead, as follows:
+
+\begin{lstlisting}[language=Cocci]
+@plusplus@
+identifier f, x, i, var;
+expression e1;
+type T;
+@@
+
+f (...) {
+ ... when != x
+     when any
+-T x = i->var;
+ ... when != x
+     when != i = e1
+     when any
+ if (...) {
+++  T x = var;
+   <+...x...+>
+  }
+... when != x
+    when any
+}
+\end{lstlisting}
+
+This rule would work against say a plusplus.c which had just
+one more token added in comparison to simpleplus.c:
+
+\begin{lstlisting}[language=C]
+#include <stdio.h>
+#include <stdbool.h>
+
+struct foo {
+       int a;
+       int b;
+       int c;
+};
+
+struct foo stuff {
+       a = 1,
+       b = 2,
+       c = 3,
+};
+
+int main(void)
+{
+       struct foo *bar = &stuff;
+       int copy_a = bar->a;
+       int copy_b = bar->b;
+
+       if (true) {
+               printf("copy_a: %d\n", copy_a);
+               printf("copy_b: %d\n", copy_b);
+       }
+
+       return 0;
+}
+\end{lstlisting}
+
+If you used simpleplus rule on plusplus.c you would end up with
+an "already tagged token" error due to the ordering considerations
+explained in this section.
+
 \section{Types}
 \label{types}
 
-- 
2.8.2

_______________________________________________
Cocci mailing list
[email protected]
https://systeme.lip6.fr/mailman/listinfo/cocci

Reply via email to