mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-17 01:11:45 +00:00
[qfcc] Emit static instance lists
For now, only protocols are in the list (gcc adds only static string objects and qfcc doesn't do those yet, so not so far behind). qfprogs dumps them.
This commit is contained in:
parent
544d7de1ec
commit
b6b7f9675f
4 changed files with 216 additions and 11 deletions
|
@ -83,6 +83,11 @@ typedef struct protocollist_s {
|
|||
protocol_t **list;
|
||||
} protocollist_t;
|
||||
|
||||
typedef struct static_instance_s {
|
||||
const char *class;
|
||||
struct def_s *instance;
|
||||
} static_instance_t;
|
||||
|
||||
extern struct type_s type_id;
|
||||
extern struct type_s type_obj_object;
|
||||
extern struct type_s type_obj_class;
|
||||
|
|
|
@ -66,6 +66,8 @@
|
|||
static hashtab_t *class_hash;
|
||||
static hashtab_t *category_hash;
|
||||
static hashtab_t *protocol_hash;
|
||||
static hashtab_t *static_instances;
|
||||
static hashtab_t *static_instance_classes;
|
||||
|
||||
// these will be built up further
|
||||
type_t type_obj_selector = { ev_invalid, 0, 0, ty_struct};
|
||||
|
@ -178,6 +180,141 @@ static struct_def_t object_struct[] = {
|
|||
{0, 0}
|
||||
};
|
||||
|
||||
static const char *
|
||||
static_instance_get_key (const void *instance, void *unused)
|
||||
{
|
||||
return ((static_instance_t *) instance)->class;
|
||||
}
|
||||
|
||||
static void
|
||||
add_static_instance (const char *class, def_t *instance_def)
|
||||
{
|
||||
static_instance_t *instance = malloc (sizeof (*instance));
|
||||
|
||||
if (!static_instances) {
|
||||
static_instances = Hash_NewTable (1021, static_instance_get_key, 0, 0);
|
||||
static_instance_classes = Hash_NewTable (1021, static_instance_get_key,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
instance->class = save_string (class);
|
||||
instance->instance = instance_def;
|
||||
Hash_Add (static_instances, instance);
|
||||
|
||||
// uniqued set of class names for all static instances
|
||||
if (!Hash_Find (static_instance_classes, class)) {
|
||||
Hash_Add (static_instance_classes, instance);
|
||||
}
|
||||
}
|
||||
typedef struct {
|
||||
const char *class_name;
|
||||
int num_instances;
|
||||
static_instance_t **instances;
|
||||
} obj_static_instances_data_t;
|
||||
|
||||
static void
|
||||
emit_instance_classname (def_t *def, void *data, int index)
|
||||
{
|
||||
obj_static_instances_data_t *da = (obj_static_instances_data_t *)data;
|
||||
|
||||
if (def->type != &type_string)
|
||||
internal_error (0, "%s: expected string def", __FUNCTION__);
|
||||
EMIT_STRING (def->space, D_STRING (def), da->class_name);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_instance_defs (def_t *def, void *data, int index)
|
||||
{
|
||||
obj_static_instances_data_t *da = (obj_static_instances_data_t *)data;
|
||||
|
||||
if (!is_array (def->type) || def->type->t.array.type->type != ev_pointer)
|
||||
internal_error (0, "%s: expected array of pointers def", __FUNCTION__);
|
||||
if (index < 0 || index >= da->num_instances + 1)
|
||||
internal_error (0, "%s: out of bounds index: %d %d",
|
||||
__FUNCTION__, index, da->num_instances + 1);
|
||||
D_INT (def) = 0;
|
||||
if (index < da->num_instances) {
|
||||
EMIT_DEF (def->space, D_INT (def), da->instances[index]->instance);
|
||||
}
|
||||
}
|
||||
|
||||
static def_t *
|
||||
emit_static_instances (const char *classname)
|
||||
{
|
||||
static struct_def_t instances_struct[] = {
|
||||
{"class_name", &type_string, emit_instance_classname},
|
||||
{"instances", 0, emit_instance_defs},
|
||||
{0, 0}
|
||||
};
|
||||
obj_static_instances_data_t data = {};
|
||||
def_t *instances_def;
|
||||
|
||||
data.class_name = classname;
|
||||
data.instances = (static_instance_t **) Hash_FindList (static_instances,
|
||||
classname);
|
||||
for (static_instance_t **inst = data.instances; *inst; inst++) {
|
||||
data.num_instances++;
|
||||
}
|
||||
instances_struct[1].type = array_type (&type_pointer,
|
||||
data.num_instances + 1);
|
||||
instances_def = emit_structure (va ("_OBJ_STATIC_INSTANCES_%s", classname),
|
||||
's', instances_struct, 0, &data,
|
||||
sc_static);
|
||||
free (data.instances);
|
||||
return instances_def;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
emit_static_instances_list (void)
|
||||
{
|
||||
static_instance_t **classes;
|
||||
int num_classes = 0;
|
||||
def_t **instance_lists;
|
||||
type_t *instance_lists_type;
|
||||
symbol_t *instance_lists_sym;
|
||||
def_t *instance_lists_def;
|
||||
pointer_t *list;
|
||||
defspace_t *space;
|
||||
|
||||
if (!static_instance_classes || !static_instances) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
classes = (static_instance_t **) Hash_GetList (static_instance_classes);
|
||||
for (static_instance_t **c = classes; *c; c++) {
|
||||
num_classes++;
|
||||
}
|
||||
if (!num_classes) {
|
||||
free (classes);
|
||||
return 0;
|
||||
}
|
||||
instance_lists = alloca (num_classes * sizeof (*instance_lists));
|
||||
for (int i = 0; i < num_classes; i++) {
|
||||
instance_lists[i] = emit_static_instances (classes[i]->class);
|
||||
}
|
||||
free (classes);
|
||||
|
||||
// +1 for terminating null
|
||||
instance_lists_type = array_type (&type_pointer, num_classes + 1);
|
||||
instance_lists_sym = make_symbol ("_OBJ_STATIC_INSTANCES",
|
||||
instance_lists_type,
|
||||
pr.far_data, sc_static);
|
||||
if (!instance_lists_sym->table) {
|
||||
symtab_addsymbol (pr.symtab, instance_lists_sym);
|
||||
}
|
||||
instance_lists_def = instance_lists_sym->s.def;
|
||||
instance_lists_def->initialized = instance_lists_def->constant = 1;
|
||||
instance_lists_def->nosave = 1;
|
||||
|
||||
list = D_POINTER (pointer_t, instance_lists_def);
|
||||
space = instance_lists_def->space;
|
||||
for (int i = 0; i < num_classes; i++, list++) {
|
||||
EMIT_DEF (space, *list, instance_lists[i]);
|
||||
}
|
||||
*list = 0;
|
||||
return instance_lists_def;
|
||||
}
|
||||
|
||||
int
|
||||
obj_is_id (const type_t *type)
|
||||
{
|
||||
|
@ -1185,6 +1322,7 @@ typedef struct {
|
|||
int cls_def_cnt;
|
||||
category_t **categories;
|
||||
int cat_def_cnt;
|
||||
def_t *instances_list;
|
||||
} obj_symtab_data_t;
|
||||
|
||||
static void
|
||||
|
@ -1238,10 +1376,10 @@ emit_symtab_defs (def_t *def, void *data, int index)
|
|||
|
||||
if (!is_array (def->type) || def->type->t.array.type->type != ev_pointer)
|
||||
internal_error (0, "%s: expected array of pointers def", __FUNCTION__);
|
||||
if (index < 0 || index >= da->cls_def_cnt + da->cat_def_cnt)
|
||||
if (index < 0 || index >= da->cls_def_cnt + da->cat_def_cnt + 1)
|
||||
internal_error (0, "%s: out of bounds index: %d %d",
|
||||
__FUNCTION__, index,
|
||||
da->cls_def_cnt + da->cat_def_cnt);
|
||||
da->cls_def_cnt + da->cat_def_cnt + 1);
|
||||
|
||||
if (index < da->cls_def_cnt) {
|
||||
class_t **cl;
|
||||
|
@ -1250,7 +1388,7 @@ emit_symtab_defs (def_t *def, void *data, int index)
|
|||
if (!index--)
|
||||
break;
|
||||
EMIT_DEF (def->space, D_INT (def), (*cl)->def);
|
||||
} else {
|
||||
} else if (index < da->cls_def_cnt + da->cat_def_cnt) {
|
||||
category_t **ca;
|
||||
index -= da->cls_def_cnt;
|
||||
for (ca = da->categories; *ca; ca++)
|
||||
|
@ -1258,6 +1396,11 @@ emit_symtab_defs (def_t *def, void *data, int index)
|
|||
if (!index--)
|
||||
break;
|
||||
EMIT_DEF (def->space, D_INT (def), (*ca)->def);
|
||||
} else {
|
||||
D_INT (def) = 0;
|
||||
if (da->instances_list) {
|
||||
EMIT_DEF (def->space, D_INT (def), da->instances_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1416,7 @@ class_finish_module (void)
|
|||
{0, 0}
|
||||
};
|
||||
|
||||
obj_symtab_data_t data = {0, 0, 0, 0, 0};
|
||||
obj_symtab_data_t data = {};
|
||||
|
||||
class_t **cl;
|
||||
category_t **ca;
|
||||
|
@ -1299,10 +1442,14 @@ class_finish_module (void)
|
|||
if ((*ca)->def && !(*ca)->def->external)
|
||||
data.cat_def_cnt++;
|
||||
}
|
||||
if (!data.refs && !data.cls_def_cnt && !data.cat_def_cnt)
|
||||
data.instances_list = emit_static_instances_list ();
|
||||
if (!data.refs && !data.cls_def_cnt && !data.cat_def_cnt
|
||||
&& !data.instances_list)
|
||||
return;
|
||||
symtab_struct[4].type = array_type (&type_pointer,
|
||||
data.cls_def_cnt + data.cat_def_cnt);
|
||||
data.cls_def_cnt
|
||||
+ data.cat_def_cnt
|
||||
+ 1);
|
||||
symtab_def = emit_structure ("_OBJ_SYMTAB", 's', symtab_struct, 0, &data,
|
||||
sc_static);
|
||||
free (data.classes);
|
||||
|
@ -1389,6 +1536,7 @@ protocol_def (protocol_t *protocol)
|
|||
{
|
||||
if (!protocol->def) {
|
||||
protocol->def = emit_protocol (protocol);
|
||||
add_static_instance ("Protocol", protocol->def);
|
||||
}
|
||||
return protocol->def;
|
||||
}
|
||||
|
@ -1548,6 +1696,10 @@ clear_classes (void)
|
|||
Hash_FlushTable (protocol_hash);
|
||||
if (category_hash)
|
||||
Hash_FlushTable (category_hash);
|
||||
if (static_instances)
|
||||
Hash_FlushTable (static_instances);
|
||||
if (static_instance_classes)
|
||||
Hash_FlushTable (static_instance_classes);
|
||||
obj_initialized = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,22 +89,41 @@ dump_selector (progs_t *pr, pr_sel_t *sel)
|
|||
printf (" %s\n", sel_types);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_method_description_list (progs_t *pr, char c,
|
||||
pr_method_description_list_t *list)
|
||||
{
|
||||
if (list) {
|
||||
for (int i = 0; i < list->count; i++) {
|
||||
printf ("%*s%s\n", 20, "", PR_GetString (pr, list->list[i].name));
|
||||
printf ("%*s%s\n", 20, "", PR_GetString (pr, list->list[i].types));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_protocol (progs_t *pr, pr_protocol_t *proto)
|
||||
{
|
||||
const char *protocol_name = "<invalid string>";
|
||||
printf (" %d ", proto->class_pointer);
|
||||
printf (" %x %x ",
|
||||
(pointer_t) ((pr_int_t *) proto - (pr_int_t *) pr->pr_globals),
|
||||
proto->class_pointer);
|
||||
if (PR_StringValid (pr, proto->protocol_name))
|
||||
protocol_name = PR_GetString (pr, proto->protocol_name);
|
||||
printf ("<%s>\n", protocol_name);
|
||||
dump_method_description_list (pr, '-',
|
||||
&G_STRUCT (pr, pr_method_description_list_t,
|
||||
proto->instance_methods));
|
||||
dump_method_description_list (pr, '-',
|
||||
&G_STRUCT (pr, pr_method_description_list_t,
|
||||
proto->class_methods));
|
||||
}
|
||||
|
||||
static void
|
||||
dump_protocol_list (progs_t *pr, pr_protocol_list_t *list)
|
||||
{
|
||||
int i;
|
||||
printf (" %d\n", list->next);
|
||||
printf (" %d\n", list->count);
|
||||
printf (" %x %d\n", list->next, list->count);
|
||||
for (i = 0; i < list->count; i++) {
|
||||
if (list->list[i] <= 0 || list->list[i] >= pr->globals_size) {
|
||||
printf ("invalid pointer\n");
|
||||
|
@ -171,6 +190,32 @@ dump_category (progs_t *pr, pr_category_t *category)
|
|||
category->protocols));
|
||||
}
|
||||
|
||||
static void
|
||||
dump_static_instance_lists (progs_t *pr, pointer_t instance_lists)
|
||||
{
|
||||
pointer_t *ptr = &G_STRUCT (pr, pointer_t, instance_lists);
|
||||
|
||||
printf (" static instance lists @ %x\n", instance_lists);
|
||||
while (*ptr) {
|
||||
__auto_type list = &G_STRUCT (pr, pr_static_instances_t, *ptr);
|
||||
const char *class_name = "*** INVALID ***";
|
||||
|
||||
if (PR_StringValid (pr, list->class_name)) {
|
||||
class_name = PR_GetString (pr, list->class_name);
|
||||
}
|
||||
printf (" %x %s\n", *ptr, class_name);
|
||||
for (int i = 0; list->instances[i]; i++) {
|
||||
if (!strcmp (class_name, "Protocol")) {
|
||||
dump_protocol (pr, &G_STRUCT (pr, pr_protocol_t,
|
||||
list->instances[i]));
|
||||
} else {
|
||||
printf (" %x\n", list->instances[i]);
|
||||
}
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_module (progs_t *pr, pr_module_t *module)
|
||||
{
|
||||
|
@ -197,6 +242,9 @@ dump_module (progs_t *pr, pr_module_t *module)
|
|||
dump_class (pr, &G_STRUCT (pr, pr_class_t, *ptr++));
|
||||
for (i = 0; i < symtab->cat_def_cnt; i++)
|
||||
dump_category (pr, &G_STRUCT (pr, pr_category_t, *ptr++));
|
||||
if (*ptr) {
|
||||
dump_static_instance_lists (pr, *ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -44,14 +44,14 @@ dump_string_block (const char *strblock, unsigned size)
|
|||
{
|
||||
const char *s = strblock;
|
||||
|
||||
printf ("%d ", 0);
|
||||
printf ("%x ", 0);
|
||||
while (s - strblock < size) {
|
||||
char c = *s++;
|
||||
switch (c) {
|
||||
case 0:
|
||||
fputs ("\n", stdout);
|
||||
if (s - strblock < size)
|
||||
printf ("%ld ", s - strblock);
|
||||
printf ("%lx ", s - strblock);
|
||||
break;
|
||||
case 9:
|
||||
fputs ("\\t", stdout);
|
||||
|
|
Loading…
Reference in a new issue