1#include <stdlib.h>
2#include <string.h>
3
4#include "protocol.h"
5#include "util.h"
6
7static void free_message(struct message *);
8static void free_description(struct description *);
9
10struct interface *
11proto_add_interface(struct protocol *proto, const char *name, int version)
12{
13 struct interface *iface;
14
15 if (proto->nifaces == proto->ifacecap) {
16 proto->ifacecap = proto->ifacecap ? proto->ifacecap * 2 : 8;
17 proto->ifaces = xreallocarray(proto->ifaces, proto->ifacecap, sizeof(proto->ifaces[0]));
18 }
19 iface = &proto->ifaces[proto->nifaces++];
20 memset(iface, 0, sizeof(*iface));
21 iface->name = xstrdup(name);
22 iface->version = version;
23 return iface;
24}
25
26struct interface *
27proto_find_interface(const struct protocol *proto, const char *name)
28{
29 size_t i;
30
31 for (i = 0; i < proto->nifaces; ++i) {
32 if (strcmp(proto->ifaces[i].name, name) == 0)
33 return &proto->ifaces[i];
34 }
35 return NULL;
36}
37
38struct message *
39iface_add_message(struct interface *iface, enum message_dir dir, const char *name)
40{
41 struct message *msg;
42 struct message **list;
43 size_t *nlist, *cap;
44
45 if (dir == MSG_REQUEST) {
46 list = &iface->requests;
47 nlist = &iface->nrequests;
48 cap = &iface->requestcap;
49 } else {
50 list = &iface->events;
51 nlist = &iface->nevents;
52 cap = &iface->eventcap;
53 }
54 if (*nlist == *cap) {
55 *cap = *cap ? *cap * 2 : 8;
56 *list = xreallocarray(*list, *cap, sizeof((*list)[0]));
57 }
58 msg = &(*list)[(*nlist)++];
59 memset(msg, 0, sizeof(*msg));
60 msg->name = xstrdup(name);
61 msg->dir = dir;
62 msg->opcode = (int)(*nlist - 1);
63 return msg;
64}
65
66void
67message_add_arg(struct message *msg, const char *name, const char *type, const char *iface, bool nullable)
68{
69 struct argument *arg;
70
71 if (msg->nargs == msg->argcap) {
72 msg->argcap = msg->argcap ? msg->argcap * 2 : 8;
73 msg->args = xreallocarray(msg->args, msg->argcap, sizeof(msg->args[0]));
74 }
75 arg = &msg->args[msg->nargs++];
76 memset(arg, 0, sizeof(*arg));
77 arg->name = xstrdup(name);
78 arg->type = xstrdup(type);
79 arg->iface = iface ? xstrdup(iface) : NULL;
80 arg->nullable = nullable;
81 arg->new_id = strcmp(type, "new_id") == 0;
82}
83
84void
85iface_add_enum(struct interface *iface, const char *name)
86{
87 if (iface->nenums == iface->enumcap) {
88 iface->enumcap = iface->enumcap ? iface->enumcap * 2 : 4;
89 iface->enums = xreallocarray(iface->enums, iface->enumcap, sizeof(iface->enums[0]));
90 }
91 memset(&iface->enums[iface->nenums], 0, sizeof(iface->enums[0]));
92 iface->enums[iface->nenums++].name = xstrdup(name);
93}
94
95struct enumdef *
96iface_last_enum(struct interface *iface)
97{
98 if (iface->nenums == 0)
99 return NULL;
100 return &iface->enums[iface->nenums - 1];
101}
102
103const struct argument *
104message_creator_arg(const struct message *msg)
105{
106 size_t i;
107
108 for (i = 0; i < msg->nargs; ++i) {
109 if (msg->args[i].new_id && msg->args[i].iface && msg->args[i].iface[0])
110 return &msg->args[i];
111 }
112 return NULL;
113}
114
115void
116proto_resolve(struct protocol *proto)
117{
118 size_t i, j;
119 struct interface *target;
120 const struct argument *arg;
121
122 for (i = 0; i < proto->nifaces; ++i) {
123 proto->ifaces[i].created_by_local = false;
124 proto->ifaces[i].ncreates = 0;
125 }
126 proto->total_requests = 0;
127 proto->total_events = 0;
128 proto->total_enums = 0;
129
130 for (i = 0; i < proto->nifaces; ++i) {
131 struct interface *iface = &proto->ifaces[i];
132
133 proto->total_requests += iface->nrequests;
134 proto->total_events += iface->nevents;
135 proto->total_enums += iface->nenums;
136 for (j = 0; j < iface->nrequests; ++j) {
137 arg = message_creator_arg(&iface->requests[j]);
138 if (!arg)
139 continue;
140 ++iface->ncreates;
141 target = proto_find_interface(proto, arg->iface);
142 if (target)
143 target->created_by_local = true;
144 }
145 }
146}
147
148static void
149free_description(struct description *desc)
150{
151 free(desc->summary);
152 free(desc->text);
153}
154
155static void
156free_message(struct message *msg)
157{
158 size_t i;
159
160 free(msg->name);
161 free_description(&msg->desc);
162 for (i = 0; i < msg->nargs; ++i) {
163 free(msg->args[i].name);
164 free(msg->args[i].type);
165 free(msg->args[i].iface);
166 }
167 free(msg->args);
168}
169
170void
171proto_free(struct protocol *proto)
172{
173 size_t i, j;
174
175 free(proto->name);
176 free_description(&proto->desc);
177 for (i = 0; i < proto->nifaces; ++i) {
178 struct interface *iface = &proto->ifaces[i];
179
180 free(iface->name);
181 free_description(&iface->desc);
182 for (j = 0; j < iface->nrequests; ++j)
183 free_message(&iface->requests[j]);
184 for (j = 0; j < iface->nevents; ++j)
185 free_message(&iface->events[j]);
186 for (j = 0; j < iface->nenums; ++j)
187 {
188 free(iface->enums[j].name);
189 free_description(&iface->enums[j].desc);
190 }
191 free(iface->requests);
192 free(iface->events);
193 free(iface->enums);
194 }
195 free(proto->ifaces);
196 memset(proto, 0, sizeof(*proto));
197}