File: extract_args.ml

package info (click to toggle)
findlib 1.2.5%2Bdebian-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 1,496 kB
  • ctags: 678
  • sloc: ml: 4,661; xml: 2,445; sh: 1,322; makefile: 306
file content (136 lines) | stat: -rw-r--r-- 2,977 bytes parent folder | download | duplicates (2)
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();;