mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-29 20:20:43 +00:00
get @system working (Closes: #52). I'm not happy with the name of this
operator and I'm very open to suggestions, but it seems to work. What @system does is to mark a def in such a way that the linker will allow it to be redefined /once/ giving the programmer control over where and when a def is defined, but initializing it elsewhere. This is most useful when working with v6 progs and separate compliation as the `system' defs need to be in a certain order in certain locations or the resuting progs.dat file will be incompatable with non-qf 0.5 servers.
This commit is contained in:
parent
a9b16f5de5
commit
ece9660099
1 changed files with 59 additions and 21 deletions
|
@ -63,6 +63,7 @@ static const char rcsid[] =
|
||||||
#include "qfcc.h"
|
#include "qfcc.h"
|
||||||
#include "reloc.h"
|
#include "reloc.h"
|
||||||
#include "strpool.h"
|
#include "strpool.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
#define Xgroup(X)\
|
#define Xgroup(X)\
|
||||||
typedef struct {\
|
typedef struct {\
|
||||||
|
@ -101,6 +102,7 @@ static int reloc_base;
|
||||||
static int func_base;
|
static int func_base;
|
||||||
static int line_base;
|
static int line_base;
|
||||||
|
|
||||||
|
#define DATA(x) (data->data + (x))
|
||||||
#define STRING(x) (strings->strings + (x))
|
#define STRING(x) (strings->strings + (x))
|
||||||
#define TYPE_STRING(x) (type_strings->strings + (x))
|
#define TYPE_STRING(x) (type_strings->strings + (x))
|
||||||
|
|
||||||
|
@ -186,15 +188,16 @@ add_relocs (qfo_t *qfo)
|
||||||
case rel_def_func:
|
case rel_def_func:
|
||||||
reloc->ofs += data_base;
|
reloc->ofs += data_base;
|
||||||
reloc->def += func_base;
|
reloc->def += func_base;
|
||||||
|
DATA (reloc->ofs)->func_var = reloc->def + 1;
|
||||||
break;
|
break;
|
||||||
case rel_def_def:
|
case rel_def_def:
|
||||||
reloc->ofs += data_base;
|
reloc->ofs += data_base;
|
||||||
break;
|
break;
|
||||||
case rel_def_string:
|
case rel_def_string:
|
||||||
reloc->ofs += data_base;
|
reloc->ofs += data_base;
|
||||||
data->data[reloc->ofs].string_var =
|
DATA (reloc->ofs)->string_var =
|
||||||
strpool_addstr (strings,
|
strpool_addstr (strings,
|
||||||
qfo->strings + data->data[reloc->ofs].string_var);
|
qfo->strings + DATA (reloc->ofs)->string_var);
|
||||||
break;
|
break;
|
||||||
case rel_def_field:
|
case rel_def_field:
|
||||||
//FIXME more?
|
//FIXME more?
|
||||||
|
@ -217,24 +220,50 @@ process_def (qfo_def_t *def)
|
||||||
} else {
|
} else {
|
||||||
Hash_Add (extern_defs, def);
|
Hash_Add (extern_defs, def);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (def->flags & QFOD_GLOBAL) {
|
||||||
if (def->flags & QFOD_GLOBAL) {
|
if ((d = Hash_Find (defined_defs, STRING (def->name)))) {
|
||||||
if ((d = Hash_Find (defined_defs, STRING (def->name)))) {
|
if (d->flags & QFOD_SYSTEM) {
|
||||||
def_error (def, "%s redefined", STRING (def->name));
|
int i, size;
|
||||||
}
|
|
||||||
while ((d = Hash_Del (extern_defs, STRING (def->name)))) {
|
|
||||||
Hash_Add (defined_defs, d);
|
|
||||||
if (d->full_type != def->full_type) {
|
if (d->full_type != def->full_type) {
|
||||||
def_error (def, "type mismatch `%s' `%s'",
|
def_error (def, "type mismatch `%s' `%s'",
|
||||||
TYPE_STRING (def->full_type),
|
TYPE_STRING (def->full_type),
|
||||||
TYPE_STRING (d->full_type));
|
TYPE_STRING (d->full_type));
|
||||||
continue;
|
def_error (d, "previous definition");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
d->ofs = def->ofs;
|
d->flags &= ~QFOD_SYSTEM;
|
||||||
d->flags = def->flags;
|
d->flags |= def->flags & (QFOD_INITIALIZED | QFOD_CONSTANT);
|
||||||
|
size = type_size (parse_type (TYPE_STRING (d->full_type)));
|
||||||
|
memcpy (DATA (d->ofs), DATA (def->ofs),
|
||||||
|
size * sizeof (pr_type_t));
|
||||||
|
for (i = 0; i < relocs.num_relocs; i++) {
|
||||||
|
qfo_reloc_t *reloc = relocs.relocs + i;
|
||||||
|
if (reloc->type >= rel_def_op
|
||||||
|
&& reloc->type <= rel_def_field)
|
||||||
|
if (reloc->ofs == def->ofs)
|
||||||
|
reloc->ofs = d->ofs;
|
||||||
|
}
|
||||||
|
def->ofs = d->ofs;
|
||||||
|
def->flags = d->flags;
|
||||||
|
} else {
|
||||||
|
def_error (def, "%s redefined", STRING (def->name));
|
||||||
|
def_error (d, "previous definition");
|
||||||
}
|
}
|
||||||
Hash_Add (defined_defs, def);
|
|
||||||
}
|
}
|
||||||
|
while ((d = Hash_Del (extern_defs, STRING (def->name)))) {
|
||||||
|
Hash_Add (defined_defs, d);
|
||||||
|
if (d->full_type != def->full_type) {
|
||||||
|
def_error (def, "type mismatch `%s' `%s'",
|
||||||
|
TYPE_STRING (def->full_type),
|
||||||
|
TYPE_STRING (d->full_type));
|
||||||
|
def_error (d, "previous definition");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
d->ofs = def->ofs;
|
||||||
|
d->flags = def->flags;
|
||||||
|
}
|
||||||
|
Hash_Add (defined_defs, def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,10 +271,11 @@ static void
|
||||||
process_field (qfo_def_t *def)
|
process_field (qfo_def_t *def)
|
||||||
{
|
{
|
||||||
qfo_def_t *field_def;
|
qfo_def_t *field_def;
|
||||||
pr_type_t *var = data->data + def->ofs;
|
pr_type_t *var = DATA (def->ofs);
|
||||||
|
|
||||||
if ((field_def = Hash_Find (field_defs, STRING (def->name)))) {
|
if ((field_def = Hash_Find (field_defs, STRING (def->name)))) {
|
||||||
def_error (def, "%s redefined", STRING (def->name));
|
def_error (def, "%s redefined", STRING (def->name));
|
||||||
|
def_error (field_def, "previous definition");
|
||||||
}
|
}
|
||||||
defgroup_add_defs (&fields, def, 1);
|
defgroup_add_defs (&fields, def, 1);
|
||||||
field_def = fields.defs + fields.num_defs - 1;
|
field_def = fields.defs + fields.num_defs - 1;
|
||||||
|
@ -275,10 +305,10 @@ fixup_def (qfo_t *qfo, qfo_def_t *def, int def_num)
|
||||||
if (!(def->flags & QFOD_EXTERNAL)) {
|
if (!(def->flags & QFOD_EXTERNAL)) {
|
||||||
def->ofs += data_base;
|
def->ofs += data_base;
|
||||||
if (def->flags & QFOD_INITIALIZED) {
|
if (def->flags & QFOD_INITIALIZED) {
|
||||||
pr_type_t *var = data->data + def->ofs;
|
pr_type_t *var = DATA (def->ofs);
|
||||||
switch (def->basic_type) {
|
switch (def->basic_type) {
|
||||||
case ev_func:
|
case ev_func:
|
||||||
func = funcs.funcs + var->func_var - 1 + func_base;
|
func = funcs.funcs + var->func_var - 1;
|
||||||
func->def = def_num;
|
func->def = def_num;
|
||||||
break;
|
break;
|
||||||
case ev_field:
|
case ev_field:
|
||||||
|
@ -411,20 +441,19 @@ fixup_relocs ()
|
||||||
case rel_op_c_op:
|
case rel_op_c_op:
|
||||||
break;
|
break;
|
||||||
case rel_def_op:
|
case rel_def_op:
|
||||||
data->data[reloc->ofs].integer_var = reloc->def;
|
DATA (reloc->ofs)->integer_var = reloc->def;
|
||||||
break;
|
break;
|
||||||
case rel_def_def:
|
case rel_def_def:
|
||||||
data->data[reloc->ofs].integer_var = def->ofs;
|
DATA (reloc->ofs)->integer_var = def->ofs;
|
||||||
break;
|
break;
|
||||||
case rel_def_func:
|
case rel_def_func:
|
||||||
data->data[reloc->ofs].integer_var = reloc->def + 1;
|
|
||||||
break;
|
break;
|
||||||
case rel_def_string:
|
case rel_def_string:
|
||||||
break;
|
break;
|
||||||
case rel_def_field:
|
case rel_def_field:
|
||||||
field_def = Hash_Find (field_defs, STRING (def->name));
|
field_def = Hash_Find (field_defs, STRING (def->name));
|
||||||
if (field_def) // null if not initialized
|
if (field_def) // null if not initialized
|
||||||
data->data[reloc->ofs].integer_var = field_def->ofs;
|
DATA (reloc->ofs)->integer_var = field_def->ofs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,7 +462,7 @@ fixup_relocs ()
|
||||||
if (def->basic_type == ev_func
|
if (def->basic_type == ev_func
|
||||||
&& (def->flags & QFOD_INITIALIZED)
|
&& (def->flags & QFOD_INITIALIZED)
|
||||||
&& !(def->flags & (QFOD_LOCAL | QFOD_EXTERNAL | QFOD_ABSOLUTE))) {
|
&& !(def->flags & (QFOD_LOCAL | QFOD_EXTERNAL | QFOD_ABSOLUTE))) {
|
||||||
func = funcs.funcs + data->data[def->ofs].func_var - 1;
|
func = funcs.funcs + DATA (def->ofs)->func_var - 1;
|
||||||
func->def = i;
|
func->def = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -455,6 +484,11 @@ move_def (hashtab_t *deftab, qfo_def_t *d)
|
||||||
relocs.relocs[d->relocs + j].type = rel_none;
|
relocs.relocs[d->relocs + j].type = rel_none;
|
||||||
final_relocs.relocs[def->relocs + j].def = def_num;
|
final_relocs.relocs[def->relocs + j].def = def_num;
|
||||||
}
|
}
|
||||||
|
if (d->basic_type == ev_func) {
|
||||||
|
qfo_func_t *func;
|
||||||
|
func = funcs.funcs + DATA (d->ofs)->func_var - 1;
|
||||||
|
func->def = def_num;
|
||||||
|
}
|
||||||
if (deftab) {
|
if (deftab) {
|
||||||
while ((d = Hash_Del (deftab, STRING (def->name)))) {
|
while ((d = Hash_Del (deftab, STRING (def->name)))) {
|
||||||
int def_relocs;
|
int def_relocs;
|
||||||
|
@ -466,6 +500,7 @@ move_def (hashtab_t *deftab, qfo_def_t *d)
|
||||||
relocs.relocs[d->relocs + j].type = rel_none;
|
relocs.relocs[d->relocs + j].type = rel_none;
|
||||||
final_relocs.relocs[def_relocs + j].def = def_num;
|
final_relocs.relocs[def_relocs + j].def = def_num;
|
||||||
}
|
}
|
||||||
|
memset (d, 0, sizeof (*d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -476,10 +511,13 @@ merge_defgroups (void)
|
||||||
int local_base, i, j;
|
int local_base, i, j;
|
||||||
qfo_def_t *def, *d;
|
qfo_def_t *def, *d;
|
||||||
qfo_func_t *func;
|
qfo_func_t *func;
|
||||||
|
static qfo_def_t null_def;
|
||||||
|
|
||||||
for (i = 0; i < global_defs.num_defs; i++) {
|
for (i = 0; i < global_defs.num_defs; i++) {
|
||||||
const char *name;
|
const char *name;
|
||||||
def = global_defs.defs + i;
|
def = global_defs.defs + i;
|
||||||
|
if (memcmp (def, &null_def, sizeof (*def)) == 0)
|
||||||
|
continue;
|
||||||
name = STRING (def->name);
|
name = STRING (def->name);
|
||||||
if ((d = Hash_Del (defined_defs, name)))
|
if ((d = Hash_Del (defined_defs, name)))
|
||||||
move_def (defined_defs, d);
|
move_def (defined_defs, d);
|
||||||
|
|
Loading…
Reference in a new issue