summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ast.c108
-rw-r--r--ast.h17
2 files changed, 123 insertions, 2 deletions
diff --git a/ast.c b/ast.c
index 0b07e10..5d42b56 100644
--- a/ast.c
+++ b/ast.c
@@ -24,6 +24,9 @@
#include <string.h>
#include <math.h>
+static size_t ut_ext_types_count = 0;
+static struct ut_extended_type *ut_ext_types = NULL;
+
struct ut_opcode *
ut_new_op(struct ut_state *s, int type, struct json_object *val, ...)
{
@@ -191,8 +194,7 @@ ut_free(struct ut_state *s)
for (op = s->pool; op;) {
tmp = op->next;
- if (op->val != (void *)1)
- json_object_put(op->val);
+ json_object_put(op->val);
free(op);
op = tmp;
@@ -201,6 +203,7 @@ ut_free(struct ut_state *s)
ut_reset(s);
}
+ free(ut_ext_types);
free(s);
}
@@ -248,3 +251,104 @@ out:
return s->error.code;
}
+
+bool
+ut_register_extended_type(const char *name, void (*freefn)(void *))
+{
+ struct ut_extended_type *tmp;
+
+ tmp = realloc(ut_ext_types, (ut_ext_types_count + 1) * sizeof(*tmp));
+
+ if (!tmp)
+ return false;
+
+ ut_ext_types = tmp;
+ ut_ext_types[ut_ext_types_count].name = name;
+ ut_ext_types[ut_ext_types_count].free = freefn;
+ ut_ext_types_count++;
+
+ return true;
+}
+
+static int
+ut_extended_type_to_string(struct json_object *v, struct printbuf *pb, int level, int flags)
+{
+ struct ut_tagvalue *tag = json_object_get_userdata(v);
+ struct ut_extended_type *et;
+
+ if (!tag)
+ return 0;
+
+ et = &ut_ext_types[tag->tagtype - 1];
+
+ return sprintbuf(pb, "%s<%s %p>%s", level ? "\"" : "", et->name, tag->data, level ? "\"" : "");
+}
+
+static void
+ut_extended_type_free(struct json_object *v, void *ud)
+{
+ struct ut_tagvalue *tag = json_object_get_userdata(v);
+ struct ut_extended_type *et;
+
+ if (!tag)
+ return;
+
+ et = &ut_ext_types[tag->tagtype - 1];
+
+ if (et->free)
+ et->free(tag->data);
+
+ json_object_put(tag->proto);
+ free(ud);
+}
+
+struct json_object *
+ut_set_extended_type(struct ut_state *s, struct json_object *v, struct json_object *proto, const char *name, void *data)
+{
+ struct ut_extended_type *et = NULL;
+ struct ut_tagvalue *tag;
+ size_t n;
+
+ for (n = 0; n < ut_ext_types_count; n++) {
+ if (!strcmp(name, ut_ext_types[n].name)) {
+ et = &ut_ext_types[n];
+ break;
+ }
+ }
+
+ if (!et)
+ return NULL;
+
+ tag = calloc(1, sizeof(*tag));
+
+ if (!tag)
+ return NULL;
+
+ tag->val = v;
+ tag->type = T_RESSOURCE;
+ tag->proto = json_object_get(proto);
+ tag->tagtype = n + 1;
+ tag->data = data;
+
+ json_object_set_serializer(tag->val, ut_extended_type_to_string, tag, ut_extended_type_free);
+
+ return tag->val;
+}
+
+void **
+ut_get_extended_type(struct json_object *v, const char *name)
+{
+ struct ut_tagvalue *tag = json_object_get_userdata(v);
+ size_t n = tag ? tag->tagtype : 0;
+ struct ut_extended_type *et;
+
+ if (!tag || tag->type != T_RESSOURCE || n == 0 || n > ut_ext_types_count)
+ return NULL;
+
+ et = &ut_ext_types[n - 1];
+
+ if (name && strcmp(et->name, name))
+ return NULL;
+
+ return &tag->data;
+}
diff --git a/ast.h b/ast.h
index f20be9c..979b975 100644
--- a/ast.h
+++ b/ast.h
@@ -57,6 +57,14 @@ struct ut_opcode {
uint32_t off;
};
+struct ut_tagvalue {
+ int type;
+ struct json_object *val;
+ struct json_object *proto;
+ size_t tagtype;
+ void *data;
+};
+
struct ut_state {
struct ut_opcode *pool;
struct ut_opcode *main;
@@ -80,6 +88,11 @@ struct ut_state {
struct json_object *ctx;
};
+struct ut_extended_type {
+ const char *name;
+ void (*free)(void *);
+};
+
struct ut_opcode *ut_new_op(struct ut_state *s, int type, struct json_object *val, ...);
struct ut_opcode *ut_wrap_op(struct ut_opcode *parent, ...);
struct ut_opcode *ut_append_op(struct ut_opcode *a, struct ut_opcode *b);
@@ -91,6 +104,10 @@ struct ut_opcode *ut_new_func(struct ut_state *s, struct ut_opcode *name, struct
struct json_object *json_object_new_double_rounded(double v);
struct json_object *json_object_new_null_obj(void);
+bool ut_register_extended_type(const char *name, void (*freefn)(void *));
+struct json_object *ut_set_extended_type(struct ut_state *s, struct json_object *v, struct json_object *proto, const char *name, void *data);
+void **ut_get_extended_type(struct json_object *val, const char *name);
+
void *ParseAlloc(void *(*mfunc)(size_t));
void Parse(void *pParser, int type, struct ut_opcode *op, struct ut_state *s);
void ParseFree(void *pParser, void (*ffunc)(void *));