File: id_utils.ml

package info (click to toggle)
coccinelle 1.0.8.deb-5
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 26,148 kB
  • sloc: ml: 136,392; ansic: 23,594; sh: 2,189; makefile: 2,157; perl: 1,576; lisp: 840; python: 823; awk: 70; csh: 12
file content (79 lines) | stat: -rw-r--r-- 2,316 bytes parent folder | download
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
(*
 * 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
 *)

(* evaluation of nested and and or using id-utils *)

module GC = Get_constants2

let evaluated = Hashtbl.create(101)

exception Out

let memoize exp vl = Hashtbl.add evaluated exp vl; vl

let interpret_query index exp =
  let rec loop exp =
    let res = try Some (Hashtbl.find evaluated exp) with Not_found -> None in
    match res with
      Some x -> x
    | None ->
	memoize exp
	  (match exp with
	    GC.Elem oo ->
	      let cmd =
		Printf.sprintf "lid -f %s -l %s -S newline" index oo in
		  (* lid puts the matched word at the beginning of the first
		     line of the output... *)
	      (match Common.cmd_to_list cmd with
		[] -> []
	      | x::xs ->
		  (match Str.split (Str.regexp "[ \t]+") x with
		    [oop;file] when oo = oop -> file :: xs
		  | _ ->
		      failwith(Printf.sprintf "unexpected output of %s" cmd)))
	  | GC.And l ->
	      let rec iloop = function
		  [] -> failwith "bad and"
		| [x] -> loop x
		| x :: xs ->
		    (match loop x with
		      [] -> raise Out
		    | resx ->
			let resxs = iloop xs in
			Common.inter_set resx resxs) in
	      (try iloop l with Out -> [])
	  | GC.Or l ->
	      List.fold_left
		(function prev -> function cur ->
		  Common.union_set (loop cur) prev)
		[] l
	  | GC.Not _ -> failwith "unexpected not"
	  | GC.False -> failwith "unexpected false"
	  | GC.True -> failwith "unexpected true") in
  loop exp

let rec interpret dir query =
  let index =
    try
      if String.get !Flag_parsing_cocci.id_utils_index 0 = '/'
      then !Flag_parsing_cocci.id_utils_index
      else
	Printf.sprintf "%s/%s" dir !Flag_parsing_cocci.id_utils_index
    with Invalid_argument _ -> failwith "empty idutils index name" in
  let res =
    if not (Sys.file_exists index)
    then
      (Common.pr2
	 (Printf.sprintf
	    "index %s unavailable, run scripts/idutils_index.sh from %s"
	    !Flag_parsing_cocci.id_utils_index dir);
       None)
    else
      match query with
	None -> Common.pr2 "no inferred idutils keywords"; None
      | Some exp -> Some (interpret_query index exp) in
  Stdcompat.Hashtbl.reset evaluated;
  res