summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <pem@mysql.com>2002-12-16 15:40:44 +0100
committerunknown <pem@mysql.com>2002-12-16 15:40:44 +0100
commitf6611aa0ab45aa5586101b34c444b8fab305fac9 (patch)
tree6a965cec0f444a67ed29877855da3a7309f6dce5
parent390b3e745c05a39704c01365958710189e216f79 (diff)
downloadmariadb-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.cc29
-rw-r--r--sql/sp_head.h16
-rw-r--r--sql/sp_pcontext.cc9
-rw-r--r--sql/sp_pcontext.h10
-rw-r--r--sql/sql_yacc.yy66
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
{