1#include "ninqu.h"
2#include "wexec.h"
3
4#include <ctype.h>
5#include <limits.h>
6#include <string.h>
7
8/* one entry per generator format. adding a backend means writing its
9 * own emit fn elsewhere and adding a row here, nothing else in ninqu
10 * needs to change */
11static const struct Backend backends[] = {
12 {"ninja", "NINJA_TRY", "build.ninja", emit_ninja},
13};
14#define NBACKENDS (int)(sizeof backends / sizeof backends[0])
15
16const struct Backend *
17backend_by_name(const char *name)
18{
19 int i;
20
21 for (i = 0; i < NBACKENDS; i++)
22 if (strcmp(backends[i].name, name) == 0)
23 return &backends[i];
24 return NULL;
25}
26
27/* try_key is a comma list of binary names, tried in order, first
28 * one found on PATH wins. bin is set to that binarys own path */
29const struct Backend *
30backend_resolve(char **bin)
31{
32 int i;
33
34 for (i = 0; i < NBACKENDS; i++) {
35 const char *p = kv_get_or(backends[i].try_key, "");
36
37 while (*p) {
38 char name[PATH_MAX];
39 const char *start;
40 char *found;
41 size_t len;
42
43 while (*p == ',' || isspace((unsigned char)*p))
44 p++;
45 start = p;
46 while (*p && *p != ',')
47 p++;
48 len = (size_t)(p - start);
49 while (len && isspace((unsigned char)start[len - 1]))
50 len--;
51 if (len && len < sizeof name) {
52 memcpy(name, start, len);
53 name[len] = '\0';
54 found = wwhich(name);
55 if (found) {
56 *bin = found;
57 return &backends[i];
58 }
59 }
60 }
61 }
62 return NULL;
63}
64
65void
66backend_exec(const struct Backend *be, const char *bin, struct StrList *wanted)
67{
68 struct StrList argv = {0};
69 int i;
70
71 sl_push(&argv, base_of(bin));
72 sl_push(&argv, "-f");
73 sl_push(&argv, be->file);
74 for (i = 0; i < wanted->n; i++)
75 sl_push(&argv, wanted->v[i]);
76
77 wexecv_self(bin, sl_argv(&argv));
78}