mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-14 00:40:55 +00:00
[qfcc] Add support for named labels in statements
Yeah, I've finally decided to implement goto. Limited to function scope of course.
This commit is contained in:
parent
d5560434c0
commit
1cd5ea5732
5 changed files with 45 additions and 1 deletions
|
@ -290,6 +290,19 @@ const char *new_label_name (void);
|
||||||
*/
|
*/
|
||||||
expr_t *new_label_expr (void);
|
expr_t *new_label_expr (void);
|
||||||
|
|
||||||
|
/** Create a named label expression node.
|
||||||
|
|
||||||
|
The label name is set using new_label_name(), but the symbol is used to add
|
||||||
|
the label to the function's label scope symbol table. If the label already
|
||||||
|
exists in the function's label scope, then the existing label is returned,
|
||||||
|
allowing for forward label declarations.
|
||||||
|
|
||||||
|
\param label The name symbol to use for adding the label to the function
|
||||||
|
label scope.
|
||||||
|
\return The new label expression (::ex_label_t) node.
|
||||||
|
*/
|
||||||
|
expr_t *named_label_expr (struct symbol_s *label);
|
||||||
|
|
||||||
/** Create a new label reference expression node.
|
/** Create a new label reference expression node.
|
||||||
|
|
||||||
Used for taking the address of a label (eg. jump tables).
|
Used for taking the address of a label (eg. jump tables).
|
||||||
|
|
|
@ -79,6 +79,7 @@ typedef struct function_s {
|
||||||
scope symbol table's defspace.
|
scope symbol table's defspace.
|
||||||
*/
|
*/
|
||||||
struct symtab_s *symtab;
|
struct symtab_s *symtab;
|
||||||
|
struct symtab_s *label_scope;
|
||||||
struct reloc_s *refs; ///< relocation targets for this function
|
struct reloc_s *refs; ///< relocation targets for this function
|
||||||
struct expr_s *var_init;
|
struct expr_s *var_init;
|
||||||
const char *name; ///< nice name for __PRETTY_FUNCTION__
|
const char *name; ///< nice name for __PRETTY_FUNCTION__
|
||||||
|
|
|
@ -495,6 +495,27 @@ new_label_expr (void)
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_t *
|
||||||
|
named_label_expr (symbol_t *label)
|
||||||
|
{
|
||||||
|
symbol_t *sym;
|
||||||
|
|
||||||
|
if (!current_func) {
|
||||||
|
// XXX this might be only an error
|
||||||
|
internal_error (0, "label defined outside of function scope");
|
||||||
|
}
|
||||||
|
|
||||||
|
sym = symtab_lookup (current_func->label_scope, label->name);
|
||||||
|
|
||||||
|
if (sym) {
|
||||||
|
return sym->s.expr;
|
||||||
|
}
|
||||||
|
label->sy_type = sy_expr;
|
||||||
|
label->s.expr = new_label_expr ();
|
||||||
|
symtab_addsymbol (current_func->label_scope, label);
|
||||||
|
return label->s.expr;
|
||||||
|
}
|
||||||
|
|
||||||
expr_t *
|
expr_t *
|
||||||
new_label_ref (ex_label_t *label)
|
new_label_ref (ex_label_t *label)
|
||||||
{
|
{
|
||||||
|
|
|
@ -493,6 +493,7 @@ build_scope (symbol_t *fsym, symtab_t *parent)
|
||||||
|
|
||||||
symtab = new_symtab (parent, stab_local);
|
symtab = new_symtab (parent, stab_local);
|
||||||
fsym->s.func->symtab = symtab;
|
fsym->s.func->symtab = symtab;
|
||||||
|
fsym->s.func->label_scope = new_symtab (0, stab_local);
|
||||||
symtab->space = defspace_new (ds_virtual);
|
symtab->space = defspace_new (ds_virtual);
|
||||||
current_symtab = symtab;
|
current_symtab = symtab;
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ int yylex (void);
|
||||||
%type <expr> unary_expr ident_expr cast_expr opt_arg_list arg_list
|
%type <expr> unary_expr ident_expr cast_expr opt_arg_list arg_list
|
||||||
%type <expr> init_var_decl_list init_var_decl
|
%type <expr> init_var_decl_list init_var_decl
|
||||||
%type <switch_block> switch_block
|
%type <switch_block> switch_block
|
||||||
%type <symbol> identifier
|
%type <symbol> identifier label
|
||||||
|
|
||||||
%type <symbol> overloaded_identifier
|
%type <symbol> overloaded_identifier
|
||||||
|
|
||||||
|
@ -1292,6 +1292,10 @@ statement
|
||||||
else
|
else
|
||||||
error (0, "continue outside of loop");
|
error (0, "continue outside of loop");
|
||||||
}
|
}
|
||||||
|
| label
|
||||||
|
{
|
||||||
|
$$ = named_label_expr ($1);
|
||||||
|
}
|
||||||
| CASE expr ':'
|
| CASE expr ':'
|
||||||
{
|
{
|
||||||
$$ = case_label_expr (switch_block, $2);
|
$$ = case_label_expr (switch_block, $2);
|
||||||
|
@ -1358,6 +1362,10 @@ else
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
label
|
||||||
|
: NAME ':'
|
||||||
|
;
|
||||||
|
|
||||||
bool_label
|
bool_label
|
||||||
: /* empty */
|
: /* empty */
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue