1#include "ninqu.h"
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7struct Rule *rules;
8int nrules, rulescap;
9struct Group *groups;
10int ngroups, groupscap;
11struct Meta *metas;
12int nmetas, metascap;
13struct Template *templates;
14int ntemplates, templatescap;
15struct Inst *insts;
16int ninsts, instscap;
17
18struct Rule *
19rule_find(const char *name)
20{
21 int i;
22 for (i = 0; i < nrules; i++)
23 if (strcmp(rules[i].name, name) == 0)
24 return &rules[i];
25 return NULL;
26}
27
28/* match (out) against path, expanding $(...) as needed. used to
29 * find a producer for a file that does not exist yet */
30struct Rule *
31rule_find_output(const char *path)
32{
33 int i;
34 for (i = 0; i < nrules; i++) {
35 if (!rules[i].out[0])
36 continue;
37 if (strchr(rules[i].out, '$')) {
38 char *exp = kv_expand(rules[i].out);
39 int ok = strcmp(exp, path) == 0;
40 free(exp);
41 if (ok)
42 return &rules[i];
43 } else if (strcmp(rules[i].out, path) == 0) {
44 return &rules[i];
45 }
46 }
47 return NULL;
48}
49
50struct Rule *
51rule_find_produces(const char *name)
52{
53 int i;
54 for (i = 0; i < nrules; i++)
55 if (rules[i].produces[0] && strcmp(rules[i].produces, name) == 0)
56 return &rules[i];
57 return NULL;
58}
59
60struct Rule *
61rule_new(const char *name)
62{
63 struct Rule *r;
64 if (rule_find(name))
65 eprintf("manifest: duplicate rule '%s'\n", name);
66 if (group_find(name))
67 eprintf("manifest: name '%s' already a group\n", name);
68 GROW(rules, nrules, rulescap, 16);
69 r = &rules[nrules++];
70 memset(r, 0, sizeof *r);
71 strlcpy(r->name, name, sizeof r->name);
72 return r;
73}
74
75struct Group *
76group_find(const char *name)
77{
78 int i;
79 for (i = 0; i < ngroups; i++)
80 if (strcmp(groups[i].name, name) == 0)
81 return &groups[i];
82 return NULL;
83}
84
85struct Group *
86group_new(const char *name)
87{
88 struct Group *g;
89 if (group_find(name))
90 eprintf("manifest: duplicate group '%s'\n", name);
91 if (rule_find(name))
92 eprintf("manifest: name '%s' already a rule\n", name);
93 GROW(groups, ngroups, groupscap, 16);
94 g = &groups[ngroups++];
95 memset(g, 0, sizeof *g);
96 strlcpy(g->name, name, sizeof g->name);
97 return g;
98}
99
100struct Meta *
101meta_find(const char *name)
102{
103 int i;
104 for (i = 0; i < nmetas; i++)
105 if (strcmp(metas[i].name, name) == 0)
106 return &metas[i];
107 return NULL;
108}
109
110struct Meta *
111meta_new(const char *name)
112{
113 struct Meta *m;
114 if (meta_find(name))
115 eprintf("manifest: duplicate meta '%s'\n", name);
116 if (rule_find(name))
117 eprintf("manifest: name '%s' already a rule\n", name);
118 if (group_find(name))
119 eprintf("manifest: name '%s' already a group\n", name);
120 GROW(metas, nmetas, metascap, 8);
121 m = &metas[nmetas++];
122 memset(m, 0, sizeof *m);
123 strlcpy(m->name, name, sizeof m->name);
124 return m;
125}
126
127struct Template *
128template_find(const char *name)
129{
130 int i;
131 for (i = 0; i < ntemplates; i++)
132 if (strcmp(templates[i].name, name) == 0)
133 return &templates[i];
134 return NULL;
135}
136
137struct Template *
138template_new(const char *name)
139{
140 struct Template *t;
141 if (template_find(name))
142 eprintf("manifest: duplicate template '%s'\n", name);
143 GROW(templates, ntemplates, templatescap, 8);
144 t = &templates[ntemplates++];
145 memset(t, 0, sizeof *t);
146 strlcpy(t->name, name, sizeof t->name);
147 return t;
148}
149
150int
151inst_new(int rule_idx)
152{
153 struct Inst *in;
154 struct Rule *r = &rules[rule_idx];
155
156 GROW(insts, ninsts, instscap, 32);
157 in = &insts[ninsts];
158 memset(in, 0, sizeof *in);
159 in->rule_idx = rule_idx;
160
161 if (r->n_inst >= r->cap_inst) {
162 r->cap_inst = r->cap_inst ? r->cap_inst * 2 : 4;
163 r->inst_idx = erealloc(r->inst_idx, (size_t)r->cap_inst * sizeof *r->inst_idx);
164 }
165 r->inst_idx[r->n_inst++] = ninsts;
166 return ninsts++;
167}