aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-16 17:36:07 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-16 17:36:07 -0500
commit408e057870c8680a50963b08f9f7efaa151a74ec (patch)
tree4d4085332d0b1b7e8727cb037dfb206fc1ed538c /scripts
parent287b901dcadd7eb3c5aa93b679bbad4058814921 (diff)
parent29a36d4dec6cf7ad72e6e3337bf954096cbbb4cf (diff)
Merge branch 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
* 'misc' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild: scripts/coccinelle: improve the coverage of some semantic patches coccinelle: semantic patches related to devm_ functions (part 2) coccinelle: semantic patches related to devm_ functions (part 1) coccinelle.txt: update documentation to include M= option coccicheck: add M= option to control which dir is processed ctags: remove struct forward declarations scripts/tags.sh: Add Page flag function magic
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/coccicheck19
-rw-r--r--scripts/coccinelle/api/devm_request_and_ioremap.cocci105
-rw-r--r--scripts/coccinelle/api/kstrdup.cocci75
-rw-r--r--scripts/coccinelle/api/memdup.cocci34
-rw-r--r--scripts/coccinelle/api/memdup_user.cocci39
-rw-r--r--scripts/coccinelle/free/devm_free.cocci71
-rw-r--r--scripts/coccinelle/free/kfree.cocci14
-rw-r--r--scripts/coccinelle/iterators/fen.cocci73
-rw-r--r--scripts/coccinelle/iterators/itnull.cocci54
-rw-r--r--scripts/coccinelle/locks/call_kern.cocci67
-rw-r--r--scripts/coccinelle/locks/flags.cocci12
-rw-r--r--scripts/coccinelle/locks/mini_lock.cocci15
-rw-r--r--scripts/coccinelle/misc/doubleinit.cocci8
-rw-r--r--scripts/coccinelle/null/eno.cocci36
-rwxr-xr-xscripts/tags.sh48
15 files changed, 587 insertions, 83 deletions
diff --git a/scripts/coccicheck b/scripts/coccicheck
index 1bb1a1bd2daa..3c2776466d87 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -9,14 +9,23 @@ if [ "$C" = "1" -o "$C" = "2" ]; then
9# FLAGS="-ignore_unknown_options -very_quiet" 9# FLAGS="-ignore_unknown_options -very_quiet"
10# OPTIONS=$* 10# OPTIONS=$*
11 11
12# Workaround for Coccinelle < 0.2.3 12 if [ "$KBUILD_EXTMOD" = "" ] ; then
13 FLAGS="-I $srctree/include -very_quiet" 13 # Workaround for Coccinelle < 0.2.3
14 shift $(( $# - 1 )) 14 FLAGS="-I $srctree/include -very_quiet"
15 OPTIONS=$1 15 shift $(( $# - 1 ))
16 OPTIONS=$1
17 else
18 echo M= is not currently supported when C=1 or C=2
19 exit 1
20 fi
16else 21else
17 ONLINE=0 22 ONLINE=0
18 FLAGS="-very_quiet" 23 FLAGS="-very_quiet"
19 OPTIONS="-dir $srctree" 24 if [ "$KBUILD_EXTMOD" = "" ] ; then
25 OPTIONS="-dir $srctree"
26 else
27 OPTIONS="-dir $KBUILD_EXTMOD -patch $srctree -I $srctree/include -I $KBUILD_EXTMOD/include"
28 fi
20fi 29fi
21 30
22if [ ! -x "$SPATCH" ]; then 31if [ ! -x "$SPATCH" ]; then
diff --git a/scripts/coccinelle/api/devm_request_and_ioremap.cocci b/scripts/coccinelle/api/devm_request_and_ioremap.cocci
new file mode 100644
index 000000000000..46beb81406ab
--- /dev/null
+++ b/scripts/coccinelle/api/devm_request_and_ioremap.cocci
@@ -0,0 +1,105 @@
1/// Reimplement a call to devm_request_mem_region followed by a call to ioremap
2/// or ioremap_nocache by a call to devm_request_and_ioremap.
3/// Devm_request_and_ioremap was introduced in
4/// 72f8c0bfa0de64c68ee59f40eb9b2683bffffbb0. It makes the code much more
5/// concise.
6///
7///
8// Confidence: High
9// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. GPLv2.
10// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2.
11// URL: http://coccinelle.lip6.fr/
12// Comments:
13// Options: -no_includes -include_headers
14
15virtual patch
16virtual org
17virtual report
18virtual context
19
20@nm@
21expression myname;
22identifier i;
23@@
24
25struct platform_driver i = { .driver = { .name = myname } };
26
27@depends on patch@
28expression dev,res,size;
29@@
30
31-if (!devm_request_mem_region(dev, res->start, size,
32- \(res->name\|dev_name(dev)\))) {
33- ...
34- return ...;
35-}
36... when != res->start
37(
38-devm_ioremap(dev,res->start,size)
39+devm_request_and_ioremap(dev,res)
40|
41-devm_ioremap_nocache(dev,res->start,size)
42+devm_request_and_ioremap(dev,res)
43)
44... when any
45 when != res->start
46
47// this rule is separate from the previous one, because a single file can
48// have multiple values of myname
49@depends on patch@
50expression dev,res,size;
51expression nm.myname;
52@@
53
54-if (!devm_request_mem_region(dev, res->start, size,myname)) {
55- ...
56- return ...;
57-}
58... when != res->start
59(
60-devm_ioremap(dev,res->start,size)
61+devm_request_and_ioremap(dev,res)
62|
63-devm_ioremap_nocache(dev,res->start,size)
64+devm_request_and_ioremap(dev,res)
65)
66... when any
67 when != res->start
68
69
70@pb depends on org || report || context@
71expression dev,res,size;
72expression nm.myname;
73position p1,p2;
74@@
75
76*if
77 (!devm_request_mem_region@p1(dev, res->start, size,
78 \(res->name\|dev_name(dev)\|myname\))) {
79 ...
80 return ...;
81}
82... when != res->start
83(
84*devm_ioremap@p2(dev,res->start,size)
85|
86*devm_ioremap_nocache@p2(dev,res->start,size)
87)
88... when any
89 when != res->start
90
91@script:python depends on org@
92p1 << pb.p1;
93p2 << pb.p2;
94@@
95
96cocci.print_main("INFO: replace by devm_request_and_ioremap",p1)
97cocci.print_secs("",p2)
98
99@script:python depends on report@
100p1 << pb.p1;
101p2 << pb.p2;
102@@
103
104msg = "INFO: devm_request_mem_region followed by ioremap on line %s can be replaced by devm_request_and_ioremap" % (p2[0].line)
105coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/coccinelle/api/kstrdup.cocci b/scripts/coccinelle/api/kstrdup.cocci
index e0805ad08d39..07a74b2c6196 100644
--- a/scripts/coccinelle/api/kstrdup.cocci
+++ b/scripts/coccinelle/api/kstrdup.cocci
@@ -1,16 +1,19 @@
1/// Use kstrdup rather than duplicating its implementation 1/// Use kstrdup rather than duplicating its implementation
2/// 2///
3// Confidence: High 3// Confidence: High
4// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 4// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
5// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 5// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
6// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 6// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
7// URL: http://coccinelle.lip6.fr/ 7// URL: http://coccinelle.lip6.fr/
8// Comments: 8// Comments:
9// Options: -no_includes -include_headers 9// Options: -no_includes -include_headers
10 10
11virtual patch 11virtual patch
12virtual context
13virtual org
14virtual report
12 15
13@@ 16@depends on patch@
14expression from,to; 17expression from,to;
15expression flag,E1,E2; 18expression flag,E1,E2;
16statement S; 19statement S;
@@ -23,7 +26,7 @@ statement S;
23 ... when != \(from = E2 \| to = E2 \) 26 ... when != \(from = E2 \| to = E2 \)
24- strcpy(to, from); 27- strcpy(to, from);
25 28
26@@ 29@depends on patch@
27expression x,from,to; 30expression x,from,to;
28expression flag,E1,E2,E3; 31expression flag,E1,E2,E3;
29statement S; 32statement S;
@@ -37,3 +40,65 @@ statement S;
37 if (to==NULL || ...) S 40 if (to==NULL || ...) S
38 ... when != \(x = E3 \| from = E3 \| to = E3 \) 41 ... when != \(x = E3 \| from = E3 \| to = E3 \)
39- memcpy(to, from, x); 42- memcpy(to, from, x);
43
44// ---------------------------------------------------------------------
45
46@r1 depends on !patch exists@
47expression from,to;
48expression flag,E1,E2;
49statement S;
50position p1,p2;
51@@
52
53* to = kmalloc@p1(strlen(from) + 1,flag);
54 ... when != \(from = E1 \| to = E1 \)
55 if (to==NULL || ...) S
56 ... when != \(from = E2 \| to = E2 \)
57* strcpy@p2(to, from);
58
59@r2 depends on !patch exists@
60expression x,from,to;
61expression flag,E1,E2,E3;
62statement S;
63position p1,p2;
64@@
65
66* x = strlen(from) + 1;
67 ... when != \( x = E1 \| from = E1 \)
68* to = \(kmalloc@p1\|kzalloc@p2\)(x,flag);
69 ... when != \(x = E2 \| from = E2 \| to = E2 \)
70 if (to==NULL || ...) S
71 ... when != \(x = E3 \| from = E3 \| to = E3 \)
72* memcpy@p2(to, from, x);
73
74@script:python depends on org@
75p1 << r1.p1;
76p2 << r1.p2;
77@@
78
79cocci.print_main("WARNING opportunity for kstrdep",p1)
80cocci.print_secs("strcpy",p2)
81
82@script:python depends on org@
83p1 << r2.p1;
84p2 << r2.p2;
85@@
86
87cocci.print_main("WARNING opportunity for kstrdep",p1)
88cocci.print_secs("memcpy",p2)
89
90@script:python depends on report@
91p1 << r1.p1;
92p2 << r1.p2;
93@@
94
95msg = "WARNING opportunity for kstrdep (strcpy on line %s)" % (p2[0].line)
96coccilib.report.print_report(p1[0], msg)
97
98@script:python depends on report@
99p1 << r2.p1;
100p2 << r2.p2;
101@@
102
103msg = "WARNING opportunity for kstrdep (memcpy on line %s)" % (p2[0].line)
104coccilib.report.print_report(p1[0], msg)
diff --git a/scripts/coccinelle/api/memdup.cocci b/scripts/coccinelle/api/memdup.cocci
index b5d722077dc1..4dceab6d54de 100644
--- a/scripts/coccinelle/api/memdup.cocci
+++ b/scripts/coccinelle/api/memdup.cocci
@@ -1,14 +1,17 @@
1/// Use kmemdup rather than duplicating its implementation 1/// Use kmemdup rather than duplicating its implementation
2/// 2///
3// Confidence: High 3// Confidence: High
4// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 4// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
5// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 5// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
6// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 6// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
7// URL: http://coccinelle.lip6.fr/ 7// URL: http://coccinelle.lip6.fr/
8// Comments: 8// Comments:
9// Options: -no_includes -include_headers 9// Options: -no_includes -include_headers
10 10
11virtual patch 11virtual patch
12virtual context
13virtual org
14virtual report
12 15
13@r1@ 16@r1@
14expression from,to; 17expression from,to;
@@ -28,7 +31,7 @@ position p;
28 ... when != \( x = E1 \| from = E1 \) 31 ... when != \( x = E1 \| from = E1 \)
29 to = \(kmalloc@p\|kzalloc@p\)(x,flag); 32 to = \(kmalloc@p\|kzalloc@p\)(x,flag);
30 33
31@@ 34@depends on patch@
32expression from,to,size,flag; 35expression from,to,size,flag;
33position p != {r1.p,r2.p}; 36position p != {r1.p,r2.p};
34statement S; 37statement S;
@@ -38,3 +41,26 @@ statement S;
38+ to = kmemdup(from,size,flag); 41+ to = kmemdup(from,size,flag);
39 if (to==NULL || ...) S 42 if (to==NULL || ...) S
40- memcpy(to, from, size); 43- memcpy(to, from, size);
44
45@r depends on !patch@
46expression from,to,size,flag;
47position p != {r1.p,r2.p};
48statement S;
49@@
50
51* to = \(kmalloc@p\|kzalloc@p\)(size,flag);
52 to = kmemdup(from,size,flag);
53 if (to==NULL || ...) S
54* memcpy(to, from, size);
55
56@script:python depends on org@
57p << r.p;
58@@
59
60coccilib.org.print_todo(p[0], "WARNING opportunity for kmemdep")
61
62@script:python depends on report@
63p << r.p;
64@@
65
66coccilib.report.print_report(p[0], "WARNING opportunity for kmemdep")
diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci
index 72ce012e878a..2efac289fd59 100644
--- a/scripts/coccinelle/api/memdup_user.cocci
+++ b/scripts/coccinelle/api/memdup_user.cocci
@@ -1,23 +1,25 @@
1/// Use kmemdup_user rather than duplicating its implementation 1/// Use memdup_user rather than duplicating its implementation
2/// This is a little bit restricted to reduce false positives 2/// This is a little bit restricted to reduce false positives
3/// 3///
4// Confidence: High 4// Confidence: High
5// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 5// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
6// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 6// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
7// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 7// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
8// URL: http://coccinelle.lip6.fr/ 8// URL: http://coccinelle.lip6.fr/
9// Comments: 9// Comments:
10// Options: -no_includes -include_headers 10// Options: -no_includes -include_headers
11 11
12virtual patch 12virtual patch
13virtual context
14virtual org
15virtual report
13 16
14@@ 17@depends on patch@
15expression from,to,size,flag; 18expression from,to,size,flag;
16position p;
17identifier l1,l2; 19identifier l1,l2;
18@@ 20@@
19 21
20- to = \(kmalloc@p\|kzalloc@p\)(size,flag); 22- to = \(kmalloc\|kzalloc\)(size,flag);
21+ to = memdup_user(from,size); 23+ to = memdup_user(from,size);
22 if ( 24 if (
23- to==NULL 25- to==NULL
@@ -33,3 +35,26 @@ identifier l1,l2;
33- -EFAULT 35- -EFAULT
34- ...+> 36- ...+>
35- } 37- }
38
39@r depends on !patch@
40expression from,to,size,flag;
41position p;
42statement S1,S2;
43@@
44
45* to = \(kmalloc@p\|kzalloc@p\)(size,flag);
46 if (to==NULL || ...) S1
47 if (copy_from_user(to, from, size) != 0)
48 S2
49
50@script:python depends on org@
51p << r.p;
52@@
53
54coccilib.org.print_todo(p[0], "WARNING opportunity for memdep_user")
55
56@script:python depends on report@
57p << r.p;
58@@
59
60coccilib.report.print_report(p[0], "WARNING opportunity for memdep_user")
diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci
new file mode 100644
index 000000000000..0a1e36146d76
--- /dev/null
+++ b/scripts/coccinelle/free/devm_free.cocci
@@ -0,0 +1,71 @@
1/// Find uses of standard freeing functons on values allocated using devm_
2/// functions. Values allocated using the devm_functions are freed when
3/// the device is detached, and thus the use of the standard freeing
4/// function would cause a double free.
5/// See Documentation/driver-model/devres.txt for more information.
6///
7/// A difficulty of detecting this problem is that the standard freeing
8/// function might be called from a different function than the one
9/// containing the allocation function. It is thus necessary to make the
10/// connection between the allocation function and the freeing function.
11/// Here this is done using the specific argument text, which is prone to
12/// false positives. There is no rule for the request_region and
13/// request_mem_region variants because this heuristic seems to be a bit
14/// less reliable in these cases.
15///
16// Confidence: Moderate
17// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. GPLv2.
18// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2.
19// URL: http://coccinelle.lip6.fr/
20// Comments:
21// Options: -no_includes -include_headers
22
23virtual org
24virtual report
25virtual context
26
27@r depends on context || org || report@
28expression x;
29@@
30
31(
32 x = devm_kzalloc(...)
33|
34 x = devm_request_irq(...)
35|
36 x = devm_ioremap(...)
37|
38 x = devm_ioremap_nocache(...)
39|
40 x = devm_ioport_map(...)
41)
42
43@pb@
44expression r.x;
45position p;
46@@
47
48(
49* kfree@p(x)
50|
51* free_irq@p(x)
52|
53* iounmap@p(x)
54|
55* ioport_unmap@p(x)
56)
57
58@script:python depends on org@
59p << pb.p;
60@@
61
62msg="WARNING: invalid free of devm_ allocated data"
63coccilib.org.print_todo(p[0], msg)
64
65@script:python depends on report@
66p << pb.p;
67@@
68
69msg="WARNING: invalid free of devm_ allocated data"
70coccilib.report.print_report(p[0], msg)
71
diff --git a/scripts/coccinelle/free/kfree.cocci b/scripts/coccinelle/free/kfree.cocci
index f9f79d9245ee..d9ae6d89c2f5 100644
--- a/scripts/coccinelle/free/kfree.cocci
+++ b/scripts/coccinelle/free/kfree.cocci
@@ -5,9 +5,9 @@
5//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument 5//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
6/// 6///
7// Confidence: Moderate 7// Confidence: Moderate
8// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 8// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
9// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 9// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
10// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 10// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
11// URL: http://coccinelle.lip6.fr/ 11// URL: http://coccinelle.lip6.fr/
12// Comments: 12// Comments:
13// Options: -no_includes -include_headers 13// Options: -no_includes -include_headers
@@ -23,7 +23,7 @@ position p1;
23kfree@p1(E) 23kfree@p1(E)
24 24
25@print expression@ 25@print expression@
26constant char *c; 26constant char [] c;
27expression free.E,E2; 27expression free.E,E2;
28type T; 28type T;
29position p; 29position p;
@@ -37,6 +37,10 @@ identifier f;
37| 37|
38 E@p != E2 38 E@p != E2
39| 39|
40 E2 == E@p
41|
42 E2 != E@p
43|
40 !E@p 44 !E@p
41| 45|
42 E@p || ... 46 E@p || ...
@@ -113,5 +117,5 @@ p1 << free.p1;
113p2 << r.p2; 117p2 << r.p2;
114@@ 118@@
115 119
116msg = "reference preceded by free on line %s" % (p1[0].line) 120msg = "ERROR: reference preceded by free on line %s" % (p1[0].line)
117coccilib.report.print_report(p2[0],msg) 121coccilib.report.print_report(p2[0],msg)
diff --git a/scripts/coccinelle/iterators/fen.cocci b/scripts/coccinelle/iterators/fen.cocci
index 77bc108c3f59..0a40af828c43 100644
--- a/scripts/coccinelle/iterators/fen.cocci
+++ b/scripts/coccinelle/iterators/fen.cocci
@@ -2,16 +2,19 @@
2/// is no point to call of_node_put on the final value. 2/// is no point to call of_node_put on the final value.
3/// 3///
4// Confidence: High 4// Confidence: High
5// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 5// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
6// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 6// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
7// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 7// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
8// URL: http://coccinelle.lip6.fr/ 8// URL: http://coccinelle.lip6.fr/
9// Comments: 9// Comments:
10// Options: -no_includes -include_headers 10// Options: -no_includes -include_headers
11 11
12virtual patch 12virtual patch
13virtual context
14virtual org
15virtual report
13 16
14@@ 17@depends on patch@
15iterator name for_each_node_by_name; 18iterator name for_each_node_by_name;
16expression np,E; 19expression np,E;
17identifier l; 20identifier l;
@@ -24,7 +27,7 @@ for_each_node_by_name(np,...) {
24... when != np = E 27... when != np = E
25- of_node_put(np); 28- of_node_put(np);
26 29
27@@ 30@depends on patch@
28iterator name for_each_node_by_type; 31iterator name for_each_node_by_type;
29expression np,E; 32expression np,E;
30identifier l; 33identifier l;
@@ -37,7 +40,7 @@ for_each_node_by_type(np,...) {
37... when != np = E 40... when != np = E
38- of_node_put(np); 41- of_node_put(np);
39 42
40@@ 43@depends on patch@
41iterator name for_each_compatible_node; 44iterator name for_each_compatible_node;
42expression np,E; 45expression np,E;
43identifier l; 46identifier l;
@@ -50,7 +53,7 @@ for_each_compatible_node(np,...) {
50... when != np = E 53... when != np = E
51- of_node_put(np); 54- of_node_put(np);
52 55
53@@ 56@depends on patch@
54iterator name for_each_matching_node; 57iterator name for_each_matching_node;
55expression np,E; 58expression np,E;
56identifier l; 59identifier l;
@@ -62,3 +65,59 @@ for_each_matching_node(np,...) {
62} 65}
63... when != np = E 66... when != np = E
64- of_node_put(np); 67- of_node_put(np);
68
69// ----------------------------------------------------------------------
70
71@r depends on !patch forall@
72//iterator name for_each_node_by_name;
73//iterator name for_each_node_by_type;
74//iterator name for_each_compatible_node;
75//iterator name for_each_matching_node;
76expression np,E;
77identifier l;
78position p1,p2;
79@@
80
81(
82*for_each_node_by_name@p1(np,...)
83{
84 ... when != break;
85 when != goto l;
86}
87|
88*for_each_node_by_type@p1(np,...)
89{
90 ... when != break;
91 when != goto l;
92}
93|
94*for_each_compatible_node@p1(np,...)
95{
96 ... when != break;
97 when != goto l;
98}
99|
100*for_each_matching_node@p1(np,...)
101{
102 ... when != break;
103 when != goto l;
104}
105)
106... when != np = E
107* of_node_put@p2(np);
108
109@script:python depends on org@
110p1 << r.p1;
111p2 << r.p2;
112@@
113
114cocci.print_main("unneeded of_node_put",p2)
115cocci.print_secs("iterator",p1)
116
117@script:python depends on report@
118p1 << r.p1;
119p2 << r.p2;
120@@
121
122msg = "ERROR: of_node_put not needed after iterator on line %s" % (p1[0].line)
123coccilib.report.print_report(p2[0], msg)
diff --git a/scripts/coccinelle/iterators/itnull.cocci b/scripts/coccinelle/iterators/itnull.cocci
index baa4297a4ed1..259899f6838e 100644
--- a/scripts/coccinelle/iterators/itnull.cocci
+++ b/scripts/coccinelle/iterators/itnull.cocci
@@ -1,20 +1,24 @@
1/// Many iterators have the property that the first argument is always bound 1/// Many iterators have the property that the first argument is always bound
2/// to a real list element, never NULL. False positives arise for some 2/// to a real list element, never NULL.
3/// iterators that do not have this property, or in cases when the loop 3//# False positives arise for some iterators that do not have this property,
4/// cursor is reassigned. The latter should only happen when the matched 4//# or in cases when the loop cursor is reassigned. The latter should only
5/// code is on the way to a loop exit (break, goto, or return). 5//# happen when the matched code is on the way to a loop exit (break, goto,
6//# or return).
6/// 7///
7// Confidence: Moderate 8// Confidence: Moderate
8// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 9// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
9// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 10// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
10// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 11// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
11// URL: http://coccinelle.lip6.fr/ 12// URL: http://coccinelle.lip6.fr/
12// Comments: 13// Comments:
13// Options: -no_includes -include_headers 14// Options: -no_includes -include_headers
14 15
15virtual patch 16virtual patch
17virtual context
18virtual org
19virtual report
16 20
17@@ 21@depends on patch@
18iterator I; 22iterator I;
19expression x,E,E1,E2; 23expression x,E,E1,E2;
20statement S,S1,S2; 24statement S,S1,S2;
@@ -55,4 +59,36 @@ I(x,...) { <...
55 x != NULL 59 x != NULL
56+ ) 60+ )
57) 61)
58 ...> } \ No newline at end of file 62 ...> }
63
64@r depends on !patch exists@
65iterator I;
66expression x,E;
67position p1,p2;
68@@
69
70*I@p1(x,...)
71{ ... when != x = E
72(
73* x@p2 == NULL
74|
75* x@p2 != NULL
76)
77 ... when any
78}
79
80@script:python depends on org@
81p1 << r.p1;
82p2 << r.p2;
83@@
84
85cocci.print_main("iterator-bound variable",p1)
86cocci.print_secs("useless NULL test",p2)
87
88@script:python depends on report@
89p1 << r.p1;
90p2 << r.p2;
91@@
92
93msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line)
94coccilib.report.print_report(p2[0], msg)
diff --git a/scripts/coccinelle/locks/call_kern.cocci b/scripts/coccinelle/locks/call_kern.cocci
index 00af5344a68f..8f10b49603c3 100644
--- a/scripts/coccinelle/locks/call_kern.cocci
+++ b/scripts/coccinelle/locks/call_kern.cocci
@@ -1,17 +1,20 @@
1/// Find functions that refer to GFP_KERNEL but are called with locks held. 1/// Find functions that refer to GFP_KERNEL but are called with locks held.
2/// The proposed change of converting the GFP_KERNEL is not necessarily the 2//# The proposed change of converting the GFP_KERNEL is not necessarily the
3/// correct one. It may be desired to unlock the lock, or to not call the 3//# correct one. It may be desired to unlock the lock, or to not call the
4/// function under the lock in the first place. 4//# function under the lock in the first place.
5/// 5///
6// Confidence: Moderate 6// Confidence: Moderate
7// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 7// Copyright: (C) 2012 Nicolas Palix. GPLv2.
8// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 8// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
9// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 9// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
10// URL: http://coccinelle.lip6.fr/ 10// URL: http://coccinelle.lip6.fr/
11// Comments: 11// Comments:
12// Options: -no_includes -include_headers 12// Options: -no_includes -include_headers
13 13
14virtual patch 14virtual patch
15virtual context
16virtual org
17virtual report
15 18
16@gfp exists@ 19@gfp exists@
17identifier fn; 20identifier fn;
@@ -32,28 +35,29 @@ fn(...) {
32 ... when any 35 ... when any
33} 36}
34 37
35@locked@ 38@locked exists@
36identifier gfp.fn; 39identifier gfp.fn;
40position p1,p2;
37@@ 41@@
38 42
39( 43(
40read_lock_irq 44read_lock_irq@p1
41| 45|
42write_lock_irq 46write_lock_irq@p1
43| 47|
44read_lock_irqsave 48read_lock_irqsave@p1
45| 49|
46write_lock_irqsave 50write_lock_irqsave@p1
47| 51|
48spin_lock 52spin_lock@p1
49| 53|
50spin_trylock 54spin_trylock@p1
51| 55|
52spin_lock_irq 56spin_lock_irq@p1
53| 57|
54spin_lock_irqsave 58spin_lock_irqsave@p1
55| 59|
56local_irq_disable 60local_irq_disable@p1
57) 61)
58 (...) 62 (...)
59... when != read_unlock_irq(...) 63... when != read_unlock_irq(...)
@@ -64,11 +68,38 @@ local_irq_disable
64 when != spin_unlock_irq(...) 68 when != spin_unlock_irq(...)
65 when != spin_unlock_irqrestore(...) 69 when != spin_unlock_irqrestore(...)
66 when != local_irq_enable(...) 70 when != local_irq_enable(...)
67fn(...) 71fn@p2(...)
68 72
69@depends on locked@ 73@depends on locked && patch@
70position gfp.p; 74position gfp.p;
71@@ 75@@
72 76
73- GFP_KERNEL@p 77- GFP_KERNEL@p
74+ GFP_ATOMIC 78+ GFP_ATOMIC
79
80@depends on locked && !patch@
81position gfp.p;
82@@
83
84* GFP_KERNEL@p
85
86@script:python depends on !patch && org@
87p << gfp.p;
88fn << gfp.fn;
89p1 << locked.p1;
90p2 << locked.p2;
91@@
92
93cocci.print_main("lock",p1)
94cocci.print_secs("call",p2)
95cocci.print_secs("GFP_KERNEL",p)
96
97@script:python depends on !patch && report@
98p << gfp.p;
99fn << gfp.fn;
100p1 << locked.p1;
101p2 << locked.p2;
102@@
103
104msg = "ERROR: function %s called on line %s inside lock on line %s but uses GFP_KERNEL" % (fn,p2[0].line,p1[0].line)
105coccilib.report.print_report(p[0], msg)
diff --git a/scripts/coccinelle/locks/flags.cocci b/scripts/coccinelle/locks/flags.cocci
index b4344d838097..1c4ffe6fd846 100644
--- a/scripts/coccinelle/locks/flags.cocci
+++ b/scripts/coccinelle/locks/flags.cocci
@@ -1,9 +1,9 @@
1/// Find nested lock+irqsave functions that use the same flags variables 1/// Find nested lock+irqsave functions that use the same flags variables
2/// 2///
3// Confidence: High 3// Confidence: High
4// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 4// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
5// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 5// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
6// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 6// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
7// URL: http://coccinelle.lip6.fr/ 7// URL: http://coccinelle.lip6.fr/
8// Comments: 8// Comments:
9// Options: -no_includes -include_headers 9// Options: -no_includes -include_headers
@@ -12,7 +12,7 @@ virtual context
12virtual org 12virtual org
13virtual report 13virtual report
14 14
15@r@ 15@r exists@
16expression lock1,lock2,flags; 16expression lock1,lock2,flags;
17position p1,p2; 17position p1,p2;
18@@ 18@@
@@ -39,7 +39,7 @@ read_lock_irqsave@p2(lock2,flags)
39write_lock_irqsave@p2(lock2,flags) 39write_lock_irqsave@p2(lock2,flags)
40) 40)
41 41
42@d@ 42@d exists@
43expression f <= r.flags; 43expression f <= r.flags;
44expression lock1,lock2,flags; 44expression lock1,lock2,flags;
45position r.p1, r.p2; 45position r.p1, r.p2;
@@ -76,5 +76,5 @@ p1 << r.p1;
76p2 << r.p2; 76p2 << r.p2;
77@@ 77@@
78 78
79msg="ERROR: nested lock+irqsave that reuses flags from %s." % (p1[0].line) 79msg="ERROR: nested lock+irqsave that reuses flags from line %s." % (p1[0].line)
80coccilib.report.print_report(p2[0], msg) 80coccilib.report.print_report(p2[0], msg)
diff --git a/scripts/coccinelle/locks/mini_lock.cocci b/scripts/coccinelle/locks/mini_lock.cocci
index 7641a2925434..3267d7410bd5 100644
--- a/scripts/coccinelle/locks/mini_lock.cocci
+++ b/scripts/coccinelle/locks/mini_lock.cocci
@@ -6,13 +6,14 @@
6/// function call that releases the lock. 6/// function call that releases the lock.
7/// 7///
8// Confidence: Moderate 8// Confidence: Moderate
9// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 9// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
10// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 10// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
11// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 11// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
12// URL: http://coccinelle.lip6.fr/ 12// URL: http://coccinelle.lip6.fr/
13// Comments: 13// Comments:
14// Options: -no_includes -include_headers 14// Options: -no_includes -include_headers
15 15
16virtual context
16virtual org 17virtual org
17virtual report 18virtual report
18 19
@@ -57,7 +58,7 @@ position r;
57 58
58for(...;...;...) { <+... return@r ...; ...+> } 59for(...;...;...) { <+... return@r ...; ...+> }
59 60
60@err@ 61@err exists@
61expression E1; 62expression E1;
62position prelocked.p; 63position prelocked.p;
63position up != prelocked.p1; 64position up != prelocked.p1;
@@ -65,14 +66,14 @@ position r!=looped.r;
65identifier lock,unlock; 66identifier lock,unlock;
66@@ 67@@
67 68
68lock(E1@p,...); 69*lock(E1@p,...);
69<+... when != E1 70<+... when != E1
70if (...) { 71if (...) {
71 ... when != E1 72 ... when != E1
72 return@r ...; 73* return@r ...;
73} 74}
74...+> 75...+>
75unlock@up(E1,...); 76*unlock@up(E1,...);
76 77
77@script:python depends on org@ 78@script:python depends on org@
78p << prelocked.p1; 79p << prelocked.p1;
diff --git a/scripts/coccinelle/misc/doubleinit.cocci b/scripts/coccinelle/misc/doubleinit.cocci
index 156b20adb351..cf74a00cf597 100644
--- a/scripts/coccinelle/misc/doubleinit.cocci
+++ b/scripts/coccinelle/misc/doubleinit.cocci
@@ -3,9 +3,9 @@
3/// initialization. 3/// initialization.
4/// 4///
5// Confidence: Low 5// Confidence: Low
6// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 6// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
7// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 7// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
8// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 8// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
9// URL: http://coccinelle.lip6.fr/ 9// URL: http://coccinelle.lip6.fr/
10// Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise 10// Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise
11// Options: -no_includes -include_headers 11// Options: -no_includes -include_headers
@@ -49,5 +49,5 @@ pr << r.p;
49@@ 49@@
50 50
51if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)): 51if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
52 msg = "%s: first occurrence %s, second occurrence %s" % (fld,ps[0].line,pr[0].line) 52 msg = "%s: first occurrence line %s, second occurrence line %s" % (fld,ps[0].line,pr[0].line)
53 coccilib.report.print_report(p0[0],msg) 53 coccilib.report.print_report(p0[0],msg)
diff --git a/scripts/coccinelle/null/eno.cocci b/scripts/coccinelle/null/eno.cocci
index 4c9c52b9c413..ed961a1f7d11 100644
--- a/scripts/coccinelle/null/eno.cocci
+++ b/scripts/coccinelle/null/eno.cocci
@@ -1,16 +1,19 @@
1/// The various basic memory allocation functions don't return ERR_PTR 1/// The various basic memory allocation functions don't return ERR_PTR
2/// 2///
3// Confidence: High 3// Confidence: High
4// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 4// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
5// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 5// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
6// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 6// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
7// URL: http://coccinelle.lip6.fr/ 7// URL: http://coccinelle.lip6.fr/
8// Comments: 8// Comments:
9// Options: -no_includes -include_headers 9// Options: -no_includes -include_headers
10 10
11virtual patch 11virtual patch
12virtual context
13virtual org
14virtual report
12 15
13@@ 16@depends on patch@
14expression x,E; 17expression x,E;
15@@ 18@@
16 19
@@ -18,3 +21,28 @@ x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache
18... when != x = E 21... when != x = E
19- IS_ERR(x) 22- IS_ERR(x)
20+ !x 23+ !x
24
25@r depends on !patch exists@
26expression x,E;
27position p1,p2;
28@@
29
30*x = \(kmalloc@p1\|kzalloc@p1\|kcalloc@p1\|kmem_cache_alloc@p1\|kmem_cache_zalloc@p1\|kmem_cache_alloc_node@p1\|kmalloc_node@p1\|kzalloc_node@p1\)(...)
31... when != x = E
32* IS_ERR@p2(x)
33
34@script:python depends on org@
35p1 << r.p1;
36p2 << r.p2;
37@@
38
39cocci.print_main("alloc call",p1)
40cocci.print_secs("IS_ERR that should be NULL tests",p2)
41
42@script:python depends on report@
43p1 << r.p1;
44p2 << r.p2;
45@@
46
47msg = "ERROR: allocation function on line %s returns NULL not ERR_PTR on failure" % (p1[0].line)
48coccilib.report.print_report(p2[0], msg)
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 38f6617a2cb1..833813a99e7c 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -132,7 +132,28 @@ exuberant()
132 --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ 132 --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \
133 --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ 133 --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \
134 --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ 134 --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \
135 --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' 135 --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \
136 --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \
137 --regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \
138 --regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \
139 --regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \
140 --regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \
141 --regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \
142 --regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \
143 --regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
144 --regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
145 --regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \
146 --regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \
147 --regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \
148 --regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \
149 --regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \
150 --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \
151 --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \
152 --regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \
153 --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \
154 --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
155 --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
156 --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/'
136 157
137 all_kconfigs | xargs $1 -a \ 158 all_kconfigs | xargs $1 -a \
138 --langdef=kconfig --language-force=kconfig \ 159 --langdef=kconfig --language-force=kconfig \
@@ -146,6 +167,8 @@ exuberant()
146 --langdef=dotconfig --language-force=dotconfig \ 167 --langdef=dotconfig --language-force=dotconfig \
147 --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/' 168 --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/'
148 169
170 # Remove structure forward declarations.
171 LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' tags
149} 172}
150 173
151emacs() 174emacs()
@@ -154,7 +177,28 @@ emacs()
154 --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \ 177 --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \
155 --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ 178 --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \
156 --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ 179 --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \
157 --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' 180 --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \
181 --regex='/PAGEFLAG\(([^,)]*).*/Page\1/' \
182 --regex='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \
183 --regex='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \
184 --regex='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \
185 --regex='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \
186 --regex='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \
187 --regex='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \
188 --regex='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
189 --regex='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \
190 --regex='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \
191 --regex='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \
192 --regex='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \
193 --regex='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \
194 --regex='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \
195 --regex='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \
196 --regex='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \
197 --regex='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \
198 --regex='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \
199 --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
200 --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
201 --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/'
158 202
159 all_kconfigs | xargs $1 -a \ 203 all_kconfigs | xargs $1 -a \
160 --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' 204 --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'