ser c frontend and c backend finished, + conversion, needs python backend
This commit is contained in:
parent
f6c5e749a6
commit
7335df0711
194
net.c
194
net.c
|
@ -2,6 +2,134 @@
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
__attribute__((unused)) static int abs_serialize(struct Abs val, byte *buf);
|
||||||
|
__attribute__((unused)) static int abs_deserialize(struct Abs *val, const byte *buf);
|
||||||
|
__attribute__((unused)) static void abs_free(struct Abs val);
|
||||||
|
__attribute__((unused)) static int key_serialize(struct Key val, byte *buf);
|
||||||
|
__attribute__((unused)) static int key_deserialize(struct Key *val, const byte *buf);
|
||||||
|
__attribute__((unused)) static void key_free(struct Key val);
|
||||||
|
__attribute__((unused)) static int rel_serialize(struct Rel val, byte *buf);
|
||||||
|
__attribute__((unused)) static int rel_deserialize(struct Rel *val, const byte *buf);
|
||||||
|
__attribute__((unused)) static void rel_free(struct Rel val);
|
||||||
|
__attribute__((unused)) static int tag_list_serialize(struct TagList val, byte *buf);
|
||||||
|
__attribute__((unused)) static int tag_list_deserialize(struct TagList *val, const byte *buf);
|
||||||
|
__attribute__((unused)) static void tag_list_free(struct TagList val);
|
||||||
|
__attribute__((unused)) static int tag_serialize(struct Tag val, byte *buf);
|
||||||
|
__attribute__((unused)) static int tag_deserialize(struct Tag *val, const byte *buf);
|
||||||
|
__attribute__((unused)) static void tag_free(struct Tag val);
|
||||||
|
|
||||||
|
static int abs_serialize(struct Abs val, byte *buf) {
|
||||||
|
byte * base_buf = buf;
|
||||||
|
*(uint32_t *)&buf[0] = val.min;
|
||||||
|
*(uint32_t *)&buf[4] = val.max;
|
||||||
|
*(uint32_t *)&buf[8] = val.fuzz;
|
||||||
|
*(uint32_t *)&buf[12] = val.flat;
|
||||||
|
*(uint32_t *)&buf[16] = val.res;
|
||||||
|
*(uint16_t *)&buf[20] = val.id;
|
||||||
|
buf += 24;
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static int abs_deserialize(struct Abs *val, const byte *buf) {
|
||||||
|
const byte * base_buf = buf;
|
||||||
|
val->min = *(uint32_t *)&buf[0];
|
||||||
|
val->max = *(uint32_t *)&buf[4];
|
||||||
|
val->fuzz = *(uint32_t *)&buf[8];
|
||||||
|
val->flat = *(uint32_t *)&buf[12];
|
||||||
|
val->res = *(uint32_t *)&buf[16];
|
||||||
|
val->id = *(uint16_t *)&buf[20];
|
||||||
|
buf += 24;
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static void abs_free(struct Abs val) { }
|
||||||
|
|
||||||
|
static int key_serialize(struct Key val, byte *buf) {
|
||||||
|
byte * base_buf = buf;
|
||||||
|
*(uint16_t *)&buf[0] = val.id;
|
||||||
|
buf += 2;
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static int key_deserialize(struct Key *val, const byte *buf) {
|
||||||
|
const byte * base_buf = buf;
|
||||||
|
val->id = *(uint16_t *)&buf[0];
|
||||||
|
buf += 2;
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static void key_free(struct Key val) { }
|
||||||
|
|
||||||
|
static int rel_serialize(struct Rel val, byte *buf) {
|
||||||
|
byte * base_buf = buf;
|
||||||
|
*(uint16_t *)&buf[0] = val.id;
|
||||||
|
buf += 2;
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static int rel_deserialize(struct Rel *val, const byte *buf) {
|
||||||
|
const byte * base_buf = buf;
|
||||||
|
val->id = *(uint16_t *)&buf[0];
|
||||||
|
buf += 2;
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static void rel_free(struct Rel val) { }
|
||||||
|
|
||||||
|
static int tag_list_serialize(struct TagList val, byte *buf) {
|
||||||
|
byte * base_buf = buf;
|
||||||
|
*(uint16_t *)&buf[0] = val.tags.len;
|
||||||
|
buf += 2;
|
||||||
|
for(size_t i = 0; i < val.tags.len; i++) {
|
||||||
|
typeof(val.tags.data[i]) e0 = val.tags.data[i];
|
||||||
|
buf += tag_serialize(e0, &buf[0]);
|
||||||
|
}
|
||||||
|
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static int tag_list_deserialize(struct TagList *val, const byte *buf) {
|
||||||
|
const byte * base_buf = buf;
|
||||||
|
val->tags.len = *(uint16_t *)&buf[0];
|
||||||
|
buf += 2;
|
||||||
|
val->tags.data = malloc(val->tags.len * sizeof(typeof(*val->tags.data)));
|
||||||
|
for(size_t i = 0; i < val->tags.len; i++) {
|
||||||
|
typeof(&val->tags.data[i]) e0 = &val->tags.data[i];
|
||||||
|
buf += tag_deserialize(e0, &buf[0]);
|
||||||
|
}
|
||||||
|
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static void tag_list_free(struct TagList val) {
|
||||||
|
for(size_t i = 0; i < val.tags.len; i++) {
|
||||||
|
typeof(val.tags.data[i]) e0 = val.tags.data[i];
|
||||||
|
tag_free(e0);
|
||||||
|
}
|
||||||
|
free(val.tags.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tag_serialize(struct Tag val, byte *buf) {
|
||||||
|
byte * base_buf = buf;
|
||||||
|
*(uint16_t *)&buf[0] = val.name.len;
|
||||||
|
buf += 2;
|
||||||
|
for(size_t i = 0; i < val.name.len; i++) {
|
||||||
|
typeof(val.name.data[i]) e0 = val.name.data[i];
|
||||||
|
*(char *)&buf[0] = e0;
|
||||||
|
buf += 1;
|
||||||
|
}
|
||||||
|
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static int tag_deserialize(struct Tag *val, const byte *buf) {
|
||||||
|
const byte * base_buf = buf;
|
||||||
|
val->name.len = *(uint16_t *)&buf[0];
|
||||||
|
buf += 2;
|
||||||
|
val->name.data = malloc(val->name.len * sizeof(typeof(*val->name.data)));
|
||||||
|
for(size_t i = 0; i < val->name.len; i++) {
|
||||||
|
typeof(&val->name.data[i]) e0 = &val->name.data[i];
|
||||||
|
*e0 = *(char *)&buf[0];
|
||||||
|
buf += 1;
|
||||||
|
}
|
||||||
|
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
|
||||||
|
return (int)(buf - base_buf);
|
||||||
|
}
|
||||||
|
static void tag_free(struct Tag val) {
|
||||||
|
free(val.name.data);
|
||||||
|
}
|
||||||
|
|
||||||
int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) {
|
int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) {
|
||||||
const byte *base_buf = buf;
|
const byte *base_buf = buf;
|
||||||
if(len < 2 * MSG_MAGIC_SIZE)
|
if(len < 2 * MSG_MAGIC_SIZE)
|
||||||
|
@ -21,23 +149,15 @@ int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) {
|
||||||
buf += 8;
|
buf += 8;
|
||||||
for(size_t i = 0; i < msg->info.abs.len; i++) {
|
for(size_t i = 0; i < msg->info.abs.len; i++) {
|
||||||
typeof(msg->info.abs.data[i]) e0 = msg->info.abs.data[i];
|
typeof(msg->info.abs.data[i]) e0 = msg->info.abs.data[i];
|
||||||
*(uint32_t *)&buf[0] = e0.min;
|
buf += abs_serialize(e0, &buf[0]);
|
||||||
*(uint32_t *)&buf[4] = e0.max;
|
|
||||||
*(uint32_t *)&buf[8] = e0.fuzz;
|
|
||||||
*(uint32_t *)&buf[12] = e0.flat;
|
|
||||||
*(uint32_t *)&buf[16] = e0.res;
|
|
||||||
*(uint16_t *)&buf[20] = e0.id;
|
|
||||||
buf += 24;
|
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < msg->info.rel.len; i++) {
|
for(size_t i = 0; i < msg->info.rel.len; i++) {
|
||||||
typeof(msg->info.rel.data[i]) e0 = msg->info.rel.data[i];
|
typeof(msg->info.rel.data[i]) e0 = msg->info.rel.data[i];
|
||||||
*(uint16_t *)&buf[0] = e0.id;
|
buf += rel_serialize(e0, &buf[0]);
|
||||||
buf += 2;
|
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < msg->info.key.len; i++) {
|
for(size_t i = 0; i < msg->info.key.len; i++) {
|
||||||
typeof(msg->info.key.data[i]) e0 = msg->info.key.data[i];
|
typeof(msg->info.key.data[i]) e0 = msg->info.key.data[i];
|
||||||
*(uint16_t *)&buf[0] = e0.id;
|
buf += key_serialize(e0, &buf[0]);
|
||||||
buf += 2;
|
|
||||||
}
|
}
|
||||||
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
|
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
|
||||||
break;
|
break;
|
||||||
|
@ -89,20 +209,7 @@ int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) {
|
||||||
buf += 18;
|
buf += 18;
|
||||||
for(size_t i = 0; i < msg->request.requests.len; i++) {
|
for(size_t i = 0; i < msg->request.requests.len; i++) {
|
||||||
typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i];
|
typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i];
|
||||||
*(uint16_t *)&buf[0] = e0.tags.len;
|
buf += tag_list_serialize(e0, &buf[0]);
|
||||||
buf += 2;
|
|
||||||
for(size_t i = 0; i < e0.tags.len; i++) {
|
|
||||||
typeof(e0.tags.data[i]) e1 = e0.tags.data[i];
|
|
||||||
*(uint16_t *)&buf[0] = e1.name.len;
|
|
||||||
buf += 2;
|
|
||||||
for(size_t i = 0; i < e1.name.len; i++) {
|
|
||||||
typeof(e1.name.data[i]) e2 = e1.name.data[i];
|
|
||||||
*(char *)&buf[0] = e2;
|
|
||||||
buf += 1;
|
|
||||||
}
|
|
||||||
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
|
|
||||||
}
|
|
||||||
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
|
|
||||||
}
|
}
|
||||||
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
|
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
|
||||||
break;
|
break;
|
||||||
|
@ -142,23 +249,15 @@ int msg_device_deserialize(const byte *buf, size_t len, DeviceMessage *msg) {
|
||||||
buf += 8;
|
buf += 8;
|
||||||
for(size_t i = 0; i < msg->info.abs.len; i++) {
|
for(size_t i = 0; i < msg->info.abs.len; i++) {
|
||||||
typeof(&msg->info.abs.data[i]) e0 = &msg->info.abs.data[i];
|
typeof(&msg->info.abs.data[i]) e0 = &msg->info.abs.data[i];
|
||||||
e0->min = *(uint32_t *)&buf[0];
|
buf += abs_deserialize(e0, &buf[0]);
|
||||||
e0->max = *(uint32_t *)&buf[4];
|
|
||||||
e0->fuzz = *(uint32_t *)&buf[8];
|
|
||||||
e0->flat = *(uint32_t *)&buf[12];
|
|
||||||
e0->res = *(uint32_t *)&buf[16];
|
|
||||||
e0->id = *(uint16_t *)&buf[20];
|
|
||||||
buf += 24;
|
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < msg->info.rel.len; i++) {
|
for(size_t i = 0; i < msg->info.rel.len; i++) {
|
||||||
typeof(&msg->info.rel.data[i]) e0 = &msg->info.rel.data[i];
|
typeof(&msg->info.rel.data[i]) e0 = &msg->info.rel.data[i];
|
||||||
e0->id = *(uint16_t *)&buf[0];
|
buf += rel_deserialize(e0, &buf[0]);
|
||||||
buf += 2;
|
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < msg->info.key.len; i++) {
|
for(size_t i = 0; i < msg->info.key.len; i++) {
|
||||||
typeof(&msg->info.key.data[i]) e0 = &msg->info.key.data[i];
|
typeof(&msg->info.key.data[i]) e0 = &msg->info.key.data[i];
|
||||||
e0->id = *(uint16_t *)&buf[0];
|
buf += key_deserialize(e0, &buf[0]);
|
||||||
buf += 2;
|
|
||||||
}
|
}
|
||||||
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
|
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
|
||||||
break;
|
break;
|
||||||
|
@ -210,22 +309,7 @@ int msg_device_deserialize(const byte *buf, size_t len, DeviceMessage *msg) {
|
||||||
msg->request.requests.data = malloc(msg->request.requests.len * sizeof(typeof(*msg->request.requests.data)));
|
msg->request.requests.data = malloc(msg->request.requests.len * sizeof(typeof(*msg->request.requests.data)));
|
||||||
for(size_t i = 0; i < msg->request.requests.len; i++) {
|
for(size_t i = 0; i < msg->request.requests.len; i++) {
|
||||||
typeof(&msg->request.requests.data[i]) e0 = &msg->request.requests.data[i];
|
typeof(&msg->request.requests.data[i]) e0 = &msg->request.requests.data[i];
|
||||||
e0->tags.len = *(uint16_t *)&buf[0];
|
buf += tag_list_deserialize(e0, &buf[0]);
|
||||||
buf += 2;
|
|
||||||
e0->tags.data = malloc(e0->tags.len * sizeof(typeof(*e0->tags.data)));
|
|
||||||
for(size_t i = 0; i < e0->tags.len; i++) {
|
|
||||||
typeof(&e0->tags.data[i]) e1 = &e0->tags.data[i];
|
|
||||||
e1->name.len = *(uint16_t *)&buf[0];
|
|
||||||
buf += 2;
|
|
||||||
e1->name.data = malloc(e1->name.len * sizeof(typeof(*e1->name.data)));
|
|
||||||
for(size_t i = 0; i < e1->name.len; i++) {
|
|
||||||
typeof(&e1->name.data[i]) e2 = &e1->name.data[i];
|
|
||||||
*e2 = *(char *)&buf[0];
|
|
||||||
buf += 1;
|
|
||||||
}
|
|
||||||
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
|
|
||||||
}
|
|
||||||
buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1);
|
|
||||||
}
|
}
|
||||||
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
|
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
|
||||||
if(msg->request._version != 1UL) {
|
if(msg->request._version != 1UL) {
|
||||||
|
@ -270,11 +354,7 @@ void msg_device_free(DeviceMessage *msg) {
|
||||||
case DeviceTagRequest: {
|
case DeviceTagRequest: {
|
||||||
for(size_t i = 0; i < msg->request.requests.len; i++) {
|
for(size_t i = 0; i < msg->request.requests.len; i++) {
|
||||||
typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i];
|
typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i];
|
||||||
for(size_t i = 0; i < e0.tags.len; i++) {
|
tag_list_free(e0);
|
||||||
typeof(e0.tags.data[i]) e1 = e0.tags.data[i];
|
|
||||||
free(e1.name.data);
|
|
||||||
}
|
|
||||||
free(e0.tags.data);
|
|
||||||
}
|
}
|
||||||
free(msg->request.requests.data);
|
free(msg->request.requests.data);
|
||||||
break;
|
break;
|
||||||
|
|
14
net.h
14
net.h
|
@ -29,13 +29,6 @@ typedef struct Rel {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
} Rel;
|
} Rel;
|
||||||
|
|
||||||
typedef struct Tag {
|
|
||||||
struct {
|
|
||||||
uint16_t len;
|
|
||||||
char *data;
|
|
||||||
} name;
|
|
||||||
} Tag;
|
|
||||||
|
|
||||||
typedef struct TagList {
|
typedef struct TagList {
|
||||||
struct {
|
struct {
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
|
@ -43,6 +36,13 @@ typedef struct TagList {
|
||||||
} tags;
|
} tags;
|
||||||
} TagList;
|
} TagList;
|
||||||
|
|
||||||
|
typedef struct Tag {
|
||||||
|
struct {
|
||||||
|
uint16_t len;
|
||||||
|
char *data;
|
||||||
|
} name;
|
||||||
|
} Tag;
|
||||||
|
|
||||||
// Device
|
// Device
|
||||||
|
|
||||||
typedef enum DeviceTag {
|
typedef enum DeviceTag {
|
||||||
|
|
|
@ -36,6 +36,8 @@ static void file_writer_format(void *w, const char *fmt, va_list args) {
|
||||||
FileWriter *fw = (FileWriter *)w;
|
FileWriter *fw = (FileWriter *)w;
|
||||||
vfprintf(fw->fd, fmt, args);
|
vfprintf(fw->fd, fmt, args);
|
||||||
}
|
}
|
||||||
|
static void null_writer_write(void *w, const char *data, size_t len) { }
|
||||||
|
static void null_writer_format(void *w, const char *fmt, va_list args) { }
|
||||||
|
|
||||||
BufferedWriter buffered_writer_init() {
|
BufferedWriter buffered_writer_init() {
|
||||||
CharVec buf = vec_init();
|
CharVec buf = vec_init();
|
||||||
|
@ -52,6 +54,9 @@ FileWriter file_writer_from_fd(FILE *fd) {
|
||||||
return (FileWriter){.w.write = file_writer_write, .w.format = file_writer_format, .fd = fd};
|
return (FileWriter){.w.write = file_writer_write, .w.format = file_writer_format, .fd = fd};
|
||||||
}
|
}
|
||||||
void file_writer_drop(FileWriter w) { fclose(w.fd); }
|
void file_writer_drop(FileWriter w) { fclose(w.fd); }
|
||||||
|
NullWriter null_writer_init() {
|
||||||
|
return (NullWriter){.w.write = null_writer_write, .w.format = null_writer_format};
|
||||||
|
}
|
||||||
|
|
||||||
void wt_write(Writer *w, const char *data, size_t len) { w->write(w, data, len); }
|
void wt_write(Writer *w, const char *data, size_t len) { w->write(w, data, len); }
|
||||||
void wt_format(Writer *w, const char *fmt, ...) {
|
void wt_format(Writer *w, const char *fmt, ...) {
|
||||||
|
@ -82,7 +87,7 @@ int struct_object_compare(const void *a, const void *b) {
|
||||||
return strncmp(sa->name.ptr, sb->name.ptr, len);
|
return strncmp(sa->name.ptr, sb->name.ptr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *obj)) {
|
void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *obj, void *), void * user_data) {
|
||||||
Hashmap *dependencies = hashmap_init(strdeps_hash, strdeps_equal, strdeps_drop, sizeof(StructDependencies));
|
Hashmap *dependencies = hashmap_init(strdeps_hash, strdeps_equal, strdeps_drop, sizeof(StructDependencies));
|
||||||
|
|
||||||
TypeDef *td = NULL;
|
TypeDef *td = NULL;
|
||||||
|
@ -132,7 +137,7 @@ void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObjec
|
||||||
|
|
||||||
for (size_t i = 0; i < to_define.len; i++) {
|
for (size_t i = 0; i < to_define.len; i++) {
|
||||||
StructObject *s = to_define.data[i];
|
StructObject *s = to_define.data[i];
|
||||||
define(w, s);
|
define(w, s, user_data);
|
||||||
hashmap_delete(dependencies, &(StructDependencies){.obj = s});
|
hashmap_delete(dependencies, &(StructDependencies){.obj = s});
|
||||||
}
|
}
|
||||||
pass++;
|
pass++;
|
||||||
|
|
|
@ -29,17 +29,22 @@ typedef struct {
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
} FileWriter;
|
} FileWriter;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Writer w;
|
||||||
|
} NullWriter;
|
||||||
|
|
||||||
BufferedWriter buffered_writer_init();
|
BufferedWriter buffered_writer_init();
|
||||||
void buffered_writer_drop(BufferedWriter w);
|
void buffered_writer_drop(BufferedWriter w);
|
||||||
FileWriter file_writer_init(const char *path);
|
FileWriter file_writer_init(const char *path);
|
||||||
FileWriter file_writer_from_fd(FILE *fd);
|
FileWriter file_writer_from_fd(FILE *fd);
|
||||||
void file_writer_drop(FileWriter w);
|
void file_writer_drop(FileWriter w);
|
||||||
|
NullWriter null_writer_init();
|
||||||
|
|
||||||
void wt_write(Writer *w, const char *data, size_t len);
|
void wt_write(Writer *w, const char *data, size_t len);
|
||||||
void wt_format(Writer *w, const char *fmt, ...);
|
void wt_format(Writer *w, const char *fmt, ...);
|
||||||
|
|
||||||
// Define the structs of a program in the correct order (respecting direct dependencies)
|
// Define the structs of a program in the correct order (respecting direct dependencies)
|
||||||
void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *));
|
void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *, void *), void *user_data);
|
||||||
char *pascal_to_snake_case(StringSlice str);
|
char *pascal_to_snake_case(StringSlice str);
|
||||||
char *snake_case_to_screaming_snake_case(StringSlice str);
|
char *snake_case_to_screaming_snake_case(StringSlice str);
|
||||||
|
|
||||||
|
|
110
ser/codegen_c.c
110
ser/codegen_c.c
|
@ -3,6 +3,8 @@
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
#include "vector_impl.h"
|
#include "vector_impl.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#define INDENT 4
|
#define INDENT 4
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -183,7 +185,7 @@ void write_field(Writer *w, Field f, Modifier *mods, size_t len, uint32_t indent
|
||||||
_vec_modifier_drop(modifiers);
|
_vec_modifier_drop(modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_struct(Writer *w, StructObject *obj) {
|
void write_struct(Writer *w, StructObject *obj, void *_user_data) {
|
||||||
wt_format(w, "typedef struct %.*s {\n", obj->name.len, obj->name.ptr);
|
wt_format(w, "typedef struct %.*s {\n", obj->name.len, obj->name.ptr);
|
||||||
|
|
||||||
for (size_t i = 0; i < obj->fields.len; i++) {
|
for (size_t i = 0; i < obj->fields.len; i++) {
|
||||||
|
@ -281,7 +283,7 @@ bool is_field_accessor_heap_array(FieldAccessor fa, TypeObject *base_type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_type_serialization(
|
void write_type_serialization(
|
||||||
Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth
|
Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth, bool always_inline
|
||||||
) {
|
) {
|
||||||
if (layout->fields.len == 0)
|
if (layout->fields.len == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -291,6 +293,14 @@ void write_type_serialization(
|
||||||
|
|
||||||
offset += calign_to(al, layout->fields.data[0].type->align);
|
offset += calign_to(al, layout->fields.data[0].type->align);
|
||||||
|
|
||||||
|
if (layout->type->kind == TypeStruct && layout->type->type.struct_.has_funcs && !always_inline) {
|
||||||
|
char *name = pascal_to_snake_case(layout->type->type.struct_.name);
|
||||||
|
char *deref = ptr ? "*" : "";
|
||||||
|
wt_format(w, "%*sbuf += %s_serialize(%s%s, &buf[%lu]);\n", indent, "", name, deref, base, offset);
|
||||||
|
free(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (; i < layout->fields.len && layout->fields.data[i].size != 0; i++) {
|
for (; i < layout->fields.len && layout->fields.data[i].size != 0; i++) {
|
||||||
FieldAccessor fa = layout->fields.data[i];
|
FieldAccessor fa = layout->fields.data[i];
|
||||||
|
@ -334,7 +344,8 @@ void write_type_serialization(
|
||||||
(CurrentAlignment){.align = farr.type->align, .offset = 0},
|
(CurrentAlignment){.align = farr.type->align, .offset = 0},
|
||||||
layouts,
|
layouts,
|
||||||
indent + INDENT,
|
indent + INDENT,
|
||||||
depth + 1
|
depth + 1,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
wt_format(w, "%*s}\n", indent, "");
|
wt_format(w, "%*s}\n", indent, "");
|
||||||
free(vname);
|
free(vname);
|
||||||
|
@ -347,7 +358,7 @@ void write_type_serialization(
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_type_deserialization(
|
void write_type_deserialization(
|
||||||
Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth
|
Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth, bool always_inline
|
||||||
) {
|
) {
|
||||||
if (layout->fields.len == 0)
|
if (layout->fields.len == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -357,6 +368,14 @@ void write_type_deserialization(
|
||||||
|
|
||||||
offset += calign_to(al, layout->fields.data[0].type->align);
|
offset += calign_to(al, layout->fields.data[0].type->align);
|
||||||
|
|
||||||
|
if (layout->type->kind == TypeStruct && layout->type->type.struct_.has_funcs && !always_inline) {
|
||||||
|
char *name = pascal_to_snake_case(layout->type->type.struct_.name);
|
||||||
|
char *ref = ptr ? "" : "&";
|
||||||
|
wt_format(w, "%*sbuf += %s_deserialize(%s%s, &buf[%lu]);\n", indent, "", name, ref, base, offset);
|
||||||
|
free(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char *deref = "";
|
char *deref = "";
|
||||||
if (layout->type->kind == TypePrimitif) {
|
if (layout->type->kind == TypePrimitif) {
|
||||||
deref = "*";
|
deref = "*";
|
||||||
|
@ -415,7 +434,8 @@ void write_type_deserialization(
|
||||||
(CurrentAlignment){.align = farr.type->align, .offset = 0},
|
(CurrentAlignment){.align = farr.type->align, .offset = 0},
|
||||||
layouts,
|
layouts,
|
||||||
indent + INDENT,
|
indent + INDENT,
|
||||||
depth + 1
|
depth + 1,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
wt_format(w, "%*s}\n", indent, "");
|
wt_format(w, "%*s}\n", indent, "");
|
||||||
free(vname);
|
free(vname);
|
||||||
|
@ -427,7 +447,7 @@ void write_type_deserialization(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent, size_t depth) {
|
int write_type_free(Writer *w, const char *base, TypeObject *type, Hashmap *layouts, size_t indent, size_t depth, bool always_inline) {
|
||||||
if (type->kind == TypePrimitif) {
|
if (type->kind == TypePrimitif) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (type->kind == TypeArray) {
|
} else if (type->kind == TypeArray) {
|
||||||
|
@ -446,7 +466,7 @@ int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent
|
||||||
}
|
}
|
||||||
|
|
||||||
char *new_base = msprintf("e%lu", depth);
|
char *new_base = msprintf("e%lu", depth);
|
||||||
total += write_type_free(w2, new_base, type->type.array.type, indent + INDENT, depth + 1);
|
total += write_type_free(w2, new_base, type->type.array.type, layouts, indent + INDENT, depth + 1, false);
|
||||||
free(new_base);
|
free(new_base);
|
||||||
wt_format(w2, "%*s}\n", indent, "");
|
wt_format(w2, "%*s}\n", indent, "");
|
||||||
|
|
||||||
|
@ -465,10 +485,24 @@ int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent
|
||||||
StructObject *s = (StructObject *)&type->type.struct_;
|
StructObject *s = (StructObject *)&type->type.struct_;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|
||||||
|
if(type->type.struct_.has_funcs && !always_inline) {
|
||||||
|
char *name = pascal_to_snake_case(s->name);
|
||||||
|
wt_format(w, "%*s%s_free(%s);\n", indent, "", name, base);
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
Layout *layout = hashmap_get(layouts, &(Layout){.type = type});
|
||||||
|
assert(layout != NULL, "No layout for type that has funcs defined");
|
||||||
|
for(size_t i = 0; i < layout->fields.len; i++) {
|
||||||
|
if(layout->fields.data[i].size == 0) total++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < s->fields.len; i++) {
|
for (size_t i = 0; i < s->fields.len; i++) {
|
||||||
Field f = s->fields.data[i];
|
Field f = s->fields.data[i];
|
||||||
char *new_base = msprintf("%s.%.*s", base, f.name.len, f.name.ptr);
|
char *new_base = msprintf("%s.%.*s", base, f.name.len, f.name.ptr);
|
||||||
total += write_type_free(w, new_base, f.type, indent, depth);
|
total += write_type_free(w, new_base, f.type, layouts, indent, depth, false);
|
||||||
free(new_base);
|
free(new_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,6 +512,52 @@ int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_struct_func_decl(Writer *w, StructObject *obj, void *_user_data) {
|
||||||
|
obj->has_funcs = true;
|
||||||
|
|
||||||
|
StringSlice sname = obj->name;
|
||||||
|
char *snake_case_name = pascal_to_snake_case(sname);
|
||||||
|
wt_format(w, "__attribute__((unused)) static int %s_serialize(struct %.*s val, byte *buf);\n", snake_case_name, sname.len, sname.ptr);
|
||||||
|
wt_format(w, "__attribute__((unused)) static int %s_deserialize(struct %.*s *val, const byte *buf);\n", snake_case_name, sname.len, sname.ptr);
|
||||||
|
wt_format(w, "__attribute__((unused)) static void %s_free(struct %.*s val);\n", snake_case_name, sname.len, sname.ptr);
|
||||||
|
free(snake_case_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_struct_func(Writer *w, StructObject *obj, void *user_data) {
|
||||||
|
Hashmap *layouts = user_data;
|
||||||
|
// Retreive original TypeObject pointer from struct object pointer.
|
||||||
|
TypeObject *t = (void *)((byte *)obj - offsetof(struct TypeObject, type));
|
||||||
|
|
||||||
|
Layout *layout = hashmap_get(layouts, &(Layout){.type = t});
|
||||||
|
assert(layout != NULL, "No layout found for struct");
|
||||||
|
|
||||||
|
StringSlice sname = obj->name;
|
||||||
|
char *snake_case_name = pascal_to_snake_case(sname);
|
||||||
|
wt_format(w, "static int %s_serialize(struct %.*s val, byte *buf) {\n", snake_case_name, sname.len, sname.ptr);
|
||||||
|
wt_format(w, "%*sbyte * base_buf = buf;\n", INDENT, "");
|
||||||
|
write_type_serialization(w, "val", false, layout, (CurrentAlignment){.offset = 0, .align = t->align}, layouts, INDENT, 0, true);
|
||||||
|
wt_format(w, "%*sreturn (int)(buf - base_buf);\n", INDENT, "");
|
||||||
|
wt_format(w, "}\n");
|
||||||
|
|
||||||
|
wt_format(w, "static int %s_deserialize(struct %.*s *val, const byte *buf) {\n", snake_case_name, sname.len, sname.ptr);
|
||||||
|
wt_format(w, "%*sconst byte * base_buf = buf;\n", INDENT, "");
|
||||||
|
write_type_deserialization(w, "val", true, layout, (CurrentAlignment){.offset = 0, .align = t->align}, layouts, INDENT, 0, true);
|
||||||
|
wt_format(w, "%*sreturn (int)(buf - base_buf);\n", INDENT, "");
|
||||||
|
wt_format(w, "}\n");
|
||||||
|
|
||||||
|
wt_format(w, "static void %s_free(struct %.*s val) {", snake_case_name, sname.len, sname.ptr);
|
||||||
|
BufferedWriter b = buffered_writer_init();
|
||||||
|
int f = write_type_free((Writer*)&b, "val", t, layouts, INDENT, 0, true);
|
||||||
|
if(f > 0) {
|
||||||
|
wt_format(w, "\n%.*s}\n\n", b.buf.len, b.buf.data);
|
||||||
|
} else {
|
||||||
|
wt_format(w, " }\n\n");
|
||||||
|
}
|
||||||
|
buffered_writer_drop(b);
|
||||||
|
|
||||||
|
free(snake_case_name);
|
||||||
|
}
|
||||||
|
|
||||||
void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
|
void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
|
||||||
char *uc_name = snake_case_to_screaming_snake_case((StringSlice){.ptr = name, .len = strlen(name)});
|
char *uc_name = snake_case_to_screaming_snake_case((StringSlice){.ptr = name, .len = strlen(name)});
|
||||||
wt_format(
|
wt_format(
|
||||||
|
@ -509,7 +589,10 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
|
||||||
name
|
name
|
||||||
);
|
);
|
||||||
|
|
||||||
define_structs(p, header, write_struct);
|
define_structs(p, header, write_struct, NULL);
|
||||||
|
define_structs(p, source, write_struct_func_decl, NULL);
|
||||||
|
wt_format(source, "\n");
|
||||||
|
define_structs(p, source, write_struct_func, p->layouts);
|
||||||
|
|
||||||
for (size_t i = 0; i < p->messages.len; i++) {
|
for (size_t i = 0; i < p->messages.len; i++) {
|
||||||
MessagesObject msgs = p->messages.data[i];
|
MessagesObject msgs = p->messages.data[i];
|
||||||
|
@ -664,7 +747,8 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
|
||||||
(CurrentAlignment){.align = ALIGN_8, .offset = 2},
|
(CurrentAlignment){.align = ALIGN_8, .offset = 2},
|
||||||
p->layouts,
|
p->layouts,
|
||||||
INDENT * 2,
|
INDENT * 2,
|
||||||
0
|
0,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, "");
|
wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, "");
|
||||||
|
|
||||||
|
@ -699,7 +783,6 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
|
||||||
wt_format(source, "%*sswitch(tag) {\n", INDENT, "");
|
wt_format(source, "%*sswitch(tag) {\n", INDENT, "");
|
||||||
wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, "");
|
wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, "");
|
||||||
|
|
||||||
|
|
||||||
for (size_t j = 0; j < msgs.messages.len; j++) {
|
for (size_t j = 0; j < msgs.messages.len; j++) {
|
||||||
MessageObject m = msgs.messages.data[j];
|
MessageObject m = msgs.messages.data[j];
|
||||||
TypeObject *mtype = message_tos.data[j];
|
TypeObject *mtype = message_tos.data[j];
|
||||||
|
@ -718,7 +801,8 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
|
||||||
(CurrentAlignment){.align = ALIGN_8, .offset = 2},
|
(CurrentAlignment){.align = ALIGN_8, .offset = 2},
|
||||||
p->layouts,
|
p->layouts,
|
||||||
INDENT * 2,
|
INDENT * 2,
|
||||||
0
|
0,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
if (m.attributes & Attr_versioned) {
|
if (m.attributes & Attr_versioned) {
|
||||||
wt_format(source, "%*sif(msg->%s._version != %luUL) {\n", INDENT * 2, "", snake_case_name, msgs.version);
|
wt_format(source, "%*sif(msg->%s._version != %luUL) {\n", INDENT * 2, "", snake_case_name, msgs.version);
|
||||||
|
@ -761,7 +845,7 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
|
||||||
char *base = msprintf("msg->%s", snake_case_name);
|
char *base = msprintf("msg->%s", snake_case_name);
|
||||||
|
|
||||||
wt_format(source, "%*scase %s%.*s: {\n", INDENT, "", tag_type, m.name.len, m.name.ptr);
|
wt_format(source, "%*scase %s%.*s: {\n", INDENT, "", tag_type, m.name.len, m.name.ptr);
|
||||||
write_type_free(source, base, mtype, INDENT * 2, 0);
|
write_type_free(source, base, mtype, p->layouts, INDENT * 2, 0, false);
|
||||||
wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, "");
|
wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, "");
|
||||||
|
|
||||||
free(base);
|
free(base);
|
||||||
|
|
|
@ -579,6 +579,7 @@ static TypeObject *resolve_type(EvaluationContext *ctx, SpannedStringSlice name)
|
||||||
value->kind = TypeStruct;
|
value->kind = TypeStruct;
|
||||||
value->type.struct_.fields = *(AnyVec *)&fields;
|
value->type.struct_.fields = *(AnyVec *)&fields;
|
||||||
value->type.struct_.name = name.slice;
|
value->type.struct_.name = name.slice;
|
||||||
|
value->type.struct_.has_funcs = false;
|
||||||
value->align.value = 0;
|
value->align.value = 0;
|
||||||
hashmap_set(ctx->typedefs, &(TypeDef){.name = name.slice, .value = value});
|
hashmap_set(ctx->typedefs, &(TypeDef){.name = name.slice, .value = value});
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,8 @@ typedef enum {
|
||||||
struct StructObject {
|
struct StructObject {
|
||||||
StringSlice name;
|
StringSlice name;
|
||||||
AnyVec fields;
|
AnyVec fields;
|
||||||
|
// Used by codegen_c
|
||||||
|
bool has_funcs;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
@ -97,6 +99,8 @@ VECTOR_IMPL(Field, FieldVec, field);
|
||||||
typedef struct {
|
typedef struct {
|
||||||
StringSlice name;
|
StringSlice name;
|
||||||
FieldVec fields;
|
FieldVec fields;
|
||||||
|
// Used by codegen_c
|
||||||
|
bool has_funcs;
|
||||||
} StructObject;
|
} StructObject;
|
||||||
|
|
||||||
void struct_drop(StructObject s);
|
void struct_drop(StructObject s);
|
||||||
|
|
Loading…
Reference in New Issue