~npalix/coccinelle/upstream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
(*
 * This file is part of Coccinelle, licensed under the terms of the GPL v2.
 * See copyright.txt in the Coccinelle source code for more information.
 * The Coccinelle source code can be obtained at http://coccinelle.lip6.fr
 *)

module Ast0 = Ast0_cocci
module Ast = Ast_cocci
module V0 = Visitor_ast0
module VT0 = Visitor_ast0_types

(* Negate counter of open brace when that is minus and preceding ) is context.
   In that case, the brace should somehow be like the preceding ) (from an
   if, while, etc) rather than like the rest of the statement. *)
let redo (_,_,_,mc,_,_) stm =
  match mc with
    Ast0.CONTEXT _ ->
      (match Ast0.unwrap stm with
	Ast0.Seq((a,b,c,mc_lbrace,d,adj),body,rbrace) ->
	  (match mc_lbrace with
	    Ast0.MINUS _ ->
	      (* subtract 1 in case -1 is used for some unknown values *)
	      let adj = { adj with Ast.counter = -1 * adj.Ast.counter - 1 } in
	      Ast0.rewrap stm (Ast0.Seq((a,b,c,mc_lbrace,d,adj),body,rbrace))
	  | _ -> stm)
      |	_ -> stm)
  | _ -> stm

let compute_adjacency p =
  let prev = ref { Ast.counter = 0; Ast.ender = false } in
  let counter = ref 0 in
  let get_adj _ =
    let adj = { Ast.counter = !counter; Ast.ender = false } in
    prev := adj;
    adj in
  let mcode (a,b,c,d,e,_) = (a,b,c,d,e,get_adj()) in
  let string_mcode ((str,_,info,mc,_,_) as x) =
    match str with
      "..." | "<..." | "...>" | "<+..." | "...+>" ->
	(!prev).Ast.ender <- true;
	(match mc with
	  Ast0.MINUS _ -> mcode x
	| Ast0.CONTEXT _ -> counter := !counter + 1; x
	| _ -> failwith "unexpected mcode for ...")
    | _ -> mcode x in
  let statement r k s =
    let s = k s in
    (* a case for each kind of term that has a fake node *)
    Ast0.rewrap s
      (match Ast0.unwrap s with
	Ast0.IfThen(iff,lp,exp,rp,branch,(info,mc,_)) ->
	  let branch = redo rp branch in
	  Ast0.IfThen(iff,lp,exp,rp,branch,(info,mc,get_adj()))
      | Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,mc,_)) ->
	  let branch1 = redo rp branch1 in
	  let branch2 = redo els branch2 in
	  let adj = { Ast.counter = !counter; Ast.ender = false } in
	  prev := adj;
	  Ast0.IfThenElse(iff,lp,exp,rp,branch1,els,branch2,(info,mc,get_adj()))
      | Ast0.While(wh,lp,exp,rp,body,(info,mc,_)) ->
	  let body = redo rp body in
	  let adj = { Ast.counter = !counter; Ast.ender = false } in
	  prev := adj;
	  Ast0.While(wh,lp,exp,rp,body,(info,mc,get_adj()))
      | Ast0.For(fr,lp,first,rp,body,(info,mc,_)) ->
	  let body = redo rp body in
	  let adj = { Ast.counter = !counter; Ast.ender = false } in
	  prev := adj;
	  Ast0.For(fr,lp,first,rp,body,(info,mc,get_adj()))
      | Ast0.Iterator(nm,lp,args,rp,body,(info,mc,_)) ->
	  let body = redo rp body in
	  let adj = { Ast.counter = !counter; Ast.ender = false } in
	  prev := adj;
	  Ast0.Iterator(nm,lp,args,rp,body,(info,mc,get_adj()))
      | s -> s) in
  let fn =
    V0.rebuilder
      {V0.rebuilder_functions with
	VT0.rebuilder_meta_mcode = mcode;
	VT0.rebuilder_string_mcode = string_mcode;
	VT0.rebuilder_const_mcode = mcode;
	VT0.rebuilder_simpleAssign_mcode = mcode;
	VT0.rebuilder_opAssign_mcode = mcode;
	VT0.rebuilder_fix_mcode = mcode;
	VT0.rebuilder_unary_mcode = mcode;
	VT0.rebuilder_arithOp_mcode = mcode;
	VT0.rebuilder_logicalOp_mcode = mcode;
	VT0.rebuilder_cv_mcode = mcode;
	VT0.rebuilder_sign_mcode = mcode;
	VT0.rebuilder_struct_mcode = mcode;
	VT0.rebuilder_storage_mcode = mcode;
	VT0.rebuilder_inc_mcode = mcode;
	VT0.rebuilder_stmtfn = statement;} in
  List.map fn.VT0.rebuilder_rec_top_level p