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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
(* $Id: extract_args.ml 94 2006-06-09 11:02:22Z gerd $ *)
(* Runs ocamlc -help and extract the command-line signature *)
open Printf
let read_lines file =
let f = open_in file in
let lines = ref [] in
try
while true do
lines := input_line f :: !lines
done;
assert false
with
| End_of_file ->
close_in f;
List.rev !lines
| error ->
close_in f;
raise error
;;
let get_help cmd =
let temp_file =
Filename.temp_file "findlib" ".txt" in
let help_out =
try
let code =
Sys.command (sprintf "%s -help >%s"
cmd
(Filename.quote temp_file)) in
if code <> 0 then
raise Not_found; (* Assume command does not exist! *)
let lines = read_lines temp_file in
Sys.remove temp_file;
lines
with error ->
Sys.remove temp_file; raise error in
help_out
;;
let switch_re = Str.regexp "[ \t]*\\(-[-a-zA-Z0-9_]*\\)[ \t]\\(.*\\)$";;
let argument_re = Str.regexp "[ \t]*[<[]";;
let rec extract_signature lines =
match lines with
| [] ->
[]
| line :: lines' ->
if Str.string_match switch_re line 0 then (
let switch_name = Str.matched_group 1 line in
let help_text = Str.matched_group 2 line in
let has_arg = Str.string_match argument_re help_text 0 in
let help_lines, lines'' = extract_help_continuation lines' in
let help_text' = String.concat "\n" (help_text :: help_lines) in
let r =
(switch_name, has_arg, help_text') in
r :: extract_signature lines''
)
else
extract_signature lines'
and extract_help_continuation lines =
match lines with
| [] ->
( [], [] )
| line :: lines' ->
if Str.string_match switch_re line 0 then
( [], lines )
else
let help_lines, lines'' = extract_help_continuation lines' in
(line :: help_lines, lines'')
;;
let rm_help_switch switches =
List.filter
(fun (name, _, _) ->
name <> "-help" && name <> "--help")
switches
;;
let output_some_signature f name switches =
fprintf f "let %s_spec = Some [\n" name;
List.iter
(fun (switch_name, has_arg, help_text) ->
fprintf f " \"%s\",\n" (String.escaped switch_name);
fprintf f " %b,\n" has_arg;
fprintf f " \"%s\";\n\n" (String.escaped help_text)
)
switches;
fprintf f "];;\n\n"
;;
let output_none f name =
fprintf f "let %s_spec = None;;\n\n" name
;;
let main() =
let f = ref stdout in
let progs = ref [] in
Arg.parse
[ "-o", Arg.String (fun s -> f := open_out s),
"<file> Save generated module to this file";
]
(fun arg -> progs := arg :: !progs)
"usage: extract_args <options> <command> ...";
progs := List.rev !progs;
List.iter
(fun prog ->
try
let help_lines = get_help prog in (* or Not_found *)
let switches = rm_help_switch (extract_signature help_lines) in
output_some_signature !f prog switches
with
Not_found ->
output_none !f prog
)
!progs;
close_out !f
;;
main();;
|