Release coccinelle-0.1.3
[bpt/coccinelle.git] / parsing_cocci / simple_assignments.ml
CommitLineData
34e49164
C
1(*
2* Copyright 2005-2008, 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
23module Ast0 = Ast0_cocci
24module Ast = Ast_cocci
25module V0 = Visitor_ast0
26
27(* find assignments that can match an initialization *)
28
29let pure_mcodekind = function
30 Ast0.CONTEXT(mc) ->
31 (match !mc with
32 (Ast.NOTHING,_,_) -> true
33 | _ -> false)
34 | _ -> false
35
36let is_simple_assign left op =
37 (match Ast0.unwrap left with
38 Ast0.Ident(_) | Ast0.MetaExpr(_,_,_,_,_) -> true
39 | _ -> false)
40 &&
41 ((Ast0.unwrap_mcode op) = Ast.SimpleAssign)
42
43let is_simple_ast_assign left op minus_left =
44 (match Ast.unwrap left with
45 Ast.Ident(_) -> true
46 | Ast.MetaExpr(name,_,_,_,_,_) ->
47 (match Ast0.unwrap minus_left with
48 Ast0.MetaExpr(name1,_,_,_,_) ->
49 Ast.unwrap_mcode name = Ast0.unwrap_mcode name1
50 | _ -> false)
51 | _ -> false)
52 &&
53 ((Ast.unwrap_mcode op) = Ast.SimpleAssign)
54
55let warning e msg =
56 Common.pr2
57 ("the simple assignment expression on line "^
58 (string_of_int (Ast0.get_line e))^
59 " contains transformations\n"^
60 "that prevent it from matching a declaration ("^msg^")\n");
61 e
62
63let rebuild e1 left right op simple =
64 Ast0.rewrap e1 (Ast0.Assignment(left,op,right,simple))
65
66let rec exp mc e1 =
67 match Ast0.unwrap e1 with
68 Ast0.Assignment(left,op,right,_) ->
69 if is_simple_assign left op
70 then
71 (if !Flag.sgrep_mode2
72 then rebuild e1 left right op true
73 else
74 match mc with
75 Ast0.MINUS(mc) ->
76 (match !mc with
77 ([[Ast.ExpressionTag(e2)]],_) ->
78 (match Ast.unwrap e2 with
79 Ast.Assignment(left',op',_,_) ->
80 if is_simple_ast_assign left' op' left
81 then rebuild e1 left right op true
82 else warning e1 "replacement is not simple"
83 | _ -> warning e1 "replacement is not an assignment")
84 | _ -> warning e1 "multiple replacements")
85 | m ->
86 let pure =
87 (pure_mcodekind m) &&
88 (pure_mcodekind (Ast0.get_mcodekind left)) &&
89 (pure_mcodekind (Ast0.get_mcode_mcodekind op)) in
90 if not pure
91 then warning e1 "not pure"
92 else rebuild e1 left right op pure)
93 else e1
94 | Ast0.DisjExpr(lp,exps,mids,rp) ->
95 Ast0.rewrap e1
96 (Ast0.DisjExpr
97 (lp,List.map (function x -> exp (Ast0.get_mcodekind x) x) exps,
98 mids,rp))
99 | Ast0.OptExp(e) ->
100 Ast0.rewrap e1 (Ast0.OptExp(exp (Ast0.get_mcodekind e) e))
101 | Ast0.UniqueExp(e) ->
102 Ast0.rewrap e1 (Ast0.UniqueExp(exp (Ast0.get_mcodekind e) e))
103 | _ -> e1
104
105let simple_assignments l =
106 let mcode x = x in
107 let donothing r k e = k e in
108 let statement r k e =
109 match Ast0.unwrap e with
110 Ast0.Exp(e1) -> Ast0.rewrap e (Ast0.Exp(exp (Ast0.get_mcodekind e) e1))
111 | _ -> k e in
112 let fn =
113 V0.rebuilder
114 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
115 mcode
116 donothing donothing donothing donothing donothing donothing
117 donothing donothing donothing donothing donothing donothing statement
118 donothing donothing in
119 List.map fn.V0.rebuilder_top_level l