aboutsummaryrefslogtreecommitdiff
path: root/ide/project_file.ml4
blob: ef39b904c65b334ce6b02ba8891e77654b2b5073 (plain)
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
type target =
  | ML of string (* ML file : foo.ml -> (ML "foo.ml") *)
  | MLI of string (* MLI file : foo.mli -> (MLI "foo.mli") *)
  | ML4 of string (* ML4 file : foo.ml4 -> (ML4 "foo.ml4") *)
  | MLLIB of string (* MLLIB file : foo.mllib -> (MLLIB "foo.mllib") *)
  | V of string  (* V file : foo.v -> (V "foo") *)
  | Arg of string
  | Special of string * string * string (* file, dependencies, command *)
  | Subdir of string
  | Def of string * string (* X=foo -> Def ("X","foo") *)
  | Include of string
  | RInclude of string * string (* -R physicalpath logicalpath *)


exception Parsing_error
let rec parse_string = parser
  | [< '' ' | '\n' | '\t' >] -> ""
  | [< 'c; s >] -> (String.make 1 c)^(parse_string s)
  | [< >] -> ""
and parse_string2 = parser
  | [< ''"' >] -> ""
  | [< 'c; s >] -> (String.make 1 c)^(parse_string2 s)
and parse_skip_comment = parser
  | [< ''\n'; s >] -> s
  | [< 'c; s >] -> parse_skip_comment s
  | [< >] -> [< >]
and parse_args = parser
  | [< '' ' | '\n' | '\t'; s >] -> parse_args s
  | [< ''#'; s >] -> parse_args (parse_skip_comment s)
  | [< ''"'; str = parse_string2; s >] -> ("" ^ str) :: parse_args s
  | [< 'c; str = parse_string; s >] -> ((String.make 1 c) ^ str) :: (parse_args s)
  | [< >] -> []


let parse f =
  let c = open_in f in
  let res = parse_args (Stream.of_channel c) in
    close_in c;
    res

let rec process_cmd_line ((project_file,makefile,install,opt) as opts) l = function
  | [] -> opts,List.rev l
  | ("-h"|"--help") :: _ ->
    raise Parsing_error
  | ("-no-opt"|"-byte") :: r ->
    process_cmd_line (project_file,makefile,install,false) l r
  | ("-full"|"-opt") :: r ->
    process_cmd_line (project_file,makefile,install,true) l r
  | "-impredicative-set" :: r ->
    prerr_string "Please now use \"-arg -impredicative-set\" instead of \"-impredicative-set\" alone to be more uniform.\n";
    process_cmd_line opts (Arg "-impredicative_set" :: l) r
  | "-no-install" :: r ->
    if not install then prerr_string "Warning: -no-install sets more than once.\n";
    process_cmd_line (project_file,makefile,false,opt) l r
  | "-custom" :: com :: dependencies :: file :: r ->
    process_cmd_line opts (Special (file,dependencies,com) :: l) r
  | "-I" :: d :: r ->
    process_cmd_line opts (Include d :: l) r
  | "-R" :: p :: lp :: r ->
    process_cmd_line opts (RInclude (p,lp) :: l) r
  | ("-I"|"-custom") :: _ ->
    raise Parsing_error
  | "-f" :: file :: r ->
    let () = match project_file with
      | None -> ()
      | Some _ -> prerr_string
	"Warning: Several features will not work with multiple project files.\n"
    in process_cmd_line (Some file,makefile,install,opt) l ((parse file)@r)
  | ["-f"] ->
    raise Parsing_error
  | "-o" :: file :: r ->
    let () = match makefile with
      |None -> ()
      |Some f ->
	prerr_string "Warning: Only one output file in genererated. ";
	prerr_string f; prerr_string " will not.\n"
    in process_cmd_line (project_file,Some file,install,opt) l r
  | v :: "=" :: def :: r ->
    process_cmd_line opts (Def (v,def) :: l) r
  | "-arg" :: a :: r ->
    process_cmd_line opts (Arg a :: l) r
  | f :: r ->
    process_cmd_line opts ((
      if Filename.check_suffix f ".v" then V f
      else if (Filename.check_suffix f ".ml") then ML f
      else if (Filename.check_suffix f ".ml4") then ML4 f
      else if (Filename.check_suffix f ".mli") then MLI f
      else if (Filename.check_suffix f ".mllib") then MLLIB f
      else Subdir f) :: l) r

let rec post_canonize f =
  if Filename.basename f = Filename.current_dir_name
  then let dir = Filename.dirname f in
    if dir = Filename.current_dir_name then f else post_canonize dir
  else f

(* Return: ((v,(mli,ml4,ml,mllib),special,subdir),(i_inc,r_inc),(args,defs)) *)
let rec split_arguments = function
  | V n :: r ->
      let (v,m,o,s),i,d = split_arguments r in ((Minilib.strip_path n::v,m,o,s),i,d)
  | ML n :: r ->
      let (v,(mli,ml4,ml,mllib),o,s),i,d = split_arguments r in ((v,(mli,ml4,Minilib.strip_path n::ml,mllib),o,s),i,d)
  | MLI n :: r ->
      let (v,(mli,ml4,ml,mllib),o,s),i,d = split_arguments r in ((v,(Minilib.strip_path n::mli,ml4,ml,mllib),o,s),i,d)
  | ML4 n :: r ->
      let (v,(mli,ml4,ml,mllib),o,s),i,d = split_arguments r in ((v,(mli,Minilib.strip_path n::ml4,ml,mllib),o,s),i,d)
  | MLLIB n :: r ->
      let (v,(mli,ml4,ml,mllib),o,s),i,d = split_arguments r in ((v,(mli,ml4,ml,Minilib.strip_path n::mllib),o,s),i,d)
  | Special (n,dep,c) :: r ->
      let (v,m,o,s),i,d = split_arguments r in ((v,m,(n,dep,c)::o,s),i,d)
  | Subdir n :: r ->
      let (v,m,o,s),i,d = split_arguments r in ((v,m,o,n::s),i,d)
  | Include p :: r ->
      let t,(i,r),d = split_arguments r in (t,((post_canonize p,Minilib.canonical_path_name p)::i,r),d)
  | RInclude (p,l) :: r ->
      let t,(i,r),d = split_arguments r in (t,(i,(post_canonize p,l,Minilib.canonical_path_name p)::r),d)
  | Def (v,def) :: r ->
      let t,i,(args,defs) = split_arguments r in (t,i,(args,(v,def)::defs))
  | Arg a :: r ->
      let t,i,(args,defs) = split_arguments r in (t,i,(a::args,defs))
  | [] -> ([],([],[],[],[]),[],[]),([],[]),([],[])