mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
Fix aggregate initializers.
Initializing arrays and structs seems to be working.
This commit is contained in:
parent
d162838299
commit
19f6faf0ad
3 changed files with 117 additions and 19 deletions
|
@ -564,8 +564,6 @@ expr_t *build_state_expr (expr_t *frame, expr_t *think, expr_t *step);
|
||||||
expr_t *assign_expr (expr_t *e1, expr_t *e2);
|
expr_t *assign_expr (expr_t *e1, expr_t *e2);
|
||||||
expr_t *cast_expr (struct type_s *t, expr_t *e);
|
expr_t *cast_expr (struct type_s *t, expr_t *e);
|
||||||
|
|
||||||
void init_elements (struct def_s *def, expr_t *eles);
|
|
||||||
|
|
||||||
const char *get_op_string (int op);
|
const char *get_op_string (int op);
|
||||||
|
|
||||||
struct keywordarg_s;
|
struct keywordarg_s;
|
||||||
|
|
|
@ -51,6 +51,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "defspace.h"
|
#include "defspace.h"
|
||||||
#include "diagnostic.h"
|
#include "diagnostic.h"
|
||||||
|
#include "emit.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "immediate.h"
|
#include "immediate.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
@ -178,6 +179,106 @@ def_to_ddef (def_t *def, ddef_t *ddef, int aux)
|
||||||
ddef->s_name = ReuseString (def->name);
|
ddef->s_name = ReuseString (def->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_elements (struct def_s *def, expr_t *eles)
|
||||||
|
{
|
||||||
|
expr_t *e, *c;
|
||||||
|
int count, i, num_params, base_offset;
|
||||||
|
pr_type_t *g;
|
||||||
|
def_t *elements;
|
||||||
|
|
||||||
|
base_offset = def->offset;
|
||||||
|
if (def->local && local_expr)
|
||||||
|
base_offset = 0;
|
||||||
|
if (is_array (def->type)) {
|
||||||
|
type_t *array_type = def->type->t.array.type;
|
||||||
|
int array_size = def->type->t.array.size;
|
||||||
|
elements = calloc (array_size, sizeof (def_t));
|
||||||
|
for (i = 0; i < array_size; i++) {
|
||||||
|
elements[i].type = array_type;
|
||||||
|
elements[i].space = def->space;
|
||||||
|
elements[i].offset = base_offset + i * type_size (array_type);
|
||||||
|
}
|
||||||
|
num_params = i;
|
||||||
|
} else if (is_struct (def->type)) {
|
||||||
|
symtab_t *symtab = def->type->t.symtab;
|
||||||
|
symbol_t *field;
|
||||||
|
|
||||||
|
for (i = 0, field = symtab->symbols; field; field = field->next) {
|
||||||
|
if (field->sy_type != sy_var)
|
||||||
|
continue;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
elements = calloc (i, sizeof (def_t));
|
||||||
|
for (i = 0, field = symtab->symbols; field; field = field->next) {
|
||||||
|
if (field->sy_type != sy_var)
|
||||||
|
continue;
|
||||||
|
elements[i].type = field->type;
|
||||||
|
elements[i].space = def->space;
|
||||||
|
elements[i].offset = base_offset + field->s.offset;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
num_params = i;
|
||||||
|
} else {
|
||||||
|
error (eles, "invalid initializer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (count = 0, e = eles->e.block.head; e; count++, e = e->next) {
|
||||||
|
convert_name (e);
|
||||||
|
if (e->type == ex_nil && count < num_params)
|
||||||
|
convert_nil (e, elements[count].type);
|
||||||
|
if (e->type == ex_error) {
|
||||||
|
free (elements);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count > num_params) {
|
||||||
|
if (options.warnings.initializer)
|
||||||
|
warning (eles, "excessive elements in initializer");
|
||||||
|
count = num_params;
|
||||||
|
}
|
||||||
|
for (i = 0, e = eles->e.block.head; i < count; i++, e = e->next) {
|
||||||
|
g = D_POINTER (pr_type_t, &elements[i]);
|
||||||
|
c = constant_expr (e);
|
||||||
|
if (c->type == ex_block) {
|
||||||
|
if (!is_array (elements[i].type)
|
||||||
|
&& !is_struct (elements[i].type)) {
|
||||||
|
error (e, "type mismatch in initializer");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
init_elements (&elements[i], c);
|
||||||
|
} else if (c->type == ex_value) {
|
||||||
|
if (c->e.value.type == ev_integer
|
||||||
|
&& elements[i].type->type == ev_float)
|
||||||
|
convert_int (c);
|
||||||
|
if (get_type (c) != elements[i].type) {
|
||||||
|
error (e, "type mismatch in initializer");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!def->local || !local_expr) {
|
||||||
|
error (e, "non-constant initializer");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (def->local && local_expr) {
|
||||||
|
int offset = elements[i].offset;
|
||||||
|
type_t *type = elements[i].type;
|
||||||
|
expr_t *ptr = new_pointer_expr (offset, type, def);
|
||||||
|
|
||||||
|
append_expr (local_expr, assign_expr (unary_expr ('.', ptr), c));
|
||||||
|
} else {
|
||||||
|
if (c->e.value.type == ev_string) {
|
||||||
|
EMIT_STRING (def->space, g->string_var,
|
||||||
|
c->e.value.v.string_val);
|
||||||
|
} else {
|
||||||
|
memcpy (g, &c->e, type_size (get_type (c)) * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free (elements);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space,
|
initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space,
|
||||||
storage_class_t storage)
|
storage_class_t storage)
|
||||||
|
@ -210,7 +311,7 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space,
|
||||||
sym->type = type;
|
sym->type = type;
|
||||||
if (!sym->table)
|
if (!sym->table)
|
||||||
symtab_addsymbol (current_symtab, sym);
|
symtab_addsymbol (current_symtab, sym);
|
||||||
if (storage == st_global && init) {
|
if (storage == st_global && init && is_scalar (type)) {
|
||||||
sym->sy_type = sy_const;
|
sym->sy_type = sy_const;
|
||||||
memset (&sym->s.value, 0, sizeof (&sym->s.value));
|
memset (&sym->s.value, 0, sizeof (&sym->s.value));
|
||||||
if (init->type != ex_value) { //FIXME arrays/structs
|
if (init->type != ex_value) { //FIXME arrays/structs
|
||||||
|
@ -238,18 +339,23 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space,
|
||||||
return;
|
return;
|
||||||
if (init->type == ex_nil)
|
if (init->type == ex_nil)
|
||||||
convert_nil (init, type);
|
convert_nil (init, type);
|
||||||
if (!type_assignable (type, get_type (init))) {
|
if (init->type == ex_block) {
|
||||||
error (init, "type mismatch in initializer");
|
init_elements (sym->s.def, init);
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (local_expr) {
|
|
||||||
append_expr (local_expr, assign_expr (new_symbol_expr (sym), init));
|
|
||||||
} else {
|
} else {
|
||||||
if (init->type != ex_value) { //FIXME arrays/structs
|
if (!type_assignable (type, get_type (init))) {
|
||||||
error (0, "non-constant initializier");
|
error (init, "type mismatch in initializer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy (D_POINTER (void, sym->s.def), &init->e.value,
|
if (local_expr) {
|
||||||
type_size (type) * sizeof (pr_type_t));
|
append_expr (local_expr,
|
||||||
|
assign_expr (new_symbol_expr (sym), init));
|
||||||
|
} else {
|
||||||
|
if (init->type != ex_value) { //FIXME enum etc
|
||||||
|
error (0, "non-constant initializier");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy (D_POINTER (void, sym->s.def), &init->e.value,
|
||||||
|
type_size (type) * sizeof (pr_type_t));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2497,12 +2497,6 @@ cast_expr (type_t *type, expr_t *e)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
init_elements (def_t *def, expr_t *eles)
|
|
||||||
{
|
|
||||||
//FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_t *
|
expr_t *
|
||||||
selector_expr (keywordarg_t *selector)
|
selector_expr (keywordarg_t *selector)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue