quakeforge/tools/qfcc/source/def.c

219 lines
4.8 KiB
C
Raw Normal View History

2002-10-22 14:53:18 +00:00
/*
def.c
2002-10-22 14:53:18 +00:00
def management and symbol tables
2002-10-22 14:53:18 +00:00
Copyright (C) 2002 Bill Currie <bill@taniwha.org>
Copyright (C) 1996-1997 Id Software, Inc.
2002-10-22 14:53:18 +00:00
Author: Bill Currie <bill@taniwha.org>
Date: 2002/06/09
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
static __attribute__ ((used)) const char rcsid[] =
"$Id$";
2002-06-01 04:41:25 +00:00
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include <QF/hash.h>
#include <QF/sys.h>
2002-06-01 05:06:19 +00:00
#include <QF/va.h>
#include "qfcc.h"
2002-06-04 21:23:39 +00:00
#include "def.h"
#include "defspace.h"
#include "diagnostic.h"
#include "expr.h"
2002-07-17 15:40:08 +00:00
#include "immediate.h"
#include "options.h"
#include "reloc.h"
#include "strpool.h"
2002-01-21 19:03:29 +00:00
#include "struct.h"
#include "symtab.h"
#include "type.h"
2002-06-05 19:03:51 +00:00
static def_t *free_defs;
static void
2002-07-02 21:34:40 +00:00
set_storage_bits (def_t *def, storage_class_t storage)
2002-06-17 02:43:38 +00:00
{
2002-07-02 21:34:40 +00:00
switch (storage) {
case st_system:
def->system = 1;
// fall through
2002-07-02 21:34:40 +00:00
case st_global:
def->global = 1;
def->external = 0;
2002-07-12 06:17:24 +00:00
def->local = 0;
2002-07-02 21:34:40 +00:00
break;
case st_extern:
def->global = 1;
def->external = 1;
2002-07-12 06:17:24 +00:00
def->local = 0;
2002-07-02 21:34:40 +00:00
break;
case st_static:
def->external = 0;
def->global = 0;
2002-07-12 06:17:24 +00:00
def->local = 0;
2002-07-02 21:34:40 +00:00
break;
case st_local:
2002-07-12 06:17:24 +00:00
def->external = 0;
def->global = 0;
def->local = 1;
2002-07-02 21:34:40 +00:00
break;
}
2002-07-02 23:08:44 +00:00
def->initialized = 0;
2002-06-17 02:43:38 +00:00
}
def_t *
new_def (const char *name, type_t *type, defspace_t *space,
storage_class_t storage)
{
def_t *def;
2002-06-05 21:13:29 +00:00
ALLOC (16384, def_t, defs, def);
if (!space && storage != st_extern)
internal_error (0, "non-external def with no storage space");
def->return_addr = __builtin_return_address (0);
def->name = name ? save_string (name) : 0;
def->type = type;
def->space = space;
if (storage != st_extern) {
*space->def_tail = def;
space->def_tail = &def->next;
def->offset = defspace_new_loc (space, type_size (type));
}
def->file = pr.source_file;
def->line = pr.source_line;
2001-09-22 23:41:47 +00:00
set_storage_bits (def, storage);
return def;
}
void
free_def (def_t *def)
{
if (def->space) {
def_t **d;
for (d = &def->space->defs; *d && *d != def; d = &(*d)->next)
;
*d = def->next;
defspace_free_loc (def->space, def->offset, type_size (def->type));
}
def->next = free_defs;
free_defs = def;
}
2002-07-17 15:40:08 +00:00
void
def_to_ddef (def_t *def, ddef_t *ddef, int aux)
{
type_t *type = def->type;
if (aux)
type = type->t.fldptr.type; // aux is true only for fields
2002-07-17 15:40:08 +00:00
ddef->type = type->type;
ddef->ofs = def->offset;
2002-07-17 15:40:08 +00:00
ddef->s_name = ReuseString (def->name);
}
void
initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space,
storage_class_t storage)
{
if (sym->table == current_symtab) {
if (sym->sy_type != sy_var || sym->type != type) {
error (0, "%s redefined", sym->name);
sym = new_symbol (sym->name);
} else {
// is var and same type
if (!sym->s.def)
internal_error (0, "half defined var");
if (storage == st_extern) {
if (init)
warning (0, "initializing external variable");
return;
}
if (init && sym->s.def->initialized) {
error (0, "%s redefined", sym->name);
return;
}
}
} else if (sym->table) {
sym = new_symbol (sym->name);
}
sym->type = type;
symtab_addsymbol (current_symtab, sym);
if (storage == st_global && init) {
sym->sy_type = sy_const;
memset (&sym->s.value, 0, sizeof (&sym->s.value));
if (init->type != ex_value) { //FIXME arrays/structs
error (0, "non-constant initializier");
} else {
sym->s.value = init->e.value;
}
return;
}
if (sym->s.def && sym->s.def->external) {
free_def (sym->s.def);
sym->s.def = 0;
}
if (!sym->s.def)
sym->s.def = new_def (sym->name, type, space, storage);
if (storage == st_extern) {
if (init)
warning (0, "initializing external variable");
return;
}
if (!init)
return;
if (!type_assignable (type, get_type (init))) {
error (init, "type mismatch in initializer");
return;
}
if (local_expr) {
append_expr (local_expr, assign_expr (new_symbol_expr (sym), init));
} else {
if (init->type != ex_value) { //FIXME arrays/structs
error (0, "non-constant initializier");
return;
}
memcpy (D_POINTER (void, sym->s.def), &init->e.value,
type_size (type) * sizeof (pr_type_t));
}
}