2 * Copyright (C) 2019 Richard W.M. Jones
3 * Copyright (C) 2019 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 (* See also "let id" in [lexer.mll]. *)
25 let var_regexp = Str.regexp "\\([a-zA-Z_][a-zA-Z0-9_]*\\)=\\(.*\\)"
29 goals: Build software.
31 goals [-f Goalfile] ['var=value' ...] ['target' ...]
33 For detailed help see goals(1).
38 (* Command line arguments. *)
39 let filename = ref "Goalfile" in
42 "-f", Arg.Set_string filename,
43 "filename Set name of Goalfile";
44 "--file", Arg.Set_string filename,
45 "filename Set name of Goalfile";
47 let argspec = Arg.align argspec in
49 let anon_fun s = args := s :: !args in
50 Arg.parse argspec anon_fun usage;
52 (*let args = List.rev !args in*)
53 let filename = !filename in
55 (* Parse the input file. *)
56 let file = Parse.parse_goalfile filename in
58 (* Parse the command line anon args. Each parameter has the
59 * form "name=<expr>" to assign a value to a variable, or
60 * "<expr>" to indicate a target to build.
62 let assignments = ref [] in
63 let targets = ref [] in
66 if Str.string_match var_regexp arg 0 then ( (* assignment *)
67 let name = Str.matched_group 1 arg in
68 let expr = Parse.parse_cli_expr (Str.matched_group 2 arg) in
69 assignments := Ast.Let (name, expr) :: !assignments
72 let expr = Parse.parse_cli_expr arg in
73 targets := expr :: !targets
77 (* If no target was set on the command line, find
78 * the first goal in the file.
80 if !targets = [] then (
83 List.find (function Ast.Goal _ -> true | _ -> false) file in
85 | Ast.Goal (name, [], _, _, _) ->
86 targets := [Ast.ECall (name, [])]
87 | Ast.Goal (name, _, _, _, _) ->
88 failwithf "%s: first target ā%sā has parameters and so cannot be used as the default target"
92 (* Actually this is fine. If there are no goals we'll do nothing. *)
96 let targets = List.rev !targets in
98 (* Assignments are simply treated as statements added to the end of
99 * the file (so they override earlier assignments to the same variable,
102 let file = file @ List.rev !assignments in
104 (* We start with an empty symbol table. *)
105 let vars = Hashtbl.create 13 in
107 (* Evaluate the target expressions in turn. *)
108 Eval.evaluate file vars targets