forked from ocaml/opam-repository
-
Notifications
You must be signed in to change notification settings - Fork 0
/
opam.ml
97 lines (84 loc) · 2.61 KB
/
opam.ml
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
95
96
97
module type COMMAND = sig
val s_title : string
val main : string list -> unit
end
module type SED = sig
include COMMAND
val s_add_expr_no_pos : string
val s_add_expr : string
end
module Sed : SED = struct
module List = struct
include List
let mapi f l =
List.rev (snd (List.fold_left (fun (n, l) x -> succ n, f n x :: l) (0, []) l))
let map f = mapi (fun _ -> f)
end
let read file =
let ic = open_in_bin file in
let rec aux l =
match try Some (input_line ic) with _ -> None with
| None -> l
| Some s -> aux (s :: l) in
let l = aux [] in
let () = close_in ic in
List.rev l
let write file contents =
let oc = open_out_bin file in
begin
List.iter (fun s -> output_string oc (s ^ "\n")) contents;
close_out oc;
end
let apply f file =
write file (f (read file))
let sed l_sed =
apply
(fun file ->
List.fold_left
(fun file -> function
| Some pos, s1, s2 ->
let reg1 = Str.regexp_string s1 in
let rec aux rev_file n = function
| [] -> assert false
| x :: xs ->
if n = pos then
List.fold_left (fun l x -> x :: l) ((Str.global_replace reg1 s2 x) :: xs) rev_file
else
aux (x :: rev_file) (succ n) xs in
aux [] 1 file
| None, s1, s2 ->
let reg1 = Str.regexp_string s1 in
List.map (Str.global_replace reg1 s2) file)
file
l_sed)
let repl_tbl =
Str.global_replace (Str.regexp_string "\\t") "\t"
(* NOTE "\x.." should be replaced too *)
let s_add_expr = "_add_expr_"
let s_add_expr_no_pos = "_add_expr_no_pos_"
let s_title = "sed"
let main l =
let rec aux l = function
| cmd :: n :: s1 :: s2 :: xs when cmd = s_add_expr ->
aux ((Some (int_of_string n), repl_tbl s1, repl_tbl s2) :: l) xs
| cmd :: s1 :: s2 :: xs when cmd = s_add_expr_no_pos -> aux ((None, repl_tbl s1, repl_tbl s2) :: l) xs
| [fic] -> List.rev l, fic
| _ -> assert false in
let l, fic = aux [] l in
sed l fic
end
let ocaml s = [ "ocaml" ; "str.cma" ; "unix.cma" ; s ]
let s_opam = "opam.ml"
let s_main = "main"
let main () =
match Array.to_list Sys.argv with
| _ :: cmd_main :: l ->
snd
(List.find
(function s_title, _ -> cmd_main = s_title)
(List.map
(fun m -> let module M = (val m : COMMAND) in M.s_title, M.main)
[ (module Sed : COMMAND) ]))
l
| _ -> assert false
let _ = main ()