+void multiname_destroy(multiname_t*m)
+{
+ if(m) {
+ if(m->name) {
+ free((void*)m->name);m->name = 0;
+ }
+ if(m->ns) {
+ namespace_destroy(m->ns);m->ns = 0;
+ }
+ if(m->namespace_set) {
+ namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
+ }
+ m->type=0;
+ free(m);
+ }
+}
+
+type_t multiname_type = {
+ dup: (dup_func)multiname_clone,
+ hash: (hash_func)multiname_hash,
+ free: (free_func)multiname_destroy,
+ equals: (equals_func)multiname_equals
+};
+
+
+// ------------------------------- constants -------------------------------------
+
+#define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 || \
+ (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
+
+#define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
+
+constant_t* constant_new_int(int i)
+{
+ NEW(constant_t,c);
+ c->i = i;
+ c->type = CONSTANT_INT;
+ return c;
+}
+constant_t* constant_new_uint(unsigned int u)
+{
+ NEW(constant_t,c);
+ c->u = u;
+ c->type = CONSTANT_UINT;
+ return c;
+}
+constant_t* constant_new_float(double f)
+{
+ NEW(constant_t,c);
+ c->f = f;
+ c->type = CONSTANT_FLOAT;
+ return c;
+}
+constant_t* constant_new_string(char*s)
+{
+ NEW(constant_t,c);
+ c->s = string_new4(s);
+ c->type = CONSTANT_STRING;
+ return c;
+}
+constant_t* constant_new_string2(const char*s, int len)
+{
+ NEW(constant_t,c);
+ c->s = string_new3(s, len);
+ c->type = CONSTANT_STRING;
+ return c;
+}
+constant_t* constant_new_namespace(namespace_t*ns)
+{
+ NEW(constant_t,c);
+ c->ns = namespace_clone(ns);
+ c->type = ns->access;
+ assert(NS_TYPE(c->type));
+ return c;
+}
+constant_t* constant_new_true()
+{
+ NEW(constant_t,c);
+ c->type = CONSTANT_TRUE;
+ return c;
+}
+constant_t* constant_new_false()
+{
+ NEW(constant_t,c);
+ c->type = CONSTANT_FALSE;
+ return c;
+}
+constant_t* constant_new_null()
+{
+ NEW(constant_t,c);
+ c->type = CONSTANT_NULL;
+ return c;
+}
+constant_t* constant_new_undefined()
+{
+ NEW(constant_t,c);
+ c->type = CONSTANT_UNDEFINED;
+ return c;
+}
+constant_t* constant_fromindex(pool_t*pool, int index, int type)
+{
+ if(!index) {
+ /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
+ index is present to indicate that a type is coming */
+ return 0;
+ }
+ NEW(constant_t,c);
+ c->type = type;
+ if(NS_TYPE(c->type)) {
+ c->ns = namespace_clone(pool_lookup_namespace(pool, index));
+ } else if(c->type == CONSTANT_INT) {
+ c->i = pool_lookup_int(pool, index);
+ } else if(c->type == CONSTANT_UINT) {
+ c->u = pool_lookup_uint(pool, index);
+ } else if(c->type == CONSTANT_FLOAT) {
+ c->f = pool_lookup_float(pool, index);
+ } else if(c->type == CONSTANT_STRING) {
+ string_t s = pool_lookup_string2(pool, index);
+ c->s = string_dup3(&s);
+ } else if(UNIQUE_CONSTANT(c->type)) {
+ // ok
+ } else {
+ fprintf(stderr, "invalid constant type %02x\n", c->type);
+ }
+ return c;
+}
+char* constant_tostring(constant_t*c)
+{
+ if(!c)
+ return 0;
+ char buf[32];
+ if(NS_TYPE(c->type)) {
+ return namespace_tostring(c->ns);
+ } else if(c->type == CONSTANT_INT) {
+ sprintf(buf, "%d", c->i);
+ return strdup(buf);
+ } else if(c->type == CONSTANT_UINT) {
+ sprintf(buf, "%u", c->u);
+ return strdup(buf);
+ } else if(c->type == CONSTANT_FLOAT) {
+ char buf[1024];
+ sprintf(buf, "%f", c->f);
+ return strdup(buf);
+ } else if(c->type == CONSTANT_STRING) {
+ /* should we escape the string? \0 bytes won't be printed */
+ return strdup_n(c->s->str,c->s->len);
+ } else if(c->type == CONSTANT_TRUE) {
+ return strdup("true");
+ } else if(c->type == CONSTANT_FALSE) {
+ return strdup("false");
+ } else if(c->type == CONSTANT_NULL) {
+ return strdup("null");
+ } else if(c->type == CONSTANT_UNDEFINED) {
+ return strdup("undefined");
+ } else {
+ fprintf(stderr, "invalid constant type %02x\n", c->type);
+ return 0;
+ }
+}
+char constant_has_index(constant_t*c)
+{
+ if(!c)
+ return 0;
+ return !UNIQUE_CONSTANT(c->type);
+}
+int constant_get_index(pool_t*pool, constant_t*c)
+{
+ if(!c)
+ return 0;
+ if(NS_TYPE(c->type)) {
+ assert(c->ns);
+ /*if(c->type!=c->ns->access) {
+ printf("%02x<->%02x\n", c->type, c->ns->access);
+ }*/
+ assert(c->type == c->ns->access);
+ return pool_register_namespace(pool, c->ns);
+ } else if(c->type == CONSTANT_INT) {
+ return pool_register_int(pool, c->i);
+ } else if(c->type == CONSTANT_UINT) {
+ return pool_register_uint(pool, c->u);
+ } else if(c->type == CONSTANT_FLOAT) {
+ return pool_register_float(pool, c->f);
+ } else if(c->type == CONSTANT_STRING) {
+ return pool_register_string2(pool, c->s);
+ } else if(!constant_has_index(c)) {
+ return 1;
+ } else {
+ fprintf(stderr, "invalid constant type %02x\n", c->type);
+ return 0;
+ }
+}
+void constant_free(constant_t*c)
+{
+ if(!c)
+ return;
+ if(c->type == CONSTANT_STRING) {
+ string_free(c->s);
+ } else if (NS_TYPE(c->type)) {
+ namespace_destroy(c->ns);c->ns=0;
+ }
+ free(c);
+}
+// ------------------------------- pool -------------------------------------
+
+int pool_register_uint(pool_t*p, unsigned int i)
+{
+ int pos = array_append_if_new(p->x_uints, &i, 0);
+ assert(pos!=0);
+ return pos;
+}
+int pool_register_int(pool_t*p, int i)
+{
+ int pos = array_append_if_new(p->x_ints, &i, 0);
+ assert(pos!=0);
+ return pos;
+}
+int pool_register_float(pool_t*p, double d)
+{
+ int pos = array_append_if_new(p->x_floats, &d, 0);
+ assert(pos!=0);
+ return pos;
+}
+int pool_register_string(pool_t*pool, const char*str)
+{
+ if(!str) return 0;
+ string_t s = string_new2(str);
+ int pos = array_append_if_new(pool->x_strings, &s, 0);
+ assert(pos!=0);
+ return pos;
+}
+int pool_register_string2(pool_t*pool, string_t*s)
+{
+ if(!s || !s->str) return 0;
+ int pos = array_append_if_new(pool->x_strings, s, 0);
+ assert(pos!=0);
+ return pos;
+}
+int pool_register_namespace(pool_t*pool, namespace_t*ns)
+{
+ if(!ns) return 0;
+ int pos = array_append_if_new(pool->x_namespaces, ns, 0);
+ assert(pos!=0);
+ return pos;
+}
+int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
+{
+ if(!set) return 0;
+ int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
+ assert(pos!=0);
+ return pos;
+}
+int pool_register_multiname(pool_t*pool, multiname_t*n)
+{
+ if(!n) return 0;
+ int pos = array_append_if_new(pool->x_multinames, n, 0);
+ assert(pos!=0);
+ return pos;
+}
+int pool_register_multiname2(pool_t*pool, char*name)
+{
+ if(!name) return 0;
+ multiname_t*n = multiname_fromstring(name);
+ int pos = array_append_if_new(pool->x_multinames, n, 0);
+ multiname_destroy(n);
+ assert(pos!=0);
+ return pos;
+}
+
+
+int pool_find_uint(pool_t*pool, unsigned int x)
+{
+ int i = array_find(pool->x_uints, &x);
+ if(i<=0) {
+ fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
+ return 0;
+ }
+ return i;
+}
+int pool_find_int(pool_t*pool, int x)
+{
+ int i = array_find(pool->x_ints, &x);
+ if(i<=0) {
+ fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
+ return 0;
+ }
+ return i;
+}
+int pool_find_float(pool_t*pool, double x)
+{
+ int i = array_find(pool->x_ints, &x);
+ if(i<=0) {
+ fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
+ return 0;
+ }
+ return i;
+}
+int pool_find_namespace(pool_t*pool, namespace_t*ns)
+{
+ if(!ns)
+ return 0;
+ int i = array_find(pool->x_namespaces, ns);
+ if(i<=0) {
+ char*s = namespace_tostring(ns);
+ fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
+ free(s);
+ return 0;
+ }
+ return i;
+}
+int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
+{
+ if(!set)
+ return 0;
+ int i = array_find(pool->x_namespace_sets, set);
+ if(i<=0) {
+ char*s = namespace_set_tostring(set);
+ fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
+ free(s);
+ return 0;
+ }
+ return i;
+}
+int pool_find_string(pool_t*pool, const char*str)
+{
+ if(!str)
+ return 0;
+ string_t s = string_new2(str);
+ int i = array_find(pool->x_strings, &s);
+ if(i<=0) {
+ fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
+ return 0;
+ }
+ return i;
+}
+int pool_find_multiname(pool_t*pool, multiname_t*name)
+{
+ if(!name)
+ return 0;
+ int i = array_find(pool->x_multinames, name);
+ if(i<=0) {
+ char*s = multiname_tostring(name);
+ fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
+ free(s);
+ return 0;
+ }
+ return i;
+}
+
+int pool_lookup_int(pool_t*pool, int i)
+{
+ if(!i) return 0;
+ return *(int*)array_getkey(pool->x_ints, i);
+}
+unsigned int pool_lookup_uint(pool_t*pool, int i)
+{
+ if(!i) return 0;
+ return *(unsigned int*)array_getkey(pool->x_uints, i);
+}
+double pool_lookup_float(pool_t*pool, int i)
+{
+ if(!i) return __builtin_nan("");
+ return *(double*)array_getkey(pool->x_floats, i);
+}
+const char*pool_lookup_string(pool_t*pool, int i)
+{
+ string_t*s = array_getkey(pool->x_strings, i);
+ if(!s) return 0;
+ return s->str;
+}
+string_t pool_lookup_string2(pool_t*pool, int i)
+{
+ string_t*s = array_getkey(pool->x_strings, i);
+ return *s;
+}
+namespace_t*pool_lookup_namespace(pool_t*pool, int i)
+{
+ return (namespace_t*)array_getkey(pool->x_namespaces, i);
+}
+namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
+{
+ return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
+}
+multiname_t*pool_lookup_multiname(pool_t*pool, int i)
+{
+ return (multiname_t*)array_getkey(pool->x_multinames, i);
+}
+