mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +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);
|
||||
|
||||
/** 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.
|
||||
|
||||
Used for taking the address of a label (eg. jump tables).
|
||||
|
|
|
@ -79,6 +79,7 @@ typedef struct function_s {
|
|||
scope symbol table's defspace.
|
||||
*/
|
||||
struct symtab_s *symtab;
|
||||
struct symtab_s *label_scope;
|
||||
struct reloc_s *refs; ///< relocation targets for this function
|
||||
struct expr_s *var_init;
|
||||
const char *name; ///< nice name for __PRETTY_FUNCTION__
|
||||
|
|
|
@ -495,6 +495,27 @@ new_label_expr (void)
|
|||
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 *
|
||||
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);
|
||||
fsym->s.func->symtab = symtab;
|
||||
fsym->s.func->label_scope = new_symtab (0, stab_local);
|
||||
symtab->space = defspace_new (ds_virtual);
|
||||
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> init_var_decl_list init_var_decl
|
||||
%type <switch_block> switch_block
|
||||
%type <symbol> identifier
|
||||
%type <symbol> identifier label
|
||||
|
||||
%type <symbol> overloaded_identifier
|
||||
|
||||
|
@ -1292,6 +1292,10 @@ statement
|
|||
else
|
||||
error (0, "continue outside of loop");
|
||||
}
|
||||
| label
|
||||
{
|
||||
$$ = named_label_expr ($1);
|
||||
}
|
||||
| CASE expr ':'
|
||||
{
|
||||
$$ = case_label_expr (switch_block, $2);
|
||||
|
@ -1358,6 +1362,10 @@ else
|
|||
}
|
||||
;
|
||||
|
||||
label
|
||||
: NAME ':'
|
||||
;
|
||||
|
||||
bool_label
|
||||
: /* empty */
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue