mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
[qfcc] Add a handle type for engine resources
I never liked the various hacks I had come up with for representing resource handles in Ruamoko. Structs with an int were awkward to test, pointers and ints could be modified, etc etc. The new @handle keyword (@ used to keep handle free for use) works just like struct, union and enum in syntax, but creates an opaque type suitable for a 32-bit handle. The backing type is a function so v6 progs can use it without (all the necessary opcodes exist) and no modifications were needed for type-checking in binary expressions, but only assignment and comparisons are supported, and (of course) nil. Tested using cbuf_t and QFile: seems to work as desired. I had considered 64-bit handles, but really, if more than 4G resource objects are needed, I'm not sure QF can handle the game. However, that limit is per resource manager, not total.
This commit is contained in:
parent
d07bd20552
commit
6d5e8922a5
17 changed files with 105 additions and 11 deletions
|
@ -48,6 +48,7 @@ typedef enum {
|
|||
ty_array,
|
||||
ty_class,
|
||||
ty_alias,
|
||||
ty_handle,
|
||||
} ty_meta_e;
|
||||
|
||||
typedef struct qfot_alias_s {
|
||||
|
@ -57,6 +58,11 @@ typedef struct qfot_alias_s {
|
|||
pr_string_t name; ///< alias name, may be null
|
||||
} qfot_alias_t;
|
||||
|
||||
typedef struct qfot_handle_s {
|
||||
etype_t type;
|
||||
pr_string_t tag;
|
||||
} qfot_handle_t;
|
||||
|
||||
typedef struct qfot_fldptr_s {
|
||||
etype_t type; ///< ev_field or ev_ptr
|
||||
pr_ptr_t aux_type; ///< referenced type
|
||||
|
@ -119,6 +125,7 @@ typedef struct qfot_type_s {
|
|||
qfot_array_t array; ///< ty_array
|
||||
pr_string_t class; ///< ty_class
|
||||
qfot_alias_t alias; ///< ty_alias
|
||||
qfot_handle_t handle; ///< ty_handle
|
||||
};
|
||||
} qfot_type_t;
|
||||
|
||||
|
|
|
@ -237,6 +237,7 @@ pr_debug_type_size (const progs_t *pr, const qfot_type_t *type)
|
|||
qfot_type_t *aux_type;
|
||||
switch (type->meta) {
|
||||
case ty_basic:
|
||||
case ty_handle:
|
||||
return pr_type_size[type->type];
|
||||
case ty_struct:
|
||||
case ty_union:
|
||||
|
@ -1052,6 +1053,7 @@ static void
|
|||
value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value)
|
||||
{
|
||||
switch (type->meta) {
|
||||
case ty_handle:
|
||||
case ty_basic:
|
||||
switch (type->type) {
|
||||
#define EV_TYPE(t) \
|
||||
|
|
|
@ -95,6 +95,9 @@ void print_type (qfot_type_t *type)
|
|||
//printf (" %d %s ", type.alias.type, type.alias.name);
|
||||
print_type (type.alias.aux_type);
|
||||
break;
|
||||
case ty_handle:
|
||||
//printf (" %s\n", type.handle.tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ static string get_type_key (void *type, void *unused)
|
|||
return [[String alloc] initWithType: type];
|
||||
}
|
||||
}
|
||||
// fallthrough
|
||||
case ty_handle:
|
||||
case ty_class:
|
||||
return [[Type alloc] initWithType: type];
|
||||
case ty_array:
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#ifndef __ruamoko_cbuf_h
|
||||
#define __ruamoko_cbuf_h
|
||||
|
||||
typedef struct { int x; } cbuf_t;
|
||||
typedef @handle cbuf_h cbuf_t;
|
||||
|
||||
@extern void Cbuf_AddText (cbuf_t *cbuf, string text);
|
||||
@extern void Cbuf_InsertText (cbuf_t *cbuf, string text);
|
||||
@extern void Cbuf_Execute (cbuf_t *cbuf);
|
||||
@extern void Cbuf_Execute_Sets (cbuf_t *cbuf);
|
||||
@extern void Cbuf_AddText (cbuf_t cbuf, string text);
|
||||
@extern void Cbuf_InsertText (cbuf_t cbuf, string text);
|
||||
@extern void Cbuf_Execute (cbuf_t cbuf);
|
||||
@extern void Cbuf_Execute_Sets (cbuf_t cbuf);
|
||||
|
||||
#endif//__ruamoko_cbuf_h
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __ruamoko_qfile_h
|
||||
#define __ruamoko_qfile_h
|
||||
|
||||
typedef struct _qfile_t *QFile;
|
||||
typedef @handle _qfile_t QFile;
|
||||
|
||||
@extern int Qrename (string old, string new);
|
||||
@extern int Qremove (string path);
|
||||
|
|
|
@ -16,6 +16,7 @@ typedef enum {
|
|||
ty_array,
|
||||
ty_class,
|
||||
ty_alias,
|
||||
ty_handle,
|
||||
} ty_meta_e;
|
||||
|
||||
typedef struct qfot_alias_s {
|
||||
|
@ -25,6 +26,11 @@ typedef struct qfot_alias_s {
|
|||
string name;
|
||||
} qfot_alias_t;
|
||||
|
||||
typedef struct qfot_handle_s {
|
||||
etype_t type;
|
||||
string tag;
|
||||
} qfot_handle_t;
|
||||
|
||||
typedef struct qfot_fldptr_s {
|
||||
etype_t type;
|
||||
struct qfot_type_s *aux_type;
|
||||
|
@ -73,6 +79,7 @@ typedef struct qfot_type_s {
|
|||
qfot_array_t array;
|
||||
string class;
|
||||
qfot_alias_t alias;
|
||||
qfot_handle_t handle;
|
||||
};
|
||||
} qfot_type_t;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <cbuf.h>
|
||||
|
||||
void Cbuf_AddText (cbuf_t *cbuf, string text) = #0;
|
||||
void Cbuf_InsertText (cbuf_t *cbuf, string text) = #0;
|
||||
void Cbuf_Execute (cbuf_t *cbuf) = #0;
|
||||
void Cbuf_Execute_Sets (cbuf_t *cbuf) = #0;
|
||||
void Cbuf_AddText (cbuf_t cbuf, string text) = #0;
|
||||
void Cbuf_InsertText (cbuf_t cbuf, string text) = #0;
|
||||
void Cbuf_Execute (cbuf_t cbuf) = #0;
|
||||
void Cbuf_Execute_Sets (cbuf_t cbuf) = #0;
|
||||
|
|
|
@ -53,6 +53,9 @@ static void type_free (void *t, void *unused)
|
|||
case ty_alias:
|
||||
str_free (type.alias.name);
|
||||
break;
|
||||
case ty_handle:
|
||||
str_free (type.handle.tag);
|
||||
break;
|
||||
}
|
||||
obj_free (t);
|
||||
}
|
||||
|
@ -179,6 +182,11 @@ static void type_free (void *t, void *unused)
|
|||
}
|
||||
type.alias.full_type = t;
|
||||
goto hash_type;
|
||||
case ty_handle:
|
||||
if (!(type.handle.tag = qdb_get_string (target, type.handle.tag))) {
|
||||
goto error;
|
||||
}
|
||||
goto hash_type;
|
||||
}
|
||||
goto error;
|
||||
hash_type:
|
||||
|
@ -197,6 +205,7 @@ error:
|
|||
int size = 0;
|
||||
|
||||
switch (type.meta) {
|
||||
case ty_handle:
|
||||
case ty_basic:
|
||||
size = pr_type_size[type.type];
|
||||
break;
|
||||
|
|
|
@ -43,6 +43,8 @@ typedef struct {
|
|||
void (*emit) (struct def_s *def, void *data, int index);
|
||||
} struct_def_t;
|
||||
|
||||
struct symbol_s *find_handle (struct symbol_s *tag, struct type_s *type);
|
||||
|
||||
struct symtab_s *start_struct (int *su, struct symbol_s *tag,
|
||||
struct symtab_s *parent);
|
||||
struct symbol_s *find_struct (int su, struct symbol_s *tag,
|
||||
|
|
|
@ -444,6 +444,7 @@ static const char *ty_meta_names[] = {
|
|||
"ty_array",
|
||||
"ty_class",
|
||||
"ty_alias",
|
||||
"ty_handle",
|
||||
};
|
||||
#define NUM_META ((int)(sizeof (ty_meta_names) / sizeof (ty_meta_names[0])))
|
||||
const int vector_types = (1 << ev_float)
|
||||
|
@ -531,6 +532,9 @@ dump_qfo_types (qfo_t *qfo, int base_address)
|
|||
type->alias.type, type->alias.aux_type,
|
||||
type->alias.full_type);
|
||||
break;
|
||||
case ty_handle:
|
||||
printf (" %-5x\n", type->handle.tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -698,6 +698,7 @@ get_def_type (qfo_t *qfo, pr_ptr_t type)
|
|||
switch ((ty_meta_e)type_def->meta) {
|
||||
case ty_alias: //XXX
|
||||
case ty_basic:
|
||||
case ty_handle: //XXX
|
||||
// field, pointer and function types store their basic type in
|
||||
// the same location.
|
||||
return type_def->type;
|
||||
|
@ -726,6 +727,7 @@ get_type_size (qfo_t *qfo, pr_ptr_t type)
|
|||
switch ((ty_meta_e)type_def->meta) {
|
||||
case ty_alias:
|
||||
return get_type_size (qfo, type_def->alias.aux_type);
|
||||
case ty_handle: //XXX
|
||||
case ty_basic:
|
||||
// field, pointer and function types store their basic type in
|
||||
// the same location.
|
||||
|
@ -776,6 +778,7 @@ get_type_alignment_log (qfo_t *qfo, pr_ptr_t type)
|
|||
switch ((ty_meta_e)type_def->meta) {
|
||||
case ty_alias:
|
||||
return get_type_alignment_log (qfo, type_def->alias.aux_type);
|
||||
case ty_handle: //XXX
|
||||
case ty_basic:
|
||||
// field, pointer and function types store their basic type in
|
||||
// the same location.
|
||||
|
|
|
@ -277,6 +277,19 @@ qfo_encode_alias (type_t *type, defspace_t *space)
|
|||
return def;
|
||||
}
|
||||
|
||||
static def_t *
|
||||
qfo_encode_handle (type_t *type, defspace_t *space)
|
||||
{
|
||||
qfot_type_t *enc;
|
||||
def_t *def;
|
||||
|
||||
def = qfo_new_encoding (type, sizeof (enc->handle), space);
|
||||
enc = D_POINTER (qfot_type_t, def);
|
||||
enc->handle.type = type->type;
|
||||
ENC_STR (enc->handle.tag, type->name);
|
||||
return def;
|
||||
}
|
||||
|
||||
def_t *
|
||||
qfo_encode_type (type_t *type, defspace_t *space)
|
||||
{
|
||||
|
@ -290,6 +303,7 @@ qfo_encode_type (type_t *type, defspace_t *space)
|
|||
qfo_encode_array, // ty_array
|
||||
qfo_encode_class, // ty_class
|
||||
qfo_encode_alias, // ty_alias
|
||||
qfo_encode_handle, // ty_handle
|
||||
};
|
||||
|
||||
if (type->type_def && type->type_def->external) {
|
||||
|
|
|
@ -449,6 +449,7 @@ static keyword_t keywords[] = {
|
|||
{"@system", SYSTEM, },
|
||||
{"@overload", OVERLOAD, },
|
||||
{"@attribute", ATTRIBUTE, },
|
||||
{"@handle", HANDLE, },
|
||||
};
|
||||
|
||||
static const char *
|
||||
|
|
|
@ -153,7 +153,7 @@ int yylex (void);
|
|||
%token RETURN AT_RETURN ELLIPSIS
|
||||
%token NIL GOTO SWITCH CASE DEFAULT ENUM
|
||||
%token ARGS TYPEDEF EXTERN STATIC SYSTEM OVERLOAD NOT ATTRIBUTE
|
||||
%token <op> STRUCT
|
||||
%token <op> STRUCT HANDLE
|
||||
%token <spec> TYPE_SPEC TYPE_NAME TYPE_QUAL
|
||||
%token <spec> OBJECT_NAME
|
||||
%token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE
|
||||
|
@ -1085,6 +1085,19 @@ struct_specifier
|
|||
symtab_addsymbol (tab, sym);
|
||||
}
|
||||
}
|
||||
| HANDLE tag
|
||||
{
|
||||
symbol_t *sym = find_handle ($2, 0);
|
||||
sym->type = find_type (sym->type);
|
||||
$$ = make_spec (sym->type, 0, 0, 0);
|
||||
if (!sym->table) {
|
||||
symtab_t *tab = current_symtab;
|
||||
while (tab->parent && tab->type == stab_struct) {
|
||||
tab = tab->parent;
|
||||
}
|
||||
symtab_addsymbol (tab, sym);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
struct_list
|
||||
|
|
|
@ -125,6 +125,18 @@ start_struct (int *su, symbol_t *tag, symtab_t *parent)
|
|||
return new_symtab (parent, stab_struct);
|
||||
}
|
||||
|
||||
symbol_t *
|
||||
find_handle (symbol_t *tag, type_t *type)
|
||||
{
|
||||
symbol_t *sym = find_tag (ty_handle, tag, type);
|
||||
if (sym->type->type == ev_invalid) {
|
||||
sym->type->type = ev_func;
|
||||
sym->type->width = 1;
|
||||
sym->type->alignment = 1;
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
symbol_t *
|
||||
find_struct (int su, symbol_t *tag, type_t *type)
|
||||
{
|
||||
|
|
|
@ -308,6 +308,7 @@ copy_chain (type_t *type, type_t *append)
|
|||
case ty_enum:
|
||||
case ty_class:
|
||||
case ty_alias: //XXX is this correct?
|
||||
case ty_handle:
|
||||
internal_error (0, "copy object type %d", type->meta);
|
||||
}
|
||||
}
|
||||
|
@ -365,6 +366,7 @@ append_type (type_t *type, type_t *new)
|
|||
case ty_enum:
|
||||
case ty_class:
|
||||
case ty_alias: //XXX is this correct?
|
||||
case ty_handle:
|
||||
internal_error (0, "append to object type");
|
||||
}
|
||||
}
|
||||
|
@ -432,6 +434,9 @@ types_same (type_t *a, type_t *b)
|
|||
return (a->name == b->name
|
||||
&& a->t.alias.aux_type == b->t.alias.aux_type
|
||||
&& a->t.alias.full_type == b->t.alias.full_type);
|
||||
case ty_handle:
|
||||
// names have gone through save_string
|
||||
return a->name == b->name;
|
||||
}
|
||||
internal_error (0, "we be broke");
|
||||
}
|
||||
|
@ -560,6 +565,8 @@ find_type (type_t *type)
|
|||
case ty_alias:
|
||||
type->t.alias.aux_type = find_type (type->t.alias.aux_type);
|
||||
break;
|
||||
case ty_handle:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -807,6 +814,9 @@ print_type_str (dstring_t *str, const type_t *type)
|
|||
return;
|
||||
}
|
||||
switch (type->meta) {
|
||||
case ty_handle:
|
||||
dasprintf (str, " handle %s", type->name);
|
||||
return;
|
||||
case ty_alias:
|
||||
dasprintf (str, "({%s=", type->name);
|
||||
print_type_str (str, type->t.alias.aux_type);
|
||||
|
@ -996,6 +1006,9 @@ encode_type (dstring_t *encoding, const type_t *type)
|
|||
if (!type)
|
||||
return;
|
||||
switch (type->meta) {
|
||||
case ty_handle:
|
||||
dasprintf (encoding, "{%s$}", type->name);
|
||||
return;
|
||||
case ty_alias:
|
||||
dasprintf (encoding, "{%s>", type->name ? type->name : "");
|
||||
encode_type (encoding, type->t.alias.aux_type);
|
||||
|
@ -1331,6 +1344,7 @@ int
|
|||
type_size (const type_t *type)
|
||||
{
|
||||
switch (type->meta) {
|
||||
case ty_handle:
|
||||
case ty_basic:
|
||||
return pr_type_size[type->type] * type->width;
|
||||
case ty_struct:
|
||||
|
@ -1373,6 +1387,7 @@ type_width (const type_t *type)
|
|||
return 4;
|
||||
}
|
||||
return type->width;
|
||||
case ty_handle:
|
||||
case ty_struct:
|
||||
case ty_union:
|
||||
return 1;
|
||||
|
|
Loading…
Reference in a new issue