1#include <alloc.h>
2#include <byte.h>
3#include <str.h>
4
5#include "protocol.h"
6#include "util.h"
7
8static void free_message(struct message *);
9static void free_description(struct description *);
10extern const char *argv0;
11
12struct interface *
13proto_add_interface(struct protocol *proto, const char *name, int version)
14{
15 struct interface *iface;
16
17 if (proto->nifaces == proto->ifacecap) {
18 size_t oldcap;
19
20 oldcap = proto->ifacecap;
21 proto->ifacecap = proto->ifacecap ? proto->ifacecap * 2 : 8;
22 if (!alloc_re((char **)&proto->ifaces,
23 oldcap * sizeof(proto->ifaces[0]),
24 proto->ifacecap * sizeof(proto->ifaces[0])))
25 die_nomem();
26 }
27 iface = &proto->ifaces[proto->nifaces++];
28 byte_zero(iface, sizeof(*iface));
29 iface->name = copystr(name);
30 iface->version = version;
31 return iface;
32}
33
34struct interface *
35proto_find_interface(const struct protocol *proto, const char *name)
36{
37 size_t i;
38
39 for (i = 0; i < proto->nifaces; ++i) {
40 if (str_equal(proto->ifaces[i].name, name))
41 return &proto->ifaces[i];
42 }
43 return NULL;
44}
45
46struct message *
47iface_add_message(struct interface *iface, enum message_dir dir, const char *name)
48{
49 struct message *msg;
50 struct message **list;
51 size_t *nlist, *cap;
52
53 if (dir == MSG_REQUEST) {
54 list = &iface->requests;
55 nlist = &iface->nrequests;
56 cap = &iface->requestcap;
57 } else {
58 list = &iface->events;
59 nlist = &iface->nevents;
60 cap = &iface->eventcap;
61 }
62 if (*nlist == *cap) {
63 size_t oldcap;
64
65 oldcap = *cap;
66 *cap = *cap ? *cap * 2 : 8;
67 if (!alloc_re((char **)list,
68 oldcap * sizeof((*list)[0]),
69 *cap * sizeof((*list)[0])))
70 die_nomem();
71 }
72 msg = &(*list)[(*nlist)++];
73 byte_zero(msg, sizeof(*msg));
74 msg->name = copystr(name);
75 msg->dir = dir;
76 msg->opcode = (int)(*nlist - 1);
77 return msg;
78}
79
80void
81message_add_arg(struct message *msg, const char *name, const char *type, const char *iface, bool nullable)
82{
83 struct argument *arg;
84
85 if (msg->nargs == msg->argcap) {
86 size_t oldcap;
87
88 oldcap = msg->argcap;
89 msg->argcap = msg->argcap ? msg->argcap * 2 : 8;
90 if (!alloc_re((char **)&msg->args,
91 oldcap * sizeof(msg->args[0]),
92 msg->argcap * sizeof(msg->args[0])))
93 die_nomem();
94 }
95 arg = &msg->args[msg->nargs++];
96 byte_zero(arg, sizeof(*arg));
97 arg->name = copystr(name);
98 arg->type = copystr(type);
99 arg->iface = iface ? copystr(iface) : NULL;
100 arg->summary = NULL;
101 arg->nullable = nullable;
102 arg->new_id = str_equal(type, "new_id");
103}
104
105void
106iface_add_enum(struct interface *iface, const char *name)
107{
108 if (iface->nenums == iface->enumcap) {
109 size_t oldcap;
110
111 oldcap = iface->enumcap;
112 iface->enumcap = iface->enumcap ? iface->enumcap * 2 : 4;
113 if (!alloc_re((char **)&iface->enums,
114 oldcap * sizeof(iface->enums[0]),
115 iface->enumcap * sizeof(iface->enums[0])))
116 die_nomem();
117 }
118 byte_zero(&iface->enums[iface->nenums], sizeof(iface->enums[0]));
119 iface->enums[iface->nenums++].name = copystr(name);
120}
121
122struct enumdef *
123iface_last_enum(struct interface *iface)
124{
125 if (iface->nenums == 0)
126 return NULL;
127 return &iface->enums[iface->nenums - 1];
128}
129
130void
131enum_add_entry(struct enumdef *en, const char *name, const char *value)
132{
133 if (en->nentries == en->entrycap) {
134 size_t oldcap;
135
136 oldcap = en->entrycap;
137 en->entrycap = en->entrycap ? en->entrycap * 2 : 8;
138 if (!alloc_re((char **)&en->entries,
139 oldcap * sizeof(en->entries[0]),
140 en->entrycap * sizeof(en->entries[0])))
141 die_nomem();
142 }
143 byte_zero(&en->entries[en->nentries], sizeof(en->entries[0]));
144 en->entries[en->nentries].name = copystr(name);
145 en->entries[en->nentries].value = copystr(value);
146 ++en->nentries;
147}
148
149struct enumentry *
150enum_last_entry(struct enumdef *en)
151{
152 if (en->nentries == 0)
153 return NULL;
154 return &en->entries[en->nentries - 1];
155}
156
157const struct argument *
158message_creator_arg(const struct message *msg)
159{
160 size_t i;
161
162 for (i = 0; i < msg->nargs; ++i) {
163 if (msg->args[i].new_id && msg->args[i].iface && msg->args[i].iface[0])
164 return &msg->args[i];
165 }
166 return NULL;
167}
168
169void
170proto_resolve(struct protocol *proto)
171{
172 size_t i, j;
173 struct interface *target;
174 const struct argument *arg;
175
176 for (i = 0; i < proto->nifaces; ++i) {
177 proto->ifaces[i].created_by_local = false;
178 proto->ifaces[i].ncreates = 0;
179 }
180 proto->total_requests = 0;
181 proto->total_events = 0;
182 proto->total_enums = 0;
183
184 for (i = 0; i < proto->nifaces; ++i) {
185 struct interface *iface = &proto->ifaces[i];
186
187 proto->total_requests += iface->nrequests;
188 proto->total_events += iface->nevents;
189 proto->total_enums += iface->nenums;
190 for (j = 0; j < iface->nrequests; ++j) {
191 arg = message_creator_arg(&iface->requests[j]);
192 if (!arg)
193 continue;
194 ++iface->ncreates;
195 target = proto_find_interface(proto, arg->iface);
196 if (target)
197 target->created_by_local = true;
198 }
199 }
200}
201
202static void
203free_description(struct description *desc)
204{
205 alloc_free(desc->summary);
206 alloc_free(desc->text);
207}
208
209static void
210free_message(struct message *msg)
211{
212 size_t i;
213
214 alloc_free(msg->name);
215 free_description(&msg->desc);
216 for (i = 0; i < msg->nargs; ++i) {
217 alloc_free(msg->args[i].name);
218 alloc_free(msg->args[i].type);
219 alloc_free(msg->args[i].iface);
220 alloc_free(msg->args[i].summary);
221 }
222 alloc_free((char *)msg->args);
223}
224
225void
226proto_free(struct protocol *proto)
227{
228 size_t i, j;
229
230 alloc_free(proto->name);
231 free_description(&proto->desc);
232 for (i = 0; i < proto->nifaces; ++i) {
233 struct interface *iface = &proto->ifaces[i];
234
235 alloc_free(iface->name);
236 free_description(&iface->desc);
237 for (j = 0; j < iface->nrequests; ++j)
238 free_message(&iface->requests[j]);
239 for (j = 0; j < iface->nevents; ++j)
240 free_message(&iface->events[j]);
241 for (j = 0; j < iface->nenums; ++j)
242 {
243 size_t k;
244
245 alloc_free(iface->enums[j].name);
246 free_description(&iface->enums[j].desc);
247 for (k = 0; k < iface->enums[j].nentries; ++k) {
248 alloc_free(iface->enums[j].entries[k].name);
249 alloc_free(iface->enums[j].entries[k].value);
250 alloc_free(iface->enums[j].entries[k].summary);
251 free_description(&iface->enums[j].entries[k].desc);
252 }
253 alloc_free((char *)iface->enums[j].entries);
254 }
255 alloc_free((char *)iface->requests);
256 alloc_free((char *)iface->events);
257 alloc_free((char *)iface->enums);
258 }
259 alloc_free((char *)proto->ifaces);
260 byte_zero(proto, sizeof(*proto));
261}