diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index b062d3a61..a3de24f99 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -35,7 +35,7 @@ typedef enum { ev_entity, ev_field, ev_func, - ev_pointer, + ev_pointer, // end of v6 types ev_quaternion, ev_integer, ev_uinteger, @@ -44,6 +44,7 @@ typedef enum { ev_object, ev_class, ev_sel, + ev_array, ev_type_count // not a type, gives number of types } etype_t; diff --git a/libs/gamecode/engine/pr_edict.c b/libs/gamecode/engine/pr_edict.c index 5198da8c2..45c5cc9b7 100644 --- a/libs/gamecode/engine/pr_edict.c +++ b/libs/gamecode/engine/pr_edict.c @@ -70,10 +70,11 @@ int pr_type_size[ev_type_count] = { 1, // ev_integer 1, // ev_uinteger 0, // ev_short value in opcode - 1, // ev_struct variable - 1, // ev_object variable - 1, // ev_class variable + 0, // ev_struct variable + 0, // ev_object variable + 0, // ev_class variable 2, // ev_sel + 0, // ev_array variable }; const char *pr_type_name[ev_type_count] = { @@ -93,6 +94,7 @@ const char *pr_type_name[ev_type_count] = { "object", "Class", "SEL", + "array", }; ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 46bdf83d7..405911382 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -57,6 +57,8 @@ static const char rcsid[] = def_t *emit_sub_expr (expr_t *e, def_t *dest); +static expr_t zero; + void add_statement_ref (def_t *def, dstatement_t *st, reloc_type type) { @@ -247,7 +249,8 @@ emit_assign_expr (int oper, expr_t *e) def_b = emit_sub_expr (e2, 0); if (e->rvalue && def_b->managed) def_b->users++; - if (e1->type == ex_expr && extract_type (e1->e.expr.e1) == ev_pointer) { + if (e1->type == ex_expr && extract_type (e1->e.expr.e1) == ev_pointer + && e1->e.expr.e1->type < ex_string) { def_a = emit_sub_expr (e1->e.expr.e1, 0); def_c = emit_sub_expr (e1->e.expr.e2, 0); op = opcode_find (operator, def_b, def_a, def_c); @@ -285,13 +288,59 @@ emit_bind_expr (expr_t *e1, expr_t *e2) return e2->e.temp.def; } +def_t * +emit_address_expr (expr_t *e) +{ + def_t *def_a, *def_b, *d; + opcode_t *op; + + def_a = emit_sub_expr (e->e.expr.e1, 0); + def_b = emit_sub_expr (e->e.expr.e2, 0); + op = opcode_find ("&", def_a, def_b, 0); + d = emit_statement (e->line, op, def_a, def_b, 0); + return d; +} + +def_t * +emit_deref_expr (expr_t *e, def_t *dest) +{ + def_t *d; + type_t *type = e->e.expr.type; + + e = e->e.expr.e1; + if (!dest && (e->type != ex_pointer + || !(e->e.pointer.val > 0 + && e->e.pointer.val < 65536))) { + dest = get_tempdef (type, current_scope); + dest->users += 2; + } +print_expr (e); printf ("%p\n", dest); + if (e->type == ex_expr + && e->e.expr.op == '&' + && e->e.expr.e1->type < ex_string) + e->e.expr.op = '.'; + d = emit_sub_expr (e, dest); + if (dest && d != dest) { + def_t *z; + opcode_t *op; + + zero.type = ex_short; + z = emit_sub_expr (&zero, 0); + op = opcode_find (".", d, z, dest); + return emit_statement (e->line, op, d, z, dest); + } else { + if (!d->name) + d->type = type; + } + return d; +} + def_t * emit_sub_expr (expr_t *e, def_t *dest) { opcode_t *op; const char *operator; def_t *def_a, *def_b, *d = 0; - static expr_t zero; def_t *tmp = 0; switch (e->type) { @@ -319,6 +368,10 @@ emit_sub_expr (expr_t *e, def_t *dest) d->users++; break; } + if (e->e.expr.op == '&' && e->e.expr.type->type == ev_pointer) { + d = emit_address_expr (e); + break; + } if (e->e.expr.e1->type == ex_block && e->e.expr.e1->e.block.is_call) { def_b = emit_sub_expr (e->e.expr.e2, 0); @@ -377,20 +430,7 @@ emit_sub_expr (expr_t *e, def_t *dest) } break; case '.': - if (!dest - && (e->e.expr.e1->type != ex_pointer - || !(e->e.expr.e1->e.pointer.val > 0 - && e->e.expr.e1->e.pointer.val < 65536))) { - dest = get_tempdef (e->e.expr.type, current_scope); - dest->users += 2; - } - if (e->e.expr.e1->type == ex_expr - && e->e.expr.e1->e.expr.op == '&') - e->e.expr.e1->e.expr.op = '.'; - d = emit_sub_expr (e->e.expr.e1, dest); - if (!d->name) - d->type = e->e.expr.type; - return d; + return emit_deref_expr (e, dest); case 'C': def_a = emit_sub_expr (e->e.expr.e1, 0); if (def_a->type->type == ev_pointer @@ -428,7 +468,8 @@ emit_sub_expr (expr_t *e, def_t *dest) case ex_pointer: if (e->e.pointer.val > 0 && e->e.pointer.val < 65536 && e->e.pointer.type->type != ev_struct) { - d = new_def (e->e.pointer.type, 0, current_scope); + d = new_def (pointer_type (e->e.pointer.type), 0, + current_scope); d->ofs = e->e.short_val; d->absolute = e->e.pointer.abs; d->users = 1; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index fe8e06309..a93b7bc47 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -103,6 +103,7 @@ type_t *types[] = { &type_void, // FIXME what type? &type_void, // FIXME what type? &type_SEL, + &type_void, // FIXME what type? }; expr_type expr_types[] = { @@ -122,6 +123,7 @@ expr_type expr_types[] = { ex_nil, // ev_object ex_nil, // ev_class ex_nil, // ev_sel + ex_nil, // ev_array }; void @@ -1072,6 +1074,7 @@ expr_t * test_expr (expr_t *e, int test) { expr_t *new = 0; + etype_t type; if (e->type == ex_error) return e; @@ -1081,7 +1084,7 @@ test_expr (expr_t *e, int test) if (!test) return unary_expr ('!', e); - switch (extract_type (e)) { + switch (type = extract_type (e)) { case ev_type_count: error (e, "internal error"); abort (); @@ -1129,7 +1132,8 @@ test_expr (expr_t *e, int test) case ev_object: case ev_class: case ev_sel: - return error (e, "struct cannot be tested"); + case ev_array: + return error (e, "%s cannot be tested", pr_type_name[type]); } new->line = e->line; new->file = e->file; @@ -1748,7 +1752,7 @@ array_expr (expr_t *array, expr_t *index) if (index->type == ex_error) return index; - if (array_type->type != ev_pointer || array_type->num_parms < 1) + if (array_type->type != ev_pointer && array_type->type != ev_array) return error (array, "not an array"); if (index_type != &type_integer && index_type != &type_uinteger) return error (index, "invalid array index type"); @@ -1769,9 +1773,14 @@ array_expr (expr_t *array, expr_t *index) && index->e.uinteger_val < 32768)) { index->type = ex_short; } - e = new_binary_expr ('.', array, index); - e->e.expr.type = pointer_type (array_type->aux_type); - return unary_expr ('.', e); + if (array_type->type == ev_array) { + e = address_expr (array, index, array_type->aux_type); + } else { + e = new_binary_expr ('.', array, index); + e->e.expr.type = pointer_type (array_type->aux_type); + } + e = unary_expr ('.', e); + return e; } expr_t * @@ -1789,7 +1798,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) switch (e1->type) { case ex_def: type = e1->e.def->type; - if (type->type == ev_struct) { + if (type->type == ev_struct || type->type == ev_array) { int abs = e1->e.def->global; def_t *def = e1->e.def; @@ -1930,10 +1939,12 @@ assign_expr (expr_t *e1, expr_t *e2) e = e2->e.expr.e1; if (e->type != ex_pointer || !(e->e.pointer.val > 0 && e->e.pointer.val < 65536)) { - e2 = e; - if (e2->type == ex_expr && e2->e.expr.op == '&' - && e2->e.expr.type->type == ev_pointer) + if (e->type == ex_expr && e->e.expr.op == '&' + && e->e.expr.type->type == ev_pointer + && e->e.expr.e1->type < ex_string) { + e2 = e; e2->e.expr.op = '.'; + } } } } @@ -1979,7 +1990,7 @@ init_elements (def_t *def, expr_t *eles) { expr_t *e; int count, i; - float *g = &G_FLOAT (G_INT (def->ofs)); + pr_type_t *g = G_POINTER (pr_type_t, def->ofs); for (count = 0, e = eles->e.block.head; e; count++, e = e->next) if (e->type == ex_error) @@ -1997,7 +2008,7 @@ init_elements (def_t *def, expr_t *eles) g += type_size (def->type->aux_type); } else { if (e->type == ex_string) { - *(int*)g = ReuseString (e->e.string_val); + g->string_var = ReuseString (e->e.string_val); } else { memcpy (g, &e->e, type_size (get_type (e)) * 4); } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 330d4e2e4..fd730743c 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -212,7 +212,7 @@ array_type (type_t *aux, int size) type_t new; memset (&new, 0, sizeof (new)); - new.type = ev_pointer; + new.type = ev_array; new.aux_type = aux; new.num_parms = size; return find_type (&new); @@ -342,6 +342,12 @@ _encode_type (dstring_t *encoding, type_t *type, int level) case ev_sel: dstring_appendstr (encoding, ":"); break; + case ev_array: + dstring_appendstr (encoding, "["); + dstring_appendstr (encoding, va ("%d ", type->num_parms)); + //XXX dstring_appendstr (encoding, name); + dstring_appendstr (encoding, "]"); + break; case ev_type_count: dstring_appendstr (encoding, "?"); break; @@ -415,6 +421,8 @@ type_size (type_t *type) field = field->next) size += type_size (field->type); return size; + case ev_array: + return type->num_parms * type_size (type->aux_type); } return 0; } diff --git a/tools/qfprogs/source/strings.c b/tools/qfprogs/source/strings.c index 9b91541c3..673e8291f 100644 --- a/tools/qfprogs/source/strings.c +++ b/tools/qfprogs/source/strings.c @@ -48,10 +48,13 @@ dump_strings (progs_t *pr) int i = 0; char *s = pr->pr_strings; + printf ("%d ", 0); while (i++ < pr->pr_stringsize) { switch (*s) { case 0: fputs ("\n", stdout); + if (i < pr->pr_stringsize) + printf ("%d ", i); break; case 9: fputs ("\\t", stdout);