permit multiline comments and strings in macros
[bpt/coccinelle.git] / parsing_cocci / iso_compile.ml
CommitLineData
f537ebc4 1(*
17ba0788
C
2 * Copyright 2012, INRIA
3 * Julia Lawall, Gilles Muller
4 * Copyright 2010-2011, INRIA, University of Copenhagen
f537ebc4
C
5 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
6 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
7 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
8 * This file is part of Coccinelle.
9 *
10 * Coccinelle is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, according to version 2 of the License.
13 *
14 * Coccinelle is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * The authors reserve the right to distribute this or future versions of
23 * Coccinelle under other licenses.
24 *)
25
26
feec80c3 27# 0 "./iso_compile.ml"
34e49164 28module V0 = Visitor_ast0
b1b2de81 29module VT0 = Visitor_ast0_types
34e49164
C
30module Ast0 = Ast0_cocci
31module Ast = Ast_cocci
32
33(* Detects where position variables can be present in the match of an
17ba0788 34isomorphism. This is allowed if all elements of an isomorphism have only
34e49164
C
35one token or if we can somehow match up equal tokens of all of the
36isomorphic variants. *)
37
38let sequence_tokens =
39 let mcode x =
40 (* sort of unpleasant to convert the token representation to a string
41 but we can't make a list of mcodes otherwise because the types are all
42 different *)
abad11c5 43 [(Dumper.dump (Ast0.unwrap_mcode x),Ast0.get_pos_ref x)] in
34e49164
C
44 let donothing r k e = k e in
45 let bind x y = x @ y in
46 let option_default = [] in
b1b2de81 47 V0.flat_combiner bind option_default
34e49164 48 mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode mcode
34e49164 49 donothing donothing donothing donothing donothing donothing
755320b0 50 donothing donothing donothing
34e49164
C
51 donothing donothing donothing donothing donothing donothing donothing
52
53(* In general, we will get a list of lists:
54
55[[tokens1;tokens2;tokens3];[tokens4;tokens5;tokens6];[tokens7;tokens8]]
56
17ba0788 57If all of the lists of tokens contain only one element, we are done.
34e49164
C
58
59Otherwise, we focus on tokens1. For each of its elements, if they are
60present in all of the others, then a position is assigned, and if not then
61a position is not. The order of the elements in the other lists is
62irrelevant; we just take the first unannotated element that matches. Once
63we are done with the elements of tokens1, we skip to tokens 4 and repeat,
64including considering the one-element special case. *)
65
66let pctr = ref 0
67let get_p _ =
68 let c = !pctr in
69 pctr := c + 1;
70 let name = ("",Printf.sprintf "p%d" c) in
17ba0788
C
71 (* pos var just gives a name we can look up, used for historical reasons *)
72 Ast0.HiddenVarTag
73 ([Ast0.MetaPosTag(Ast0.MetaPos(Ast0.make_mcode name,[],Ast.PER))])
34e49164
C
74
75let process_info l =
17ba0788 76 let rec loop previously_used = function
34e49164
C
77 [] -> ()
78 | ((f::r)::xs) as a ->
17ba0788
C
79 let safe_add p pos =
80 (* don't add pos var where a pos var is already present *)
81 if Common.inter_set previously_used pos = [] then p::pos else pos in
82 let p =
83 if List.for_all (List.for_all (function e -> List.length e = 1)) a
84 then
85 let p = get_p() in
86 List.iter
87 (List.iter
88 (List.iter (function (_,pos) -> pos := safe_add p !pos)))
89 a;
90 [p]
91 else
92 let all = r @ List.concat xs in
93 let rec find_first_available a = function
94 [] -> raise Not_found
95 | (str,pos)::xs ->
96 if str = a && Common.inter_set previously_used !pos = []
97 then pos
98 else find_first_available a xs in
99 List.fold_left
100 (function prev ->
101 function (str,pos) ->
102 if Common.inter_set previously_used !pos = []
103 then
104 try
105 let entries = List.map (find_first_available str) all in
106 let p = get_p() in
107 pos := p::!pos;
108 List.iter (function pos -> pos := p :: !pos) entries;
109 p::prev
110 with Not_found -> prev
111 (* otherwise already annotated *)
112 else prev)
113 [] f in
114 loop (p@previously_used) xs
34e49164
C
115 | _ -> failwith "bad iso" in
116 loop l
117
118(* Entry point *)
119
120let process (metavars,alts,name) =
121 let toks =
b1b2de81 122 List.map (List.map sequence_tokens.VT0.combiner_rec_anything) alts in
17ba0788 123 process_info [] toks