diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index f1fdf307d..c11d43fe5 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -111,6 +111,8 @@ void category_add_protocols (category_t *category, protocollist_t *protocols); void class_finish_module (void); void class_to_struct (class_t *class, struct struct_s *strct); +void emit_class_ref (const char *class_name); +void emit_category_ref (const char *class_name, const char *category_name); protocol_t *get_protocol (const char *name, int create); void protocol_add_methods (protocol_t *protocol, struct methodlist_s *methods); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index ec5fcb433..b6a3c342c 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -250,7 +250,7 @@ class_begin (class_type_t *class_type) } } -static void +void emit_class_ref (const char *class_name) { def_t *def; @@ -283,6 +283,27 @@ emit_class_name (const char *class_name) G_INT (def->ofs) = 0; } +void +emit_category_ref (const char *class_name, const char *category_name) +{ + def_t *def; + def_t *ref; + + def = get_def (&type_pointer, + va (".obj_category_ref_%s_%s", class_name, category_name), + pr.scope, st_static); + if (def->initialized) + return; + def->initialized = def->constant = 1; + def->nosave = 1; + ref = get_def (&type_integer, + va (".obj_category_name_%s_%s", class_name, category_name), + pr.scope, st_extern); + if (!ref->external) + G_INT (def->ofs) = ref->ofs; + reloc_def_def (ref, def->ofs); +} + static void emit_category_name (const char *class_name, const char *category_name) { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index aaaefd331..8981fa0fe 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -306,6 +306,7 @@ static keyword_t keywords[] = { {"@protected", PROTECTED, 0, 0, PROG_VERSION}, {"@protocol", PROTOCOL, 0, 0, PROG_VERSION}, {"@public", PUBLIC, 0, 0, PROG_VERSION}, + {"@reference", REFERENCE, 0, 0, PROG_VERSION}, {"@selector", SELECTOR, 0, 0, PROG_VERSION}, {"@self", SELF, 0, 0, PROG_VERSION}, {"@this", THIS, 0, 0, PROG_VERSION}, diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index f92d57f3d..bd42c9e2b 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -162,7 +162,7 @@ expr_t *argv_expr (void); %token TYPE %token TYPE_NAME %token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE PROTECTED -%token PROTOCOL PUBLIC SELECTOR +%token PROTOCOL PUBLIC SELECTOR REFERENCE %type type non_field_type type_name def simple_def struct_def %type struct_def_item ivar_decl ivar_declarator def_item def_list @@ -1307,6 +1307,21 @@ new_category_name } ; +class_reference + : identifier + { + emit_class_ref ($1); + } + ; + +category_reference + : identifier '(' identifier ')' + { + emit_category_ref ($1, $3); + } + ; + + protocol_name : identifier { @@ -1404,6 +1419,8 @@ classdef } | IMPLEMENTATION class_with_super { class_begin (&$2->class_type); } | IMPLEMENTATION category_name { class_begin (&$2->class_type); } + | REFERENCE class_reference ';' { } + | REFERENCE category_reference ';' { } ; protocoldef diff --git a/tools/qfcc/test/reference.r b/tools/qfcc/test/reference.r new file mode 100644 index 000000000..453e356fd --- /dev/null +++ b/tools/qfcc/test/reference.r @@ -0,0 +1,2 @@ +@reference Array(Private); +@reference Foo;