Release coccinelle-0.1.6
[bpt/coccinelle.git] / engine / .#lib_matcher_c.ml.1.1
1 (*
2 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller
4 * This file is part of Coccinelle.
5 *
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
9 *
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
20 *)
21
22
23 open Common
24
25 (*****************************************************************************)
26 (* Types *)
27 (*****************************************************************************)
28
29 type protocol_match =
30 | MatchPos of Ograph_extended.nodei
31 | MatchNeg of Ograph_extended.nodei
32 | NoMatch
33 (* could generate exn instead, but in many cases as for my acomment gui
34 * I still want to print the match for the other elements, so one failure
35 * should not stop everything
36 *)
37 | MatchProblem of string
38
39
40 (*****************************************************************************)
41 (* Helpers *)
42 (*****************************************************************************)
43
44 (*****************************************************************************)
45 (* Specific finder wrappers *)
46 (*****************************************************************************)
47 let (find_nodes_satisfying_pattern:
48 Control_flow_c.cflow -> Ast_cocci.rule_elem -> Ograph_extended.nodei list)=
49 fun flow pattern ->
50
51 let nodes = flow#nodes in
52 let nodes = nodes#tolist in
53 nodes +> Common.map_filter (fun (nodei, node) ->
54 let res =
55 Pattern_c.match_re_node [] (* dropped isos *)
56 pattern node
57 []
58 in
59 if List.length res > 0
60 then Some nodei
61 else None
62 )
63
64
65 let (find_nodes_containing_expr:
66 Control_flow_c.cflow -> Ast_c.expression -> Ograph_extended.nodei list)=
67 fun flow expr ->
68
69 let expr = Lib_parsing_c.real_al_expr expr in
70
71 let nodes = flow#nodes in
72 let nodes = nodes#tolist in
73 nodes +> Common.map_filter (fun (nodei, node) ->
74 let node = Lib_parsing_c.real_al_node node in
75
76 let found = ref false in
77
78 Visitor_c.vk_node { Visitor_c.default_visitor_c with
79 Visitor_c.kexpr = (fun (k, bigf) e2 ->
80 if e2 =*= expr
81 then found := true
82 else k e2
83 );
84 } node;
85
86 if !found
87 then Some nodei
88 else None
89 )
90
91
92
93 (*****************************************************************************)
94 (* Main entries *)
95 (*****************************************************************************)
96
97 (*
98 *
99 * todo: Check for all path upwards ?
100 *)
101
102 let (find_nodes_upward_satisfying_protocol:
103 Ograph_extended.nodei -> Control_flow_c.cflow ->
104 Ast_cocci.rule_elem * Ast_cocci.rule_elem ->
105 protocol_match
106 ) =
107 fun nodei flow (pattern1, pattern2) ->
108
109 let already_done = ref [nodei] in
110 let found = ref [] in
111
112 let rec aux nodei =
113 let pred =
114 List.map fst ((flow#predecessors nodei)#tolist)
115 in
116 pred +> List.iter (fun nodei2 ->
117 if List.mem nodei2 !already_done
118 then ()
119 else begin
120 Common.push2 nodei2 already_done;
121
122 let node2 = flow#nodes#assoc nodei2 in
123
124 let res1 =
125 Pattern_c.match_re_node []
126 pattern1 node2
127 []
128 in
129 let res2 =
130 Pattern_c.match_re_node []
131 pattern2 node2
132 []
133 in
134 match List.length res1 > 0, List.length res2 > 0 with
135 | true, false ->
136 Common.push2 (MatchPos nodei2) found
137 | false, true ->
138 Common.push2 (MatchNeg nodei2) found
139 | true, true ->
140 failwith "wierd, node match both rule_elem"
141 | false, false ->
142 aux nodei2
143 end
144 );
145 in
146 aux nodei;
147 (match !found with
148 | [] -> NoMatch
149 | [x] -> x
150 | x::y::ys ->
151 failwith "multiple found";
152 )
153
154
155
156