diff options
author | unknown <pem@mysql.com> | 2002-12-16 15:40:44 +0100 |
---|---|---|
committer | unknown <pem@mysql.com> | 2002-12-16 15:40:44 +0100 |
commit | f6611aa0ab45aa5586101b34c444b8fab305fac9 (patch) | |
tree | 6a965cec0f444a67ed29877855da3a7309f6dce5 | |
parent | 390b3e745c05a39704c01365958710189e216f79 (diff) | |
download | mariadb-git-f6611aa0ab45aa5586101b34c444b8fab305fac9.tar.gz |
Fixed the broken backpatching implementation.
Implemented IF-THEN-ELSE.
sql/sp_head.cc:
Reimplemented the broken backpatching, so it works for nested constructions and
IF-THEN-ELSE too.
sql/sp_head.h:
Reimplemented the broken backpatching, so it works for nested constructions and
IF-THEN-ELSE too.
sql/sp_pcontext.cc:
Return the value from push-methods, for convenience.
sql/sp_pcontext.h:
Return the value from push-methods, for convenience.
sql/sql_yacc.yy:
Implemented IF-THEN-ELSE.
Corrected for the new backpatch method.
-rw-r--r-- | sql/sp_head.cc | 29 | ||||
-rw-r--r-- | sql/sp_head.h | 16 | ||||
-rw-r--r-- | sql/sp_pcontext.cc | 9 | ||||
-rw-r--r-- | sql/sp_pcontext.h | 10 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 66 |
5 files changed, 96 insertions, 34 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc index a2a40d08ecb..226701bafe4 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -260,25 +260,32 @@ sp_head::restore_lex(THD *thd) } void -sp_head::push_backpatch(sp_instr *i) +sp_head::push_backpatch(sp_instr *i, sp_label_t *lab) { - (void)m_backpatch.push_front(i); + bp_t *bp= (bp_t *)my_malloc(sizeof(bp_t), MYF(MY_WME)); + + if (bp) + { + bp->lab= lab; + bp->instr= i; + (void)m_backpatch.push_front(bp); + } } void -sp_head::backpatch() +sp_head::backpatch(sp_label_t *lab) { - sp_instr *ip; + bp_t *bp; uint dest= instructions(); - List_iterator_fast<sp_instr> li(m_backpatch); + List_iterator_fast<bp_t> li(m_backpatch); - while ((ip= li++)) - { - sp_instr_jump *i= static_cast<sp_instr_jump *>(ip); + while ((bp= li++)) + if (bp->lab == lab) + { + sp_instr_jump *i= static_cast<sp_instr_jump *>(bp->instr); - i->set_destination(dest); - } - m_backpatch.empty(); + i->set_destination(dest); + } } diff --git a/sql/sp_head.h b/sql/sp_head.h index 87f2b78b9fd..097eb6718e6 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -24,6 +24,8 @@ #include <stddef.h> +struct sp_label; + class sp_instr; class sp_head : public Sql_alloc @@ -72,11 +74,14 @@ public: void restore_lex(THD *thd); + // Put the instruction on the backpatch list, associated with the label. void - push_backpatch(sp_instr *i); + push_backpatch(sp_instr *, struct sp_label *); + // Update all instruction with this label in the backpatch list to + // the current position. void - backpatch(); + backpatch(struct sp_label *); private: @@ -85,7 +90,12 @@ private: LEX *m_mylex; // My own lex LEX m_lex; // Temp. store for the other lex DYNAMIC_ARRAY m_instr; // The "instructions" - List<sp_instr> m_backpatch; // Instructions needing backpaching + typedef struct + { + struct sp_label *lab; + sp_instr *instr; + } bp_t; + List<bp_t> m_backpatch; // Instructions needing backpaching inline sp_instr * get_instr(uint i) diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 9dc995f582f..96296e54184 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -92,7 +92,7 @@ sp_pcontext::push(LEX_STRING *name, enum enum_field_types type, } } -void +sp_label_t * sp_pcontext::push_label(char *name, uint ip) { sp_label_t *lab = (sp_label_t *)my_malloc(sizeof(sp_label_t), MYF(MY_WME)); @@ -103,18 +103,21 @@ sp_pcontext::push_label(char *name, uint ip) lab->ip= ip; m_label.push_front(lab); } + return lab; } -void +sp_label_t * sp_pcontext::push_gen_label(uint ip) { + sp_label_t *lab= NULL; char *s= my_malloc(10, MYF(MY_WME)); // 10=... if (s) { sprintf(s, ".%08x", m_genlab++); // ...9+1 - push_label(s, ip); + lab= push_label(s, ip); } + return lab; } sp_label_t * diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 7c8e2ba0c43..2eb59172365 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -38,7 +38,7 @@ typedef struct my_bool isset; } sp_pvar_t; -typedef struct +typedef struct sp_label { char *name; uint ip; // Instruction index @@ -116,10 +116,10 @@ class sp_pcontext : public Sql_alloc return m_pvar+i; } - void + sp_label_t * push_label(char *name, uint ip); - void + sp_label_t * push_gen_label(uint ip); sp_label_t * @@ -131,10 +131,10 @@ class sp_pcontext : public Sql_alloc return m_label.head(); } - inline void + inline sp_label_t * pop_label() { - m_label.pop(); + return m_label.pop(); } private: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 30f9fe97ec5..3d562dcfdbe 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1044,25 +1044,25 @@ sp_proc_stmt: lex->sphead->add_instr(i); lex->sphead->restore_lex(YYTHD); } -/* | sp_if - | sp_case */ + | IF sp_if END IF {} +/* | sp_case */ | sp_labeled_control {} | { /* Unlabeled controls get a secret label. */ LEX *lex= Lex; - Lex->spcont->push_gen_label(lex->sphead->instructions()); + lex->spcont->push_gen_label(lex->sphead->instructions()); } sp_unlabeled_control { LEX *lex= Lex; - lex->spcont->pop_label(); - lex->sphead->backpatch(); + lex->sphead->backpatch(lex->spcont->pop_label()); } | LEAVE_SYM IDENT { LEX *lex= Lex; + sp_head *sp = lex->sphead; sp_label_t *lab= lex->spcont->find_label($2.str); if (! lab) @@ -1072,10 +1072,10 @@ sp_proc_stmt: } else { - sp_instr_jump *i= new sp_instr_jump(lex->sphead->instructions()); + sp_instr_jump *i= new sp_instr_jump(sp->instructions()); - lex->sphead->push_backpatch(i); /* Jumping forward */ - lex->sphead->add_instr(i); + sp->push_backpatch(i, lab); /* Jumping forward */ + sp->add_instr(i); } } | ITERATE_SYM IDENT @@ -1119,6 +1119,44 @@ sp_proc_stmt: } ; +sp_if: + expr THEN_SYM + { + sp_head *sp= Lex->sphead; + sp_pcontext *ctx= Lex->spcont; + uint ip= sp->instructions(); + sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $1); + + sp->push_backpatch(i, ctx->push_gen_label(0)); /* Forward only */ + sp->add_instr(i); + } + sp_proc_stmts + { + sp_head *sp= Lex->sphead; + sp_pcontext *ctx= Lex->spcont; + uint ip= sp->instructions(); + sp_instr_jump *i = new sp_instr_jump(ip); + + sp->add_instr(i); + sp->backpatch(ctx->pop_label()); + sp->push_backpatch(i, ctx->push_gen_label(0)); /* Forward only */ + } + sp_elseifs + { + LEX *lex= Lex; + sp_head *sp= lex->sphead; + sp_pcontext *ctx= lex->spcont; + + sp->backpatch(ctx->pop_label()); + } + ; + +sp_elseifs: + /* Empty */ + | ELSEIF_SYM sp_if + | ELSE sp_proc_stmts + ; + sp_labeled_control: IDENT ':' { @@ -1131,8 +1169,10 @@ sp_labeled_control: YYABORT; } else + { lex->spcont->push_label($1.str, lex->sphead->instructions()); + } } sp_unlabeled_control IDENT { @@ -1152,7 +1192,7 @@ sp_labeled_control: else { lex->spcont->pop_label(); - lex->sphead->backpatch(); + lex->sphead->backpatch(lab); } } ; @@ -1180,11 +1220,13 @@ sp_unlabeled_control: | WHILE_SYM expr DO_SYM { LEX *lex= Lex; - uint ip= lex->sphead->instructions(); + sp_head *sp= lex->sphead; + uint ip= sp->instructions(); sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $2); - lex->sphead->push_backpatch(i); /* Jumping forward */ - lex->sphead->add_instr(i); + /* Jumping forward */ + sp->push_backpatch(i, lex->spcont->last_label()); + sp->add_instr(i); } sp_proc_stmts END WHILE_SYM { |