1#if !defined(_DEFAULT_SOURCE)
2#define _DEFAULT_SOURCE
3#endif
4#if !defined(_POSIX_C_SOURCE)
5#define _POSIX_C_SOURCE 200809L
6#endif
7
8#include <sys/types.h>
9
10#include "arg.h"
11#include "util.h"
12
13/* grow a struct-array when full, n/cap doubles each time */
14#define GROW(arr, n, cap, init) \
15 do { \
16 if ((n) >= (cap)) { \
17 (cap) = (cap) ? (cap) * 2 : (init); \
18 (arr) = erealloc((arr), (size_t)(cap) * sizeof *(arr)); \
19 } \
20 } while (0)
21
22struct StrList {
23 char **v;
24 int n;
25 int cap;
26};
27
28void sl_push(struct StrList *sl, const char *s);
29int sl_has(struct StrList *sl, const char *s);
30void sl_split(struct StrList *sl, const char *s);
31char *sl_join(struct StrList *sl);
32char **sl_argv(struct StrList *sl);
33const char *base_of(const char *path);
34void child_execvp(char **av) __attribute__((noreturn));
35
36struct Kv {
37 char *key;
38 char *val;
39};
40
41struct KvStore {
42 struct Kv *v;
43 int n, cap;
44};
45
46struct Map {
47 char name[128];
48 struct KvStore entries;
49};
50
51char *kv_get(const char *key);
52const char *kv_get_or(const char *key, const char *def);
53void kv_set(const char *key, const char *val);
54void kv_set_manifest(const char *key, const char *val);
55void kv_set_cli(const char *key, const char *val);
56char *kv_expand(const char *s);
57char *kv_get_raw(struct KvStore *s, const char *key);
58void kv_set_raw(struct KvStore *s, const char *key, const char *val);
59struct Map *map_find(const char *name);
60struct Map *map_new(const char *name);
61
62extern struct KvStore kv;
63extern struct KvStore *local_overlay;
64extern struct StrList kv_locked;
65extern struct Map *maps;
66extern int nmaps, mapscap;
67
68enum SKind { S_ATOM, S_LIST };
69
70struct SNode {
71 enum SKind kind;
72 char *atom;
73 struct SNode **kids;
74 int nkids;
75 int line;
76};
77
78struct SLex {
79 const char *src;
80 size_t pos;
81 int line;
82};
83
84struct SNode *snode_atom(const char *s, int line);
85struct SNode *snode_list(int line);
86void snode_push(struct SNode *list, struct SNode *kid);
87void snode_free(struct SNode *n);
88struct SNode *snode_clone(struct SNode *n);
89struct SNode *snode_parse(struct SLex *lx);
90int s_is_list(struct SNode *n);
91const char *s_head(struct SNode *n);
92char *subst_tmpl(const char *s, struct StrList *params, char **vals);
93void snode_subst(struct SNode *n, struct StrList *params, char **vals);
94void lex_swallow_dollar(struct SLex *lx, char *buf, size_t *blen, size_t bsz);
95void lex_string(struct SLex *lx, char *buf, size_t bsz);
96const char *find_dollar_close(const char *inner);
97
98/* gate: (not X) | (and X...) | (or X...) | bare var */
99enum GKind { G_TRUE, G_VAR, G_NOT, G_AND, G_OR };
100
101struct Gate {
102 enum GKind kind;
103 char *var;
104 struct Gate **kids;
105 int nkids;
106};
107
108struct Gate *gate_new(enum GKind kind);
109void gate_free(struct Gate *g);
110struct Gate *gate_parse(struct SNode *expr);
111int gate_has_dyn(struct Gate *g);
112int gate_eval(struct Gate *g);
113struct Gate *gate_materialize(struct Gate *g);
114
115struct Cmd {
116 struct StrList argv;
117 int is_pipe;
118 struct StrList **stages;
119 int nstages;
120};
121
122struct Rule {
123 char name[128];
124 struct StrList globs;
125 struct StrList skip;
126 char require_marker[1024];
127 char require_file[1024];
128 struct StrList in;
129 struct StrList extra_deps;
130 char out[1024];
131 struct Cmd cmd;
132 struct Gate *gate;
133 char workdir[1024];
134 int phony;
135 int redirect;
136 char produces[128];
137 char description[256];
138 char group_name[128];
139 char member_of[128];
140 char member_alias[128];
141 struct StrList features;
142
143 int *inst_idx;
144 int n_inst, cap_inst;
145 int expanded;
146};
147
148struct Group {
149 char name[128];
150 struct StrList refs;
151};
152
153struct Meta {
154 char name[128];
155 struct StrList keys;
156 struct StrList vals;
157};
158
159struct Template {
160 char name[128];
161 struct StrList params;
162 struct SNode *body;
163};
164
165struct Rule *rule_find(const char *name);
166struct Rule *rule_find_output(const char *path);
167struct Rule *rule_find_produces(const char *name);
168struct Rule *rule_new(const char *name);
169struct Group *group_find(const char *name);
170struct Group *group_new(const char *name);
171struct Meta *meta_find(const char *name);
172struct Meta *meta_new(const char *name);
173struct Template *template_find(const char *name);
174struct Template *template_new(const char *name);
175
176extern struct Rule *rules;
177extern int nrules, rulescap;
178extern struct Group *groups;
179extern int ngroups, groupscap;
180extern struct Meta *metas;
181extern int nmetas, metascap;
182extern struct Template *templates;
183extern int ntemplates, templatescap;
184
185struct Inst {
186 int rule_idx;
187 struct StrList in;
188 struct StrList stale_extra;
189 char out[1024];
190 struct Cmd cmd;
191 char workdir[1024];
192 int phony;
193 int redirect;
194
195 struct StrList dep_rule_names;
196 int *dep_inst;
197 int n_dep, cap_dep;
198 int will_build;
199};
200
201int inst_new(int rule_idx);
202int inst_stale(struct Inst *inst);
203void dep_push(struct Inst *inst, int idx);
204void resolve_deps(void);
205
206extern struct Inst *insts;
207extern int ninsts, instscap;
208
209long mtime_of(const char *path);
210int file_exists(const char *path);
211int file_contains(const char *path, const char *needle);
212void glob_expand(const char *pattern, struct StrList *out);
213void glob_all(struct Rule *r, struct StrList *out);
214int is_wildcard_pattern(const char *pattern);
215int rule_is_literal(struct Rule *r);
216int path_claimed_elsewhere(const char *path, struct Rule *self);
217void splitext(const char *base, char *stem, size_t stemsz, char *ext, size_t extsz);
218void to_ident(const char *s, char *out, size_t outsz);
219
220pid_t spawn_inst(struct Inst *inst, struct StrList *argv);
221pid_t spawn_pipe(struct Inst *inst);
222void mk_out_dir(const char *out);
223void announce_inst(struct Inst *inst);
224void run_inst_sync(int idx);
225void run_batch(int *idxs, int n);
226void run_inst_with_deps(int idx);
227void materialize_if_missing(const char *path);
228char *capture_argv(struct StrList *argv);
229
230extern int jobs_n;
231extern int summary_mode;
232extern int failed_any;
233
234void load_file(const char *path);
235void load_manifest(struct SNode *root);
236void dispatch_top_form(struct SNode *form);
237void parse_exec_clause(struct SNode *clause, struct Cmd *cmd);
238void parse_shell_clause(struct SNode *clause, struct Cmd *cmd);
239void parse_pipe_clause(struct SNode *clause, struct Cmd *cmd);
240void meta_apply(struct Meta *m);
241const char *first_atom(struct SNode *node, const char *msg);
242const char *sole_atom(struct SNode *node, const char *msg);
243
244extern struct StrList files_read;
245
246void expand_rule(const char *name);
247
248void schedule_and_run(void);
249void emit_ninja(const char *path, struct StrList *wanted);
250
251struct Backend {
252 const char *name;
253 const char *try_key;
254 const char *file;
255 void (*emit)(const char *path, struct StrList *wanted);
256};
257
258const struct Backend *backend_by_name(const char *name);
259const struct Backend *backend_resolve(char **bin);
260void backend_exec(const struct Backend *be, const char *bin, struct StrList *wanted)
261 __attribute__((noreturn));
262
263void do_features(void);
264void do_query(const char *sub, const char *arg);
265
266void include_ref(const char *name);
267void build_default_group(void);
268void resolve_wanted(const char *w);
269void resolve_all_bareword_deps(void);