4 local h = io.open("types.h", "w")
5 local c = io.open("types.c", "w")
6 local def = io.open(arg[1] or "types.def", "r")
8 local function emit_h(str)
12 local function emit_c(str)
16 local function emit(fun, code)
18 emit_c(fun .. "\n" .. code)
22 local struct_prefix = "__attribute__((packed)) "
23 local export_prefix = ""
24 local local_prefix = "__attribute__((unused)) static inline "
30 This file was automatically generated by Protogen.
31 DO NOT EDIT it manually. Instead, edit types.def and re-run protogen.
38 #ifndef _PROTOGEN_TYPES_H_
39 #define _PROTOGEN_TYPES_H_
42 #include <dragonnet/peer.h>
54 } ]] .. struct_prefix .. [[Blob;
62 #include <dragonnet/send.h>
63 #include <dragonnet/recv.h>
79 ]] .. local_prefix .. [[void raw_write(Blob *buffer, const void *data, size_t len)
81 buffer->data = realloc(buffer->data, len + buffer->siz);
82 memcpy(&buffer->data[buffer->siz], data, len);
86 ]] .. local_prefix .. [[bool raw_read(Blob *buffer, void *data, size_t len)
91 if (buffer->siz < len) {
92 fprintf(stderr, "[warning] buffer exhausted (requested bytes: %zu, remaining bytes: %" PRIu64 ")\n", len, buffer->siz);
96 memcpy(data, buffer->data, len);
106 local existing_types = {}
107 local has_deallocator = {}
111 local base_vector_components = {"x", "y", "z", "w"}
112 local vector_components = {}
115 local components = {}
118 table.insert(components, base_vector_components[j])
121 vector_components[i] = components
126 local numeric_types = {}
128 local function emit_vector(type, l)
129 local name = "v" .. l .. type
130 local box = "aabb" .. l .. type
132 existing_types[name] = true
133 has_deallocator[name] = false
135 existing_types[box] = true
136 has_deallocator[box] = false
138 local typedef, equals, add, sub, clamp, cmp, scale, mix, write, read, send, recv =
139 "", "", "", "", "", "", "", "", "", "", "", ""
141 for i, c in ipairs(vector_components[l]) do
152 .. "a." .. c .. " == "
160 .. "a." .. c .. " + "
168 .. "a." .. c .. " - "
177 .. "val." .. c .. ", "
178 .. "min." .. c .. ", "
179 .. "max." .. c .. ")" ..
186 .. "\tif ((i = " .. type .. "_cmp("
187 .. "&((const " .. name .. " *) a)->" .. c .. ", "
188 .. "&((const " .. name .. " *) b)->" .. c .. ")) != 0)"
189 .. "\n\t\treturn i;\n"
192 .. "v." .. c .. " * s" ..
209 .. "\t" .. type .. "_write(buffer, &val->" .. c .. ");\n"
212 .. "\tif (!" .. type .. "_read(buffer, &val->" .. c .. "))\n\t\treturn false;\n"
215 .. "\tif (!" .. type .. "_send(peer, " .. (last and "submit" or "false") .. ", &val->" .. c .. "))\n\t\treturn false;\n"
218 .. "\tif (!" .. type .. "_recv(peer, &val->" .. c .. "))\n\t\treturn false;\n"
221 emit_h("typedef struct {\n\t" .. type .. " " .. typedef .. "} " .. struct_prefix .. name .. ";\n")
223 emit(export_prefix .. "bool " .. name .. "_equals(" .. name .. " a, " .. name .. " b)", "{\n\treturn " .. equals .. "}\n\n")
224 emit(export_prefix .. name .. " " .. name .. "_add(" .. name .. " a, " .. name .. " b)", "{\n\treturn (" .. name .. ") {" .. add .. "}\n\n")
225 emit(export_prefix .. name .. " " .. name .. "_sub(" .. name .. " a, " .. name .. " b)", "{\n\treturn (" .. name .. ") {" .. sub .. "}\n\n")
226 emit(export_prefix .. name .. " " .. name .. "_clamp(" .. name .. " val, " .. name .. " min, " .. name .. " max)", "{\n\treturn (" .. name .. ") {" .. clamp .. "}\n\n")
227 emit(export_prefix .. "int " .. name .. "_cmp(const void *a, const void *b)", "{\n\tint i;\n" .. cmp .. "\treturn 0;\n}\n\n")
228 emit(export_prefix .. name .. " " .. name .. "_scale(" .. name .. " v, " .. type .. " s)", "{\n\treturn (" .. name .. ") {" .. scale .. "}\n\n")
230 if type:sub(1, 1) == "f" then
231 emit(export_prefix .. name .. " " .. name .. "_mix(" .. name .. " a, " .. name .. " b, " .. type .. " f)", "{\n\treturn (" .. name .. ") {" .. mix .. "}\n\n")
234 emit(export_prefix .. "void " .. name .. "_write(Blob *buffer, " .. name .. " *val)", "{\n" .. write .. "}\n\n")
235 emit(export_prefix .. "bool " .. name .. "_read(Blob *buffer, " .. name .. " *val)", "{\n" .. read .. "\treturn true;\n}\n\n")
237 emit_c("#ifdef USE_DRAGONNET\n")
238 emit_c(local_prefix .. "bool " .. name .. "_send(DragonnetPeer *peer, bool submit, " .. name .. " *val)\n{\n" .. send .. "\treturn true;\n}\n\n")
239 emit_c(local_prefix .. "bool " .. name .. "_recv(DragonnetPeer *peer, " .. name .. " *val)\n{\n" .. recv .. "\treturn true;\n}\n")
244 emit_h("typedef struct {\n\t" .. name .. " min, max;\n} " .. struct_prefix .. box .. ";\n")
246 emit(export_prefix .. "void " .. box .. "_write(Blob *buffer, " .. box .. " *val)", "{\n\t" .. name .. "_write(buffer, &val->min);\n\t" .. name .. "_write(buffer, &val->max);\n}\n\n")
247 emit(export_prefix .. "bool " .. box .. "_read(Blob *buffer, " .. box .. " *val)", "{\n\tif (!" .. name .. "_read(buffer, &val->min))\n\t\treturn false;\n\tif (!" .. name .. "_read(buffer, &val->max))\n\t\treturn false;\n\treturn true;\n}\n\n")
249 emit_c("#ifdef USE_DRAGONNET\n")
250 emit_c(local_prefix .. "bool " .. box .. "_send(DragonnetPeer *peer, bool submit, " .. box .. " *val)\n{\n\tif (!" .. name .. "_send(peer, false, &val->min))\n\t\treturn false;\n\tif (!" .. name .. "_send(peer, submit, &val->max))\n\t\treturn false;\n\treturn true;\n}\n\n")
251 emit_c(local_prefix .. "bool " .. box .. "_recv(DragonnetPeer *peer, " .. box .. " *val)\n{\n\tif (!" .. name .. "_recv(peer, &val->min))\n\t\treturn false;\n\t if (!" .. name .. "_recv(peer, &val->max))\n\t\treturn false;\n\treturn true;\n}\n")
257 local function emit_numeric(class, bits, alias)
258 local name = class .. bits
259 table.insert(numeric_types, name)
261 existing_types[name] = true
262 has_deallocator[name] = false
264 emit_h("typedef " .. alias .. " " .. name .. ";\n")
266 emit(export_prefix .. name .. " " .. name .. "_min(" .. name .. " a, " .. name .. " b)", "{\n\treturn a < b ? a : b;\n}\n\n")
267 emit(export_prefix .. name .. " " .. name .. "_max(" .. name .. " a, " .. name .. " b)", "{\n\treturn a > b ? a : b;\n}\n\n")
268 emit(export_prefix .. name .. " " .. name .. "_clamp(" .. name .. " val, " .. name .. " min, " .. name .. " max)", "{\n\treturn val < min ? min : val > max ? max : val;\n}\n\n")
269 emit(export_prefix .. "int " .. name .. "_cmp(const void *a, const void *b)", "{\n\treturn\n\t\t*(const " .. name .. " *) a < *(const " .. name .. " *) b ? -1 :\n\t\t*(const " .. name .. " *) a > *(const " .. name .. " *) b ? +1 :\n\t\t0;\n}\n\n")
272 emit(export_prefix .. name .. " " .. name .. "_mix(" .. name .. " a, " .. name .. " b, " .. name .. " f)", "{\n\treturn (1.0 - f) * a + b * f;\n}\n\n")
275 emit(export_prefix .. "void " .. name .. "_write(Blob *buffer, " .. name .. " *val)", "{\n" .. (class == "u"
276 and "\t" .. name .. " be = htobe" .. bits .. "(*val);\n\traw_write(buffer, &be, sizeof be);\n"
277 or "\tu" .. bits .. "_write(buffer, (u" .. bits .. " *) val);\n"
279 emit(export_prefix .. "bool " .. name .. "_read(Blob *buffer, " .. name .. " *val)", "{\n" .. (class == "u"
280 and "\t" .. name .. " be;\n\tif (!raw_read(buffer, &be, sizeof be))\n\t\treturn false;\n\t*val = be" .. bits .. "toh(be);\n\treturn true;\n"
281 or "\treturn u" .. bits .. "_read(buffer, (u" .. bits .. " *) val);\n"
284 emit_c("#ifdef USE_DRAGONNET\n")
285 emit_c(local_prefix .. "bool " .. name .. "_send(DragonnetPeer *peer, bool submit, " .. name .. " *val)\n{\n" .. (class == "u"
286 and "\t" .. name .. " be = htobe" .. bits .. "(*val);\n\treturn dragonnet_send_raw(peer, submit, &be, sizeof be);\n"
287 or "\treturn u" .. bits .. "_send(peer, submit, (u" .. bits .. " *) val);\n"
289 emit_c(local_prefix .. "bool " .. name .. "_recv(DragonnetPeer *peer, " .. name .. " *val)\n{\n" .. (class == "u"
290 and "\t" .. name .. " be;\n\tif (!dragonnet_recv_raw(peer, &be, sizeof be))\n\t\treturn false;\n\t*val = be" .. bits .. "toh(be);\n\treturn true;\n"
291 or "\treturn u" .. bits .. "_recv(peer, (u" .. bits .. " *) val);\n"
303 local bytes = math.floor(2 ^ i)
304 local bits = 8 * bytes
306 emit_numeric("u", bits, "uint" .. bits .. "_t")
307 emit_numeric("s", bits, "int" .. bits .. "_t")
310 emit_numeric("f", bits, ({"float", "double"})[i - 1])
314 local converters = {}
319 for i, c in ipairs(vector_components[l]) do
320 converters[l] = converters[l]
329 for _, from in ipairs(numeric_types) do
330 for _, to in ipairs(numeric_types) do
333 local v_from = "v" .. i .. from
334 local v_to = "v" .. i .. to
336 emit(export_prefix .. v_to .. " " .. v_from .. "_to_" .. to .. "(" .. v_from .. " v)", "{\n\treturn (" .. v_to .. ") {" .. converters[i] .. "}\n\n")
346 existing_types.String = true
347 has_deallocator.String = true
350 export_prefix .. "void String_free(String *val)", [[
360 export_prefix .. "void String_write(Blob *buffer, String *val)", [[
362 *val ? raw_write(buffer, *val, strlen(*val) + 1) : raw_write(buffer, "", 1);
369 export_prefix .. "bool String_read(Blob *buffer, String *val)", [[
371 String v = malloc(1 + (1 << 16));
374 for (u16 i = 0;; i++) {
375 if (!raw_read(buffer, &c, 1)) {
385 *val = realloc(v, strlen(v) + 1);
396 ]] .. local_prefix .. [[bool String_send(DragonnetPeer *peer, bool submit, String *val)
398 return *val ? dragonnet_send_raw(peer, submit, *val, strlen(*val) + 1) : dragonnet_send_raw(peer, submit, "", 1);
401 ]] .. local_prefix .. [[bool String_recv(DragonnetPeer *peer, String *val)
403 String v = malloc(1 + (1 << 16));
406 for (u16 i = 0;; i++) {
407 if (!dragonnet_recv_raw(peer, &c, 1)) {
417 *val = realloc(v, strlen(v) + 1);
430 existing_types.Blob = true
431 has_deallocator.Blob = true
434 export_prefix .. "void Blob_compress(Blob *buffer, Blob *val)", [[
436 buffer->siz = 8 + 2 + val->siz;
437 buffer->data = malloc(buffer->siz);
439 *(u64 *) buffer->data = val->siz;
446 s.avail_in = val->siz;
447 s.next_in = (Bytef *) val->data;
448 s.avail_out = buffer->siz - 8 + 1;
449 s.next_out = (Bytef *) buffer->data + 8;
451 deflateInit(&s, Z_BEST_COMPRESSION);
452 deflate(&s, Z_FINISH);
455 buffer->siz = s.total_out + 8;
462 export_prefix .. "void Blob_decompress(Blob *buffer, Blob *val)", [[
464 buffer->siz = *(u64 *) val->data;
465 buffer->data = malloc(buffer->siz);
472 s.avail_in = val->siz - 8;
473 s.next_in = val->data + 8;
474 s.avail_out = buffer->siz;
475 s.next_out = (Bytef *) buffer->data;
478 inflate(&s, Z_NO_FLUSH);
481 buffer->siz = s.total_out;
488 export_prefix .. "void Blob_shrink(Blob *val)", [[
490 val->data = realloc(val->data, val->siz);
497 export_prefix .. "void Blob_free(Blob *val)", [[
507 export_prefix .. "void Blob_write(Blob *buffer, Blob *val)", [[
509 u64_write(buffer, &val->siz);
510 raw_write(buffer, val->data, val->siz);
517 export_prefix .. "bool Blob_read(Blob *buffer, Blob *val)", [[
519 if (!u64_read(buffer, &val->siz))
522 if (!raw_read(buffer, val->data = malloc(val->siz), val->siz)) {
537 ]] .. local_prefix .. [[bool Blob_send(DragonnetPeer *peer, bool submit, Blob *val)
539 if (!u64_send(peer, false, &val->siz))
541 return dragonnet_send_raw(peer, submit, val->data, val->siz);
544 ]] .. local_prefix .. [[bool Blob_recv(DragonnetPeer *peer, Blob *val)
546 if (!u64_recv(peer, &val->siz))
549 if (!dragonnet_recv_raw(peer, val->data = malloc(val->siz), val->siz)) {
567 ]] .. local_prefix .. [[void raw_write_compressed(Blob *buffer, void *val, void (*val_write)(Blob *, void *))
569 Blob compressed, raw = {0};
570 val_write(&raw, val);
571 Blob_compress(&compressed, &raw);
572 Blob_write(buffer, &compressed);
574 Blob_free(&compressed);
578 ]] .. local_prefix .. [[bool raw_read_compressed(Blob *buffer, void *val, bool (*val_read)(Blob *, void *))
580 Blob compressed, raw = {0};
581 bool success = Blob_read(buffer, &compressed);
584 Blob_decompress(&raw, &compressed);
585 Blob raw_buffer = raw;
586 success = success && val_read(&raw_buffer, val);
589 Blob_free(&compressed);
596 ]] .. local_prefix .. [[bool raw_send_compressed(DragonnetPeer *peer, bool submit, void *val, void (*val_write)(Blob *, void *))
598 Blob compressed, raw = {0};
599 val_write(&raw, val);
600 Blob_compress(&compressed, &raw);
601 bool success = Blob_send(peer, submit, &compressed);
603 Blob_free(&compressed);
609 ]] .. local_prefix .. [[bool raw_recv_compressed(DragonnetPeer *peer, void *val, bool (*val_read)(Blob *, void *))
611 Blob compressed, raw = {0};
612 bool success = Blob_recv(peer, &compressed);
615 Blob_decompress(&raw, &compressed);
616 Blob raw_buffer = raw;
617 success = success && val_read(&raw_buffer, val);
620 Blob_free(&compressed);
630 local custom_types = {}
633 local function consume_name(name)
635 table.insert(custom_types, current_type)
641 current_type = {components = {}, component_names = {}}
643 current_type.flags = name:split(" ")
644 current_type.name = table.remove(current_type.flags, #current_type.flags)
646 if existing_types[current_type.name] then
647 error("redeclaration of type " .. current_type.name)
650 existing_types[current_type.name] = true
651 has_deallocator[current_type.name] = false
655 local function consume_comp(comp)
656 if not current_type then
657 error("component without a type: " .. comp)
662 component.flags = comp:split(" ")
663 component.name = table.remove(component.flags, #component.flags)
664 component.type = table.remove(component.flags, #component.flags)
666 component.full_name = current_type.name .. "." .. component.name
669 local met_brace = false
670 local brace_level = 0
672 for i = 1, #component.type do
673 local c = component.type:sub(i, i)
677 if not met_brace then
682 brace_level = brace_level + 1
684 if brace_level == 1 then
685 table.insert(component.array, "")
690 brace_level = brace_level - 1
692 if brace_level < 0 then
693 error("missing [ in " .. component.full_name)
694 elseif brace_level > 0 then
697 elseif not met_brace then
698 base_type = base_type .. c
699 elseif brace_level == 1 then
701 elseif brace_level == 0 then
702 error("invalid character " .. c .. " outside of braces in " .. component.full_name)
706 component.array[#component.array] = component.array[#component.array] .. c
710 component.type = base_type
712 if brace_level > 0 then
713 error("missing ] in " .. component.full_name)
716 if not existing_types[component.type] then
717 error("type " .. component.type .. " of " .. component.full_name .. " does not exist ")
720 has_deallocator[current_type.name] = has_deallocator[current_type.name] or has_deallocator[component.type]
722 if current_type.component_names[component.name] then
723 error("component " .. component.full_name .. " redeclared")
726 current_type.component_names[component.name] = true
728 table.insert(current_type.components, component)
732 for l in def:lines() do
733 local f = l:sub(1, 1)
736 consume_comp(l:sub(2, #l))
747 local dragonnet_types_h = ""
748 local dragonnet_types_c = ""
750 for _, t in ipairs(custom_types) do
753 for _, f in pairs(t.flags) do
757 error("invalid flag " .. f .. " for " .. t.name)
761 local typedef, free, write, read, send, recv =
762 "", "", "", "", "", ""
764 for ic, c in ipairs(t.components) do
771 for _, a in ipairs(c.array) do
772 table.insert(indices, 1, a)
775 for _, a in ipairs(indices) do
777 type = "struct { size_t siz; " .. type .. " (*ptr)" .. type_end .. "; }"
780 type_end = "[" .. a .. "]" .. type_end
786 .. "\t" .. type .. " " .. c.name .. type_end .. ";\n"
788 local compressed = false
790 for _, f in pairs(c.flags) do
791 if f == "compressed" then
794 error("invalid flag " .. f .. " for " .. c.full_name)
820 local array_submit = ""
823 for ia, a in ipairs(c.array) do
828 local var = "val->" .. c.name .. index
829 local ptr = var .. ".ptr"
832 loop.free = loop.free .. indent.free .. "if (" .. ptr .. ") {\n"
833 loop_end.free = indent.free .. "}\n" .. loop_end.free
834 indent.free = indent.free .. "\t"
835 loop_end.free = indent.free .. "free(" .. ptr .. ");\n" .. loop_end.free
837 loop.write = loop.write .. indent.write .. "u64_write(buffer, &" .. siz .. ");\n"
839 loop.send = loop.send .. indent.send .. "if (!u64_send(peer, &" .. siz .. ", false))\n"
840 .. indent.send .. "\treturn false;\n"
842 loop.read = loop.read .. indent.read .. "if (!u64_read(buffer, &" .. siz .. "))\n"
843 .. indent.read .. "\treturn false;\n"
844 .. indent.read .. ptr .. " = calloc(" .. siz .. ", sizeof *" .. ptr .. ");\n"
846 loop.recv = loop.recv .. indent.recv .. "if (!u64_recv(peer, &" .. siz .. "))\n"
847 .. indent.recv .. "\treturn false;\n"
848 .. indent.recv .. ptr .. " = calloc(" .. siz .. ", sizeof *" .. ptr .. ");\n"
850 index = index .. ".ptr"
853 for f in pairs(loop) do
854 loop[f] = loop[f] .. indent[f] .. "for (size_t " .. it .. " = 0; " .. it .. " < " .. siz .. "; " .. it .. "++) {\n"
855 loop_end[f] = indent[f] .. "}\n" .. loop_end[f]
856 indent[f] = indent[f] .. "\t"
859 index = index .. "[" .. it .. "]"
860 array_submit = array_submit .. " && " .. it .. " == " .. siz .. " - 1"
864 local addr = "&val->" .. c.name .. index
866 if has_deallocator[c.type] then
868 .. loop.free .. indent.free .. c.type .. "_free(" .. addr .. ");\n" .. loop_end.free
872 .. loop.write .. indent.write .. (compressed
873 and "raw_write_compressed(buffer, " .. addr .. ", (void *) &" .. c.type .. "_write);\n"
874 or c.type .. "_write(buffer, " .. addr .. ");\n"
878 .. loop.read .. indent.read .. "if (!" .. (compressed
879 and "raw_read_compressed(buffer, " .. addr .. ", (void *) &" .. c.type .. "_read)"
880 or c.type .. "_read(buffer, " .. addr .. ")"
881 ) .. ")\n" .. indent.read .. "\treturn false;\n" .. loop_end.read
883 local submit = ic == #t.components and "submit" .. array_submit or "false"
885 .. loop.send .. indent.send .. "if (!" .. (compressed
886 and "raw_send_compressed(peer, " .. submit .. ", " .. addr .. ", (void *) &" .. c.type .. "_write)"
887 or c.type .. "_send(peer, " .. submit .. ", " .. addr .. ")"
888 ) .. ")\n" .. indent.send .. "\treturn false;\n" .. loop_end.send
891 .. loop.recv .. indent.recv .. "if (!" .. (compressed
892 and "raw_recv_compressed(peer, " .. addr .. ", (void *) &" .. c.type .. "_read)"
893 or c.type .. "_recv(peer, " .. addr .. ")"
894 ) .. ")\n" .. indent.recv .. "\treturn false;\n" .. loop_end.recv
897 emit_h("typedef struct {\n" .. typedef .. "} " .. struct_prefix .. t.name .. ";\n")
899 if has_deallocator[t.name] then
900 emit(export_prefix .. "void " .. t.name .. "_free(" .. t.name .. " *val)", "{\n" .. free .. "}\n\n")
903 emit(export_prefix .. "void " .. t.name .. "_write(Blob *buffer, " .. t.name .. " *val)", "{\n" .. write .. "}\n\n")
904 emit(export_prefix .. "bool " .. t.name .. "_read(Blob *buffer, " .. t.name .. " *val)", "{\n" .. read .. "\treturn true;\n}\n\n")
907 emit_h("#ifdef USE_DRAGONNET\n")
910 emit_c("#ifdef USE_DRAGONNET\n")
912 emit_c(local_prefix .. "bool " .. t.name .. "_send(DragonnetPeer *peer, bool submit, " .. t.name .. " *val)\n{\n" .. send .. "\treturn true;\n}\n\n")
913 emit_c(local_prefix .. "bool " .. t.name .. "_recv(DragonnetPeer *peer, " .. t.name .. " *val)\n{\n" .. recv .. "\treturn true;\n}\n")
917 emit_c("static DragonnetTypeId " .. t.name .. "_type_id = DRAGONNET_TYPE_" .. t.name .. ";\n")
919 emit("bool dragonnet_peer_send_" .. t.name .. "(DragonnetPeer *peer, " .. t.name .. " *val)", "{\n\tpthread_mutex_lock(&peer->mtx);\n\tif (!u16_send(peer, false, &" .. t.name .. "_type_id))\n\t\treturn false;\n\tif (!" .. t.name .. "_send(peer, true, val))\n\t\treturn false;\n\treturn true;\n}\n")
922 dragonnet_types_h = dragonnet_types_h
923 .. "\tDRAGONNET_TYPE_" .. t.name .. ",\n"
925 dragonnet_types_c = dragonnet_types_c
926 .. "\t{\n\t\t.siz = sizeof(" .. t.name .. "),\n\t\t.deserialize = (void *) &" .. t.name .. "_recv,\n\t\t.free = " .. (has_deallocator[t.name] and "(void *) &" .. t.name .. "_free" or "NULL") .. ",\n\t},\n"
934 emit_h("#ifdef USE_DRAGONNET\n")
935 emit_h("typedef enum {\n" .. dragonnet_types_h .. "\tDRAGONNET_NUM_TYPES\n} DragonnetTypeNum;\n")
938 emit_c("#ifdef USE_DRAGONNET\n")
939 emit_c("DragonnetTypeId dragonnet_num_types = DRAGONNET_NUM_TYPES;\nDragonnetType dragonnet_types[] = {\n" .. dragonnet_types_c .. "};\n")