+
+// ------------------------------- 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);
+}