let show_or_not_cocci a b =
Common.profile_code "show_xxx" (fun () -> show_or_not_cocci2 a b)
+(* ---------------------------------------------------------------------- *)
(* the output *)
-let show_or_not_diff2 cfile outfile show_only_minus =
+let fix_sgrep_diffs l =
+ let l =
+ List.filter (function s -> (s =~ "^\\+\\+\\+") || not (s =~ "^\\+")) l in
+ let l = List.rev l in
+ (* adjust second number for + code *)
+ let rec loop1 n = function
+ [] -> []
+ | s::ss ->
+ if s =~ "^-" && not(s =~ "^---")
+ then s :: loop1 (n+1) ss
+ else if s =~ "^@@"
+ then
+ (match Str.split (Str.regexp " ") s with
+ bef::min::pl::aft ->
+ (match Str.split (Str.regexp ",") pl with
+ [n1;n2] ->
+ let n2 = int_of_string n2 in
+ (Printf.sprintf "%s %s %s,%d %s" bef min n1 (n2-n)
+ (String.concat " " aft))
+ :: loop1 0 ss
+ | _ -> failwith "bad + line information")
+ | _ -> failwith "bad @@ information")
+ else s :: loop1 n ss in
+ let rec loop2 n = function
+ [] -> []
+ | s::ss ->
+ if s =~ "^---"
+ then s :: loop2 0 ss
+ else if s =~ "^@@"
+ then
+ (match Str.split (Str.regexp " ") s with
+ bef::min::pl::aft ->
+ (match (Str.split (Str.regexp ",") min,
+ Str.split (Str.regexp ",") pl) with
+ ([_;m2],[n1;n2]) ->
+ let n1 =
+ int_of_string
+ (String.sub n1 1 ((String.length n1)-1)) in
+ let m2 = int_of_string m2 in
+ let n2 = int_of_string n2 in
+ (Printf.sprintf "%s %s +%d,%d %s" bef min (n1-n) n2
+ (String.concat " " aft))
+ :: loop2 (n+(m2-n2)) ss
+ | _ -> failwith "bad -/+ line information")
+ | _ -> failwith "bad @@ information")
+ else s :: loop2 n ss in
+ loop2 0 (List.rev (loop1 0 l))
+
+let normalize_path file =
+ let fullpath =
+ if String.get file 0 = '/' then file else (Sys.getcwd()) ^ "/" ^ file in
+ let elements = Str.split_delim (Str.regexp "/") fullpath in
+ let rec loop prev = function
+ [] -> String.concat "/" (List.rev prev)
+ | "." :: rest -> loop prev rest
+ | ".." :: rest ->
+ (match prev with
+ x::xs -> loop xs rest
+ | _ -> failwith "bad path")
+ | x::rest -> loop (x::prev) rest in
+ loop [] elements
+
+let show_or_not_diff2 cfile outfile =
if !Flag_cocci.show_diff then begin
match Common.fst(Compare_c.compare_to_original cfile outfile) with
Compare_c.Correct -> () (* diff only in spacing, etc *)
match (!Flag.patch,res) with
(* create something that looks like the output of patch *)
(Some prefix,minus_file::plus_file::rest) ->
+ let prefix =
+ let lp = String.length prefix in
+ if String.get prefix (lp-1) = '/'
+ then String.sub prefix 0 (lp-1)
+ else prefix in
let drop_prefix file =
- if prefix =$= ""
- then "/"^file
- else
+ let file = normalize_path file in
+ if Str.string_match (Str.regexp prefix) file 0
+ then
let lp = String.length prefix in
- String.sub file lp ((String.length file) - lp) in
+ let lf = String.length file in
+ if lp < lf
+ then String.sub file lp (lf - lp)
+ else
+ failwith
+ (Printf.sprintf "prefix %s doesn't match file %s"
+ prefix file)
+ else
+ failwith
+ (Printf.sprintf "prefix %s doesn't match file %s"
+ prefix file) in
let diff_line =
match List.rev(Str.split (Str.regexp " ") line) with
new_file::old_file::cmdrev ->
| _ -> failwith "bad command" in
let (minus_line,plus_line) =
if !Flag.sgrep_mode2
- then (minus_file,plus_file)
+ then (minus_file,"+++ /tmp/nothing")
else
match (Str.split (Str.regexp "[ \t]") minus_file,
Str.split (Str.regexp "[ \t]") plus_file) with
(String.concat ":" l1) (String.concat ":" l2)) in
diff_line::minus_line::plus_line::rest
| _ -> res in
- xs +> List.iter (fun s ->
- if s =~ "^\\+" && show_only_minus
- then ()
- else pr s)
+ let xs = if !Flag.sgrep_mode2 then fix_sgrep_diffs xs else xs in
+ xs +> List.iter pr
end
-let show_or_not_diff a b c =
- Common.profile_code "show_xxx" (fun () -> show_or_not_diff2 a b c)
+let show_or_not_diff a b =
+ Common.profile_code "show_xxx" (fun () -> show_or_not_diff2 a b)
(* the derived input *)
* For the moment we base in part our heuristic on the name of the file, e.g.
* serio.c is related we think to #include <linux/serio.h>
*)
-
-let interpret_include_path _ =
- match !Flag_cocci.include_path with
- None -> "include"
- | Some x -> x
+let rec search_include_path searchlist relpath =
+ match searchlist with
+ [] -> Some relpath
+ | hd::tail ->
+ let file = Filename.concat hd relpath in
+ if Sys.file_exists file then
+ Some file
+ else
+ search_include_path tail relpath
+
+let interpret_include_path relpath =
+ let searchlist =
+ match !Flag_cocci.include_path with
+ [] -> ["include"]
+ | x -> List.rev x
+ in
+ search_include_path searchlist relpath
let (includes_to_parse:
(Common.filename * Parse_c.program2) list ->
{Ast_c.i_include = ((x,ii)); i_rel_pos = info_h_pos;}) ->
(match x with
| Ast_c.Local xs ->
- let f = Filename.concat dir (Common.join "/" xs) in
+ let relpath = Common.join "/" xs in
+ let f = Filename.concat dir (relpath) in
(* for our tests, all the files are flat in the current dir *)
if not (Sys.file_exists f) && !Flag_cocci.relax_include_path
then
let attempt2 = Filename.concat dir (Common.last xs) in
if not (Sys.file_exists f) && all_includes
- then Some (Filename.concat (interpret_include_path())
- (Common.join "/" xs))
+ then
+ interpret_include_path relpath
else Some attempt2
else Some f
| Ast_c.NonLocal xs ->
+ let relpath = Common.join "/" xs in
if all_includes ||
Common.fileprefix (Common.last xs) =$= Common.fileprefix file
then
- Some (Filename.concat (interpret_include_path())
- (Common.join "/" xs))
+ interpret_include_path relpath
else None
| Ast_c.Weird _ -> None
)
local_python_code ^
"cocci = Cocci()\n"
-let make_init rulenb lang code =
+let make_init rulenb lang deps code =
let mv = [] in
- let deps = Ast_cocci.NoDep in
- {
- scr_ast_rule = (lang, mv, code);
- language = lang;
- scr_dependencies = deps;
- scr_ruleid = rulenb;
- script_code = (if lang = "python" then python_code else "") ^code
- }
+ {
+ scr_ast_rule = (lang, mv, code);
+ language = lang;
+ scr_dependencies = deps;
+ scr_ruleid = rulenb;
+ script_code = (if lang = "python" then python_code else "") ^code
+}
(* --------------------------------------------------------------------- *)
let prepare_cocci ctls free_var_lists negated_pos_lists
script_code = code;
}
in ScriptRuleCocciInfo r
- | Ast_cocci.InitialScriptRule (lang,code) ->
- let r = make_init rulenb lang code in
+ | Ast_cocci.InitialScriptRule (lang,deps,code) ->
+ let r = make_init rulenb lang deps code in
InitialScriptRuleCocciInfo r
- | Ast_cocci.FinalScriptRule (lang,code) ->
+ | Ast_cocci.FinalScriptRule (lang,deps,code) ->
let mv = [] in
- let deps = Ast_cocci.NoDep in
let r =
{
scr_ast_rule = (lang, mv, code);
-
-
-
-
let prepare_c files choose_includes : file_info list =
let cprograms = List.map cprogram_of_file_cached files in
let includes = includes_to_parse (zip files cprograms) choose_includes in
let all =
(includes +> List.map (fun hpath -> Right hpath))
++
- ((zip files cprograms) +> List.map (fun (file, asts) -> Left (file, asts)))
+ ((zip files cprograms) +>
+ List.map (fun (file, asts) -> Left (file, asts)))
in
let env = ref !TAC.initial_env in
show_or_not_binding "in" e;
Pycocci.build_classes (List.map (function (x,y) -> x) ve);
Pycocci.construct_variables mv ve;
- let _ = Pycocci.pyrun_simplestring (local_python_code ^r.script_code) in
+ let _ =
+ Pycocci.pyrun_simplestring
+ (local_python_code ^r.script_code) in
relevant_bindings :: cache
end in
if !Pycocci.inc_match
adjust_pp_with_indent (fun () ->
Format.force_newline();
- Pretty_print_cocci.unparse(rebuild r.scr_ast_rule));
+ Pretty_print_cocci.unparse(rebuild r.scr_ast_rule r.scr_dependencies));
end;
match r.language with
"python" ->
(* include_match makes no sense in an initial or final rule, although
- er have no way to prevent it *)
+ we have no way to prevent it *)
let _ = apply_python_rule r [] [] [] [] (ref []) in
()
| _ ->
InitialScriptRuleCocciInfo(r) ->
(if List.mem r.language languages
then failwith ("double initializer found for "^r.language));
- initial_final_bigloop "initial"
- (function(x,_,y) -> Ast_cocci.InitialScriptRule(x,y))
- r;
- r.language::languages
+ if interpret_dependencies [] [] r.scr_dependencies
+ then
+ begin
+ initial_final_bigloop "initial"
+ (fun (x,_,y) -> fun deps ->
+ Ast_cocci.InitialScriptRule(x,deps,y))
+ r;
+ r.language::languages
+ end
+ else languages
| _ -> languages)
[] cocci_infos in
in
List.iter (fun lgg ->
initial_final_bigloop "initial"
- (function(x,_,y) -> Ast_cocci.InitialScriptRule(x,y))
- (make_init (-1) lgg "");
+ (fun (x,_,y) -> fun deps ->
+ Ast_cocci.InitialScriptRule(x,deps,y))
+ (make_init (-1) lgg Ast_cocci.NoDep "");
)
uninitialized_languages;
(* and now unparse everything *)
cfile_of_program (for_unparser c_or_h.asts) outfile;
- let show_only_minus = !Flag.sgrep_mode2 in
- show_or_not_diff c_or_h.fpath outfile show_only_minus;
+ show_or_not_diff c_or_h.fpath outfile;
(c_or_h.fpath,
if !Flag.sgrep_mode2 then None else Some outfile)
(if List.mem r.language languages
then failwith ("double finalizer found for "^r.language));
initial_final_bigloop "final"
- (function(x,_,y) -> Ast_cocci.FinalScriptRule(x,y))
+ (fun (x,_,y) -> fun deps -> Ast_cocci.FinalScriptRule(x,deps,y))
r;
r.language::languages
| _ -> languages)