summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rt_struct.c49
-rw-r--r--rt_struct.h123
2 files changed, 172 insertions, 0 deletions
diff --git a/rt_struct.c b/rt_struct.c
new file mode 100644
index 0000000..314407c
--- /dev/null
+++ b/rt_struct.c
@@ -0,0 +1,49 @@
+#include <stdlib.h>
+#include <string.h>
+#include "macros.h"
+#include "rt_struct.h"
+
+static int is_root_type(rts_type_tag tag) {
+ return tag != TAG_STRUCT && tag != TAG_UNION;
+}
+
+int create_rts(rts_type *type) {
+ if (type == NULL) {
+ return 1;
+ }
+
+ if (is_root_type(type->tag)) {
+ return 0;
+ }
+
+ if (type->members == NULL || type->members[0] == NULL) {
+ return 1;
+ } else {
+ size_t offset = 0;
+ size_t max_align = 0;
+ size_t remainder = 0;
+ size_t padding = 0;
+ rts_member **members = type->members;
+ for (int i = 0; members[i] != NULL; ++i) {
+ rts_type *member_type = members[i]->type;
+ if (create_rts(member_type)) {
+ return 1;
+ } else {
+ const size_t align = member_type->alignment;
+ max_align = max(max_align, align);
+ if (type->tag == TAG_STRUCT) {
+ remainder = offset % align;
+ padding = (remainder) ? align - remainder : 0;
+ offset += padding;
+ type->offsets[i] = offset;
+ offset += member_type->size;
+ }
+ }
+ }
+ type->alignment = max_align;
+ remainder = offset % max_align;
+ padding = (remainder) ? max_align - remainder : 0;
+ type->size = offset + padding;
+ return 0;
+ }
+}
diff --git a/rt_struct.h b/rt_struct.h
new file mode 100644
index 0000000..b1ccd5f
--- /dev/null
+++ b/rt_struct.h
@@ -0,0 +1,123 @@
+#ifndef RT_STRUCT_H
+#define RT_STRUCT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <time.h>
+
+typedef enum rts_type_tag rts_type_tag;
+typedef struct rts_type rts_type;
+typedef struct rts_member rts_member;
+
+enum rts_type_tag {
+ TAG_UINT,
+ TAG_SINT,
+ TAG_INT = TAG_SINT,
+ TAG_UCHAR,
+ TAG_SCHAR,
+ TAG_CHAR,
+ TAG_USHORT,
+ TAG_SSHORT,
+ TAG_SHORT = TAG_SSHORT,
+ TAG_ULONG,
+ TAG_SLONG,
+ TAG_LONG = TAG_SLONG,
+ TAG_ULONGLONG,
+ TAG_SLONGLONG,
+ TAG_LONGLONG = TAG_SLONGLONG,
+ TAG_FLOAT,
+ TAG_DOUBLE,
+ TAG_LONGDOUBLE,
+ TAG_TIME,
+ TAG_SIZE,
+ TAG_UINT8,
+ TAG_INT8,
+ TAG_UINT16,
+ TAG_INT16,
+ TAG_UINT32,
+ TAG_INT32,
+ TAG_UINT64,
+ TAG_INT64,
+ TAG_POINTER,
+ TAG_STRUCT,
+ TAG_UNION,
+ NUM_TAG
+};
+
+struct rts_type {
+ rts_type_tag tag; /* Type Tag. */
+ char *name; /* Name of type. */
+ int is_packed; /* Packed type flag. */
+ size_t alignment; /* Alignment of type. */
+ size_t size; /* Size of type. */
+ rts_member **members; /* Member(s) of type. */
+ size_t *offsets; /* Offset(s) of type. */
+};
+
+struct rts_member {
+ char *name; /* Name of member. */
+ int ptr_count; /* Pointer count of member. */
+ int arr_count; /* Array dimension count of member. */
+ rts_type *type; /* Type of member. */
+};
+
+#define TYPEDEF_RTS(name, type) \
+ struct _align_##name { \
+ char c; \
+ type x; \
+ }; \
+ static const rts_type RTS_TYPE_##name = { \
+ TAG_##name, \
+ NULL, \
+ 0, \
+ offsetof(struct _align_##name, x), \
+ sizeof(type), \
+ NULL, NULL \
+ } \
+
+TYPEDEF_RTS(UINT, unsigned int);
+TYPEDEF_RTS(SINT, signed int);
+TYPEDEF_RTS(INT, int);
+
+TYPEDEF_RTS(UCHAR, unsigned char);
+TYPEDEF_RTS(SCHAR, signed char);
+TYPEDEF_RTS(CHAR, char);
+
+TYPEDEF_RTS(USHORT, unsigned short);
+TYPEDEF_RTS(SSHORT, signed short);
+TYPEDEF_RTS(SHORT, short);
+
+TYPEDEF_RTS(ULONG, unsigned long);
+TYPEDEF_RTS(SLONG, signed long);
+TYPEDEF_RTS(LONG, long);
+
+TYPEDEF_RTS(ULONGLONG, unsigned long long);
+TYPEDEF_RTS(SLONGLONG, signed long long);
+TYPEDEF_RTS(LONGLONG, long long);
+
+TYPEDEF_RTS(FLOAT, float);
+TYPEDEF_RTS(DOUBLE, double);
+TYPEDEF_RTS(LONGDOUBLE, long double);
+
+TYPEDEF_RTS(TIME, time_t);
+TYPEDEF_RTS(SIZE, size_t);
+
+TYPEDEF_RTS(UINT8, uint8_t);
+TYPEDEF_RTS(INT8, int8_t);
+
+TYPEDEF_RTS(UINT16, uint16_t);
+TYPEDEF_RTS(INT16, int16_t);
+
+TYPEDEF_RTS(UINT32, uint32_t);
+TYPEDEF_RTS(INT32, int32_t);
+
+TYPEDEF_RTS(UINT64, uint64_t);
+TYPEDEF_RTS(INT64, int64_t);
+
+TYPEDEF_RTS(POINTER, void *);
+
+#undef TYPEDEF_RTS
+
+extern int create_rts(rts_type *type);
+
+#endif