2002-10-22 14:53:18 +00:00
|
|
|
/*
|
|
|
|
def.c
|
2001-04-01 02:12:57 +00:00
|
|
|
|
2002-10-22 14:53:18 +00:00
|
|
|
def management and symbol tables
|
2001-04-01 02:12:57 +00:00
|
|
|
|
2002-10-22 14:53:18 +00:00
|
|
|
Copyright (C) 2002 Bill Currie <bill@taniwha.org>
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
2001-04-01 02:12:57 +00:00
|
|
|
|
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
|
2001-04-01 02:12:57 +00:00
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
2003-01-15 15:31:36 +00:00
|
|
|
|
2005-08-04 15:27:09 +00:00
|
|
|
static __attribute__ ((used)) const char rcsid[] =
|
2003-01-15 15:31:36 +00:00
|
|
|
"$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>
|
|
|
|
|
2001-04-01 02:12:57 +00:00
|
|
|
#include <QF/hash.h>
|
2001-10-24 22:50:06 +00:00
|
|
|
#include <QF/sys.h>
|
2002-06-01 05:06:19 +00:00
|
|
|
#include <QF/va.h>
|
2001-04-01 02:12:57 +00:00
|
|
|
|
|
|
|
#include "qfcc.h"
|
2002-06-04 21:23:39 +00:00
|
|
|
#include "def.h"
|
2011-01-17 03:06:15 +00:00
|
|
|
#include "defspace.h"
|
2011-01-24 12:54:57 +00:00
|
|
|
#include "diagnostic.h"
|
2002-03-18 07:30:21 +00:00
|
|
|
#include "expr.h"
|
2002-07-17 15:40:08 +00:00
|
|
|
#include "immediate.h"
|
2004-02-17 00:39:21 +00:00
|
|
|
#include "options.h"
|
2002-07-16 21:59:47 +00:00
|
|
|
#include "reloc.h"
|
2002-07-05 20:02:10 +00:00
|
|
|
#include "strpool.h"
|
2002-01-21 19:03:29 +00:00
|
|
|
#include "struct.h"
|
2011-01-25 03:07:02 +00:00
|
|
|
#include "symtab.h"
|
2002-05-09 06:34:48 +00:00
|
|
|
#include "type.h"
|
2001-04-01 02:12:57 +00:00
|
|
|
|
2002-06-05 19:03:51 +00:00
|
|
|
static def_t *free_defs;
|
2002-06-09 03:57:20 +00:00
|
|
|
|
2011-01-24 06:41:43 +00:00
|
|
|
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) {
|
2002-09-16 15:42:11 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2003-07-23 18:28:31 +00:00
|
|
|
def_t *
|
2011-01-24 06:41:43 +00:00
|
|
|
new_def (const char *name, type_t *type, defspace_t *space,
|
2002-06-28 17:59:32 +00:00
|
|
|
storage_class_t storage)
|
2001-04-01 02:12:57 +00:00
|
|
|
{
|
2001-12-06 19:49:40 +00:00
|
|
|
def_t *def;
|
2001-04-01 02:12:57 +00:00
|
|
|
|
2002-06-05 21:13:29 +00:00
|
|
|
ALLOC (16384, def_t, defs, def);
|
2001-06-04 05:45:51 +00:00
|
|
|
|
2011-01-24 06:41:43 +00:00
|
|
|
if (!space && storage != st_extern)
|
|
|
|
internal_error (0, "non-external def with no storage space");
|
2011-02-11 06:46:03 +00:00
|
|
|
if (!type)
|
|
|
|
internal_error (0, "attempt to create def '%s' with a null type",
|
|
|
|
name);
|
2001-04-01 02:12:57 +00:00
|
|
|
|
2002-06-09 03:57:20 +00:00
|
|
|
def->return_addr = __builtin_return_address (0);
|
2001-04-01 02:12:57 +00:00
|
|
|
|
2002-07-03 19:12:29 +00:00
|
|
|
def->name = name ? save_string (name) : 0;
|
2001-04-01 02:12:57 +00:00
|
|
|
def->type = type;
|
|
|
|
|
2011-01-24 06:41:43 +00:00
|
|
|
if (storage != st_extern) {
|
2011-02-13 10:26:20 +00:00
|
|
|
int size = type_size (type);
|
|
|
|
if (!size) {
|
|
|
|
error (0, "%s has incomplete type", name);
|
|
|
|
size = 1;
|
|
|
|
}
|
|
|
|
def->offset = defspace_new_loc (space, size);
|
2011-02-09 15:15:19 +00:00
|
|
|
}
|
|
|
|
if (space) {
|
2011-02-11 09:27:07 +00:00
|
|
|
def->space = space;
|
2011-01-24 06:41:43 +00:00
|
|
|
*space->def_tail = def;
|
|
|
|
space->def_tail = &def->next;
|
2002-07-12 15:54:46 +00:00
|
|
|
}
|
2001-04-01 02:12:57 +00:00
|
|
|
|
2002-07-03 21:32:03 +00:00
|
|
|
def->file = pr.source_file;
|
|
|
|
def->line = pr.source_line;
|
2001-09-22 23:41:47 +00:00
|
|
|
|
2011-01-24 06:41:43 +00:00
|
|
|
set_storage_bits (def, storage);
|
2001-12-06 19:49:40 +00:00
|
|
|
|
2001-06-05 05:22:11 +00:00
|
|
|
return def;
|
2001-06-04 17:52:50 +00:00
|
|
|
}
|
|
|
|
|
2011-01-25 06:42:26 +00:00
|
|
|
def_t *
|
|
|
|
alias_def (def_t *def, type_t *type)
|
|
|
|
{
|
|
|
|
def_t *alias;
|
|
|
|
|
|
|
|
ALLOC (16384, def_t, defs, alias);
|
|
|
|
alias->offset = def->offset;
|
|
|
|
alias->type = type;
|
|
|
|
alias->alias = def;
|
|
|
|
return alias;
|
|
|
|
}
|
|
|
|
|
2001-06-04 17:52:50 +00:00
|
|
|
void
|
2011-01-24 06:41:43 +00:00
|
|
|
free_def (def_t *def)
|
2001-06-04 22:35:54 +00:00
|
|
|
{
|
2011-01-25 06:42:26 +00:00
|
|
|
if (!def->alias && def->space) {
|
2011-01-24 06:41:43 +00:00
|
|
|
def_t **d;
|
2001-08-22 21:55:01 +00:00
|
|
|
|
2011-01-24 06:41:43 +00:00
|
|
|
for (d = &def->space->defs; *d && *d != def; d = &(*d)->next)
|
|
|
|
;
|
2011-02-14 01:35:54 +00:00
|
|
|
if (!*d)
|
|
|
|
internal_error (0, "freeing unlinked def %s", def->name);
|
2011-01-24 06:41:43 +00:00
|
|
|
*d = def->next;
|
2011-02-14 01:35:54 +00:00
|
|
|
if (&def->next == def->space->def_tail)
|
|
|
|
def->space->def_tail = d;
|
2011-02-11 09:27:07 +00:00
|
|
|
if (!def->external)
|
|
|
|
defspace_free_loc (def->space, def->offset, type_size (def->type));
|
2002-08-20 06:11:10 +00:00
|
|
|
}
|
2011-01-24 06:41:43 +00:00
|
|
|
def->next = free_defs;
|
|
|
|
free_defs = def;
|
2002-06-28 16:00:01 +00:00
|
|
|
}
|
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)
|
2011-01-09 10:41:24 +00:00
|
|
|
type = type->t.fldptr.type; // aux is true only for fields
|
2002-07-17 15:40:08 +00:00
|
|
|
ddef->type = type->type;
|
2011-01-24 06:41:43 +00:00
|
|
|
ddef->ofs = def->offset;
|
2002-07-17 15:40:08 +00:00
|
|
|
ddef->s_name = ReuseString (def->name);
|
|
|
|
}
|
2011-01-25 03:07:02 +00:00
|
|
|
|
|
|
|
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;
|
2011-02-10 05:51:52 +00:00
|
|
|
if (init->type == ex_nil)
|
|
|
|
convert_nil (init, type);
|
2011-01-25 03:07:02 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|