[qfcc] Implement goto

It's just too useful when used correctly.
This commit is contained in:
Bill Currie 2020-03-11 12:53:40 +09:00
parent 4a8854d9ed
commit 813319efc2
3 changed files with 19 additions and 7 deletions

View file

@ -353,6 +353,7 @@ static keyword_t obj_keywords[] = {
// make the language features available to traditional code.
static keyword_t at_keywords[] = {
{"for", FOR },
{"goto", GOTO },
{"break", BREAK },
{"continue", CONTINUE},
{"switch", SWITCH },

View file

@ -145,8 +145,8 @@ int yylex (void);
%token <expr> VALUE STRING
%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS
%token NIL IFBE IFB IFAE IFA SWITCH CASE DEFAULT ENUM TYPEDEF
%token ARGS EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT
%token NIL IFBE IFB IFAE IFA GOTO SWITCH CASE DEFAULT ENUM
%token ARGS TYPEDEF EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT
%token <op> STRUCT
%token <type> TYPE
%token <symbol> OBJECT TYPE_NAME
@ -1310,6 +1310,11 @@ statement
switch_block = $5;
break_label = $2;
}
| GOTO NAME
{
expr_t *label = named_label_expr ($2);
$$ = goto_expr (label);
}
| IF not '(' texpr ')' statement %prec IFX
{
$$ = build_if_statement ($2, $4, $6, 0, 0);

View file

@ -1551,7 +1551,7 @@ remove_label_from_dest (ex_label_t *label)
sblock_t *sblock;
ex_label_t **l;
if (!label)
if (!label || !label->dest)
return;
debug (0, "dropping deceased label %s", label->name);
@ -1588,14 +1588,20 @@ thread_jumps (sblock_t *blocks)
if (!sblock->statements)
continue;
s = (statement_t *) sblock->tail;
if (statement_is_goto (s))
if (statement_is_goto (s)) {
label = &s->opa->o.label;
else if (statement_is_cond (s))
if (!(*label)->dest && s->opa->expr) {
error (s->opa->expr, "undefined label `%s'", (*label)->name);
s->opa->expr = 0;
}
} else if (statement_is_cond (s)) {
label = &s->opb->o.label;
else
} else {
continue;
}
for (l = *label;
l->dest->statements && statement_is_goto (l->dest->statements);
l->dest && l->dest->statements
&& statement_is_goto (l->dest->statements);
l = l->dest->statements->opa->o.label) {
}
if (l != *label) {