main shrubtools / proto / protocol.c
  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}