Commit d7ace789 authored by pem@mysql.com's avatar pem@mysql.com

Merge mysql.com:/usr/local/bk/mysql-5.0

into mysql.com:/home/pem/work/mysql-5.0-merge
parents f1e280e2 38b4cbbb
...@@ -63,6 +63,11 @@ iterate foo; ...@@ -63,6 +63,11 @@ iterate foo;
end| end|
ERROR 42000: ITERATE with no matching label: foo ERROR 42000: ITERATE with no matching label: foo
create procedure foo() create procedure foo()
begin
goto foo;
end|
ERROR 42000: GOTO with no matching label: foo
create procedure foo()
foo: loop foo: loop
foo: loop foo: loop
set @x=2; set @x=2;
......
...@@ -398,6 +398,87 @@ id data ...@@ -398,6 +398,87 @@ id data
i 3 i 3
delete from t1| delete from t1|
drop procedure i| drop procedure i|
create procedure j()
begin
declare y int;
label a;
select * from t1;
select count(*) into y from t1;
if y > 2 then
goto b;
end if;
insert into t1 values ("j", y);
goto a;
label b;
end|
call j()|
id data
id data
j 0
id data
j 0
j 1
id data
j 0
j 1
j 2
drop procedure j|
create procedure k(a int)
begin
declare x int default 0;
declare continue handler for sqlstate '42S98' set x = 1;
label a;
select * from t1;
b:
while x < 2 do
begin
declare continue handler for sqlstate '42S99' set x = 2;
if a = 0 then
set x = x + 1;
iterate b;
elseif a = 1 then
leave b;
elseif a = 2 then
set a = 1;
goto a;
end if;
end;
end while b;
select * from t1;
end|
call k(0)|
id data
j 0
j 1
j 2
id data
j 0
j 1
j 2
call k(1)|
id data
j 0
j 1
j 2
id data
j 0
j 1
j 2
call k(2)|
id data
j 0
j 1
j 2
id data
j 0
j 1
j 2
id data
j 0
j 1
j 2
drop procedure k|
delete from t1|
insert into t1 values ("foo", 3), ("bar", 19)| insert into t1 values ("foo", 3), ("bar", 19)|
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)| insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
create procedure sel1() create procedure sel1()
...@@ -1487,7 +1568,7 @@ Grants for root@localhost ...@@ -1487,7 +1568,7 @@ Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
File Position Binlog_Do_DB Binlog_Ignore_DB File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 22185 master-bin.000001 22451
Database Table In_use Name_locked Database Table In_use Name_locked
Privilege Context Comment Privilege Context Comment
Alter Tables To alter the table Alter Tables To alter the table
...@@ -1541,7 +1622,7 @@ Grants for root@localhost ...@@ -1541,7 +1622,7 @@ Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
File Position Binlog_Do_DB Binlog_Ignore_DB File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 22185 master-bin.000001 22451
Database Table In_use Name_locked Database Table In_use Name_locked
Privilege Context Comment Privilege Context Comment
Alter Tables To alter the table Alter Tables To alter the table
...@@ -1580,10 +1661,10 @@ show processlist; ...@@ -1580,10 +1661,10 @@ show processlist;
end| end|
call bug4902_2()| call bug4902_2()|
Id User Host db Command Time State Info Id User Host db Command Time State Info
# root localhost test Query 0 NULL call bug4902_2() # root localhost test Query # NULL call bug4902_2()
call bug4902_2()| call bug4902_2()|
Id User Host db Command Time State Info Id User Host db Command Time State Info
# root localhost test Query 0 NULL call bug4902_2() # root localhost test Query # NULL call bug4902_2()
drop procedure bug4902_2| drop procedure bug4902_2|
drop table if exists t3| drop table if exists t3|
create procedure bug4904() create procedure bug4904()
......
...@@ -82,7 +82,7 @@ drop procedure if exists foo| ...@@ -82,7 +82,7 @@ drop procedure if exists foo|
--error 1304 --error 1304
show create procedure foo| show create procedure foo|
# LEAVE/ITERATE with no match # LEAVE/ITERATE/GOTO with no match
--error 1307 --error 1307
create procedure foo() create procedure foo()
foo: loop foo: loop
...@@ -98,6 +98,11 @@ create procedure foo() ...@@ -98,6 +98,11 @@ create procedure foo()
foo: begin foo: begin
iterate foo; iterate foo;
end| end|
--error 1307
create procedure foo()
begin
goto foo;
end|
# Redefining label # Redefining label
--error 1308 --error 1308
......
...@@ -468,6 +468,65 @@ delete from t1| ...@@ -468,6 +468,65 @@ delete from t1|
drop procedure i| drop procedure i|
# The non-standard GOTO, for compatibility
#
# QQQ The "label" syntax is temporary.
# QQQ This is no nearly enough, more tests are needed
#
create procedure j()
begin
declare y int;
label a;
select * from t1;
select count(*) into y from t1;
if y > 2 then
goto b;
end if;
insert into t1 values ("j", y);
goto a;
label b;
end|
call j()|
drop procedure j|
# With dummy handlers, just to test restore of contexts with jumps
create procedure k(a int)
begin
declare x int default 0;
declare continue handler for sqlstate '42S98' set x = 1;
label a;
select * from t1;
b:
while x < 2 do
begin
declare continue handler for sqlstate '42S99' set x = 2;
if a = 0 then
set x = x + 1;
iterate b;
elseif a = 1 then
leave b;
elseif a = 2 then
set a = 1;
goto a;
end if;
end;
end while b;
select * from t1;
end|
call k(0)|
call k(1)|
call k(2)|
drop procedure k|
delete from t1|
# SELECT with one of more result set sent back to the clinet # SELECT with one of more result set sent back to the clinet
insert into t1 values ("foo", 3), ("bar", 19)| insert into t1 values ("foo", 3), ("bar", 19)|
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)| insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
...@@ -1725,9 +1784,9 @@ create procedure bug4902_2() ...@@ -1725,9 +1784,9 @@ create procedure bug4902_2()
begin begin
show processlist; show processlist;
end| end|
--replace_column 1 # --replace_column 1 # 6 #
call bug4902_2()| call bug4902_2()|
--replace_column 1 # --replace_column 1 # 6 #
call bug4902_2()| call bug4902_2()|
drop procedure bug4902_2| drop procedure bug4902_2|
......
...@@ -209,6 +209,7 @@ static SYMBOL symbols[] = { ...@@ -209,6 +209,7 @@ static SYMBOL symbols[] = {
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)}, { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
{ "GET_FORMAT", SYM(GET_FORMAT)}, { "GET_FORMAT", SYM(GET_FORMAT)},
{ "GLOBAL", SYM(GLOBAL_SYM)}, { "GLOBAL", SYM(GLOBAL_SYM)},
{ "GOTO", SYM(GOTO_SYM)},
{ "GRANT", SYM(GRANT)}, { "GRANT", SYM(GRANT)},
{ "GRANTS", SYM(GRANTS)}, { "GRANTS", SYM(GRANTS)},
{ "GROUP", SYM(GROUP)}, { "GROUP", SYM(GROUP)},
...@@ -256,6 +257,7 @@ static SYMBOL symbols[] = { ...@@ -256,6 +257,7 @@ static SYMBOL symbols[] = {
{ "KEY", SYM(KEY_SYM)}, { "KEY", SYM(KEY_SYM)},
{ "KEYS", SYM(KEYS)}, { "KEYS", SYM(KEYS)},
{ "KILL", SYM(KILL_SYM)}, { "KILL", SYM(KILL_SYM)},
{ "LABEL", SYM(LABEL_SYM)},
{ "LANGUAGE", SYM(LANGUAGE_SYM)}, { "LANGUAGE", SYM(LANGUAGE_SYM)},
{ "LAST", SYM(LAST_SYM)}, { "LAST", SYM(LAST_SYM)},
{ "LEADING", SYM(LEADING)}, { "LEADING", SYM(LEADING)},
......
...@@ -846,14 +846,38 @@ sp_head::backpatch(sp_label_t *lab) ...@@ -846,14 +846,38 @@ sp_head::backpatch(sp_label_t *lab)
List_iterator_fast<bp_t> li(m_backpatch); List_iterator_fast<bp_t> li(m_backpatch);
while ((bp= li++)) while ((bp= li++))
if (bp->lab == lab)
{ {
sp_instr_jump *i= static_cast<sp_instr_jump *>(bp->instr); if (bp->lab == lab ||
(bp->lab->type == SP_LAB_REF &&
my_strcasecmp(system_charset_info, bp->lab->name, lab->name) == 0))
{
sp_scope_t sdiff;
i->set_destination(dest); if (bp->lab->type == SP_LAB_REF)
bp->lab= lab;
m_pcont->diff_scopes(0, &sdiff);
bp->instr->backpatch(dest, sdiff.hndlrs, sdiff.curs);
}
} }
} }
int
sp_head::check_backpatch(THD *thd)
{
bp_t *bp;
List_iterator_fast<bp_t> li(m_backpatch);
while ((bp= li++))
{
if (bp->lab->type == SP_LAB_REF)
{
net_printf(thd, ER_SP_LILABEL_MISMATCH, "GOTO", bp->lab->name);
return -1;
}
}
return 0;
}
void void
sp_head::set_info(char *definer, uint definerlen, sp_head::set_info(char *definer, uint definerlen,
longlong created, longlong modified, longlong created, longlong modified,
...@@ -1199,8 +1223,9 @@ sp_instr_jump::print(String *str) ...@@ -1199,8 +1223,9 @@ sp_instr_jump::print(String *str)
uint uint
sp_instr_jump::opt_mark(sp_head *sp) sp_instr_jump::opt_mark(sp_head *sp)
{ {
marked= 1;
m_dest= opt_shortcut_jump(sp); m_dest= opt_shortcut_jump(sp);
if (m_dest != m_ip+1) /* Jumping to following instruction? */
marked= 1;
m_optdest= sp->get_instr(m_dest); m_optdest= sp->get_instr(m_dest);
return m_dest; return m_dest;
} }
......
...@@ -182,6 +182,13 @@ public: ...@@ -182,6 +182,13 @@ public:
void void
backpatch(struct sp_label *); backpatch(struct sp_label *);
// Check that no unresolved references exist.
// If none found, 0 is returned, otherwise errors have been issued
// and -1 is returned.
// This is called by the parser at the end of a create procedure/function.
int
check_backpatch(THD *thd);
char *name(uint *lenp = 0) const char *name(uint *lenp = 0) const
{ {
if (lenp) if (lenp)
...@@ -272,7 +279,7 @@ public: ...@@ -272,7 +279,7 @@ public:
virtual void print(String *str) = 0; virtual void print(String *str) = 0;
virtual void set_destination(uint dest) virtual void backpatch(uint dest, uint hpop, uint cpop)
{} {}
virtual uint opt_mark(sp_head *sp) virtual uint opt_mark(sp_head *sp)
...@@ -394,8 +401,7 @@ public: ...@@ -394,8 +401,7 @@ public:
virtual void opt_move(uint dst, List<sp_instr> *ibp); virtual void opt_move(uint dst, List<sp_instr> *ibp);
virtual void virtual void backpatch(uint dest, uint hpop, uint cpop)
set_destination(uint dest)
{ {
if (m_dest == 0) // Don't reset if (m_dest == 0) // Don't reset
m_dest= dest; m_dest= dest;
...@@ -575,6 +581,21 @@ public: ...@@ -575,6 +581,21 @@ public:
virtual void print(String *str); virtual void print(String *str);
virtual void backpatch(uint dest, uint hpop, uint cpop)
{
if (hpop > m_count)
m_count= 0;
else
m_count-= hpop;
}
virtual uint opt_mark(sp_head *sp)
{
if (m_count)
marked= 1;
return m_ip+1;
}
private: private:
uint m_count; uint m_count;
...@@ -655,6 +676,21 @@ public: ...@@ -655,6 +676,21 @@ public:
virtual void print(String *str); virtual void print(String *str);
virtual void backpatch(uint dest, uint hpop, uint cpop)
{
if (cpop > m_count)
m_count= 0;
else
m_count-= cpop;
}
virtual uint opt_mark(sp_head *sp)
{
if (m_count)
marked= 1;
return m_ip+1;
}
private: private:
uint m_count; uint m_count;
......
...@@ -27,12 +27,14 @@ ...@@ -27,12 +27,14 @@
#include "sp_head.h" #include "sp_head.h"
sp_pcontext::sp_pcontext() sp_pcontext::sp_pcontext()
: Sql_alloc(), m_params(0), m_framesize(0), m_handlers(0), m_cursmax(0) : Sql_alloc(), m_params(0), m_framesize(0), m_handlers(0), m_cursmax(0),
m_hndlrlev(0)
{ {
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8)); VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8)); VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8)); VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8));
VOID(my_init_dynamic_array(&m_scopes, sizeof(sp_scope_t), 16, 8)); VOID(my_init_dynamic_array(&m_scopes, sizeof(sp_scope_t), 16, 8));
VOID(my_init_dynamic_array(&m_glabel, sizeof(sp_label_t *), 16, 8));
m_label.empty(); m_label.empty();
} }
...@@ -43,6 +45,7 @@ sp_pcontext::destroy() ...@@ -43,6 +45,7 @@ sp_pcontext::destroy()
delete_dynamic(&m_cond); delete_dynamic(&m_cond);
delete_dynamic(&m_cursor); delete_dynamic(&m_cursor);
delete_dynamic(&m_scopes); delete_dynamic(&m_scopes);
delete_dynamic(&m_glabel);
m_label.empty(); m_label.empty();
} }
...@@ -53,14 +56,46 @@ sp_pcontext::push_scope() ...@@ -53,14 +56,46 @@ sp_pcontext::push_scope()
s.vars= m_pvar.elements; s.vars= m_pvar.elements;
s.conds= m_cond.elements; s.conds= m_cond.elements;
s.hndlrs= m_hndlrlev;
s.curs= m_cursor.elements; s.curs= m_cursor.elements;
s.glab= m_glabel.elements;
insert_dynamic(&m_scopes, (gptr)&s); insert_dynamic(&m_scopes, (gptr)&s);
} }
void void
sp_pcontext::pop_scope() sp_pcontext::pop_scope(sp_scope_t *sp)
{ {
(void)pop_dynamic(&m_scopes); byte *p= pop_dynamic(&m_scopes);
if (sp && p)
memcpy(sp, p, sizeof(sp_scope_t));
}
void
sp_pcontext::diff_scopes(uint sold, sp_scope_t *diffs)
{
uint snew= m_scopes.elements;
sp_scope_t scope;
diffs->vars= diffs->conds= diffs->hndlrs= diffs->curs= diffs->glab= 0;
while (snew-- > sold)
{
get_dynamic(&m_scopes, (gptr)&scope, snew);
diffs->vars+= scope.vars;
diffs->conds+= scope.conds;
diffs->hndlrs+= scope.hndlrs;
diffs->curs+= scope.curs;
diffs->glab+= scope.glab;
}
if (sold)
{
get_dynamic(&m_scopes, (gptr)&scope, sold-1);
diffs->vars-= scope.vars;
diffs->conds-= scope.conds;
diffs->hndlrs-= scope.hndlrs;
diffs->curs-= scope.curs;
diffs->glab-= scope.glab;
}
} }
...@@ -132,7 +167,8 @@ sp_pcontext::push_label(char *name, uint ip) ...@@ -132,7 +167,8 @@ sp_pcontext::push_label(char *name, uint ip)
{ {
lab->name= name; lab->name= name;
lab->ip= ip; lab->ip= ip;
lab->isbegin= FALSE; lab->type= SP_LAB_GOTO;
lab->scopes= 0;
m_label.push_front(lab); m_label.push_front(lab);
} }
return lab; return lab;
...@@ -245,3 +281,41 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped) ...@@ -245,3 +281,41 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
} }
return FALSE; return FALSE;
} }
sp_label_t *
sp_pcontext::push_glabel(char *name, uint ip)
{
sp_label_t *lab = (sp_label_t *)sql_alloc(sizeof(sp_label_t));
if (lab)
{
lab->name= name;
lab->ip= ip;
lab->type= SP_LAB_GOTO;
lab->scopes= 0;
insert_dynamic(&m_glabel, (gptr)&lab);
}
return lab;
}
sp_label_t *
sp_pcontext::find_glabel(char *name)
{
uint i= m_glabel.elements;
while (i--)
{
sp_label_t *lab;
get_dynamic(&m_glabel, (gptr)&lab, i);
if (my_strcasecmp(system_charset_info, name, lab->name) == 0)
return lab;
}
return NULL;
}
void
sp_pcontext::pop_glabel(uint count)
{
(void)pop_dynamic(&m_glabel);
}
...@@ -39,11 +39,18 @@ typedef struct sp_pvar ...@@ -39,11 +39,18 @@ typedef struct sp_pvar
Item *dflt; Item *dflt;
} sp_pvar_t; } sp_pvar_t;
#define SP_LAB_REF 0 // Unresolved reference (for goto)
#define SP_LAB_GOTO 1 // Free goto label
#define SP_LAB_BEGIN 2 // Label at BEGIN
#define SP_LAB_ITER 3 // Label at iteration control
typedef struct sp_label typedef struct sp_label
{ {
char *name; char *name;
uint ip; // Instruction index uint ip; // Instruction index
my_bool isbegin; // For ITERATE error checking int type; // begin/iter or ref/free
uint scopes; // No. of scopes at label
} sp_label_t; } sp_label_t;
typedef struct sp_cond_type typedef struct sp_cond_type
...@@ -61,7 +68,7 @@ typedef struct sp_cond ...@@ -61,7 +68,7 @@ typedef struct sp_cond
typedef struct sp_scope typedef struct sp_scope
{ {
uint vars, conds, curs; uint vars, conds, hndlrs, curs, glab;
} sp_scope_t; } sp_scope_t;
class sp_pcontext : public Sql_alloc class sp_pcontext : public Sql_alloc
...@@ -82,7 +89,18 @@ class sp_pcontext : public Sql_alloc ...@@ -82,7 +89,18 @@ class sp_pcontext : public Sql_alloc
push_scope(); push_scope();
void void
pop_scope(); pop_scope(sp_scope_t *sp = 0);
uint
scopes()
{
return m_scopes.elements;
}
// Sets '*diffs' to the differences between current scope index snew and sold
void
diff_scopes(uint sold, sp_scope_t *diffs);
// //
// Parameters and variables // Parameters and variables
...@@ -223,6 +241,18 @@ class sp_pcontext : public Sql_alloc ...@@ -223,6 +241,18 @@ class sp_pcontext : public Sql_alloc
return m_handlers; return m_handlers;
} }
inline void
push_handlers(uint count)
{
m_hndlrlev+= count;
}
inline void
pop_handlers(uint count)
{
m_hndlrlev-= count;
}
// //
// Cursors // Cursors
// //
...@@ -246,17 +276,32 @@ class sp_pcontext : public Sql_alloc ...@@ -246,17 +276,32 @@ class sp_pcontext : public Sql_alloc
return m_cursmax; return m_cursmax;
} }
//
// GOTO labels
//
sp_label_t *
push_glabel(char *name, uint ip);
sp_label_t *
find_glabel(char *name);
void
pop_glabel(uint count);
private: private:
uint m_params; // The number of parameters uint m_params; // The number of parameters
uint m_framesize; // The maximum framesize uint m_framesize; // The maximum framesize
uint m_handlers; // The total number of handlers uint m_handlers; // The total number of handlers
uint m_cursmax; // The maximum number of cursors uint m_cursmax; // The maximum number of cursors
uint m_hndlrlev; // Current number of active handlers
DYNAMIC_ARRAY m_pvar; // Parameters/variables DYNAMIC_ARRAY m_pvar; // Parameters/variables
DYNAMIC_ARRAY m_cond; // Conditions DYNAMIC_ARRAY m_cond; // Conditions
DYNAMIC_ARRAY m_cursor; // Cursors DYNAMIC_ARRAY m_cursor; // Cursors
DYNAMIC_ARRAY m_scopes; // For error checking DYNAMIC_ARRAY m_scopes; // For error checking
DYNAMIC_ARRAY m_glabel; // Goto labels
List<sp_label_t> m_label; // The label list List<sp_label_t> m_label; // The label list
......
...@@ -611,6 +611,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -611,6 +611,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CURSOR_SYM %token CURSOR_SYM
%token ELSEIF_SYM %token ELSEIF_SYM
%token ITERATE_SYM %token ITERATE_SYM
%token GOTO_SYM
%token LABEL_SYM
%token LEAVE_SYM %token LEAVE_SYM
%token LOOP_SYM %token LOOP_SYM
%token REPEAT_SYM %token REPEAT_SYM
...@@ -1180,13 +1182,16 @@ create: ...@@ -1180,13 +1182,16 @@ create:
sp_proc_stmt sp_proc_stmt
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead;
lex->sphead->init_strings(YYTHD, lex, $3); if (sp->check_backpatch(YYTHD))
YYABORT;
sp->init_strings(YYTHD, lex, $3);
lex->sql_command= SQLCOM_CREATE_PROCEDURE; lex->sql_command= SQLCOM_CREATE_PROCEDURE;
/* Restore flag if it was cleared above */ /* Restore flag if it was cleared above */
if (lex->sphead->m_old_cmq) if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
lex->sphead->restore_thd_mem_root(YYTHD); sp->restore_thd_mem_root(YYTHD);
} }
| CREATE or_replace algorithm VIEW_SYM table_ident | CREATE or_replace algorithm VIEW_SYM table_ident
{ {
...@@ -1286,6 +1291,8 @@ create_function_tail: ...@@ -1286,6 +1291,8 @@ create_function_tail:
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
if (sp->check_backpatch(YYTHD))
YYABORT;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION; lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->init_strings(YYTHD, lex, lex->spname); sp->init_strings(YYTHD, lex, lex->spname);
/* Restore flag if it was cleared above */ /* Restore flag if it was cleared above */
...@@ -1816,7 +1823,8 @@ sp_proc_stmt: ...@@ -1816,7 +1823,8 @@ sp_proc_stmt:
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp = lex->sphead; sp_head *sp = lex->sphead;
sp_label_t *lab= lex->spcont->find_label($2.str); sp_pcontext *ctx= lex->spcont;
sp_label_t *lab= ctx->find_label($2.str);
if (! lab) if (! lab)
{ {
...@@ -1825,8 +1833,20 @@ sp_proc_stmt: ...@@ -1825,8 +1833,20 @@ sp_proc_stmt:
} }
else else
{ {
sp_instr_jump *i= new sp_instr_jump(sp->instructions()); uint ip= sp->instructions();
sp_scope_t sdiff;
sp_instr_jump *i;
sp_instr_hpop *ih;
sp_instr_cpop *ic;
ctx->diff_scopes(0, &sdiff);
ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
sp->push_backpatch(ih, lab);
sp->add_instr(ih);
ic= new sp_instr_cpop(ip++, sdiff.curs);
sp->push_backpatch(ic, lab);
sp->add_instr(ic);
i= new sp_instr_jump(ip);
sp->push_backpatch(i, lab); /* Jumping forward */ sp->push_backpatch(i, lab); /* Jumping forward */
sp->add_instr(i); sp->add_instr(i);
} }
...@@ -1834,19 +1854,101 @@ sp_proc_stmt: ...@@ -1834,19 +1854,101 @@ sp_proc_stmt:
| ITERATE_SYM IDENT | ITERATE_SYM IDENT
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_label_t *lab= lex->spcont->find_label($2.str); sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
sp_label_t *lab= ctx->find_label($2.str);
if (! lab || lab->isbegin) if (! lab || lab->type != SP_LAB_ITER)
{ {
net_printf(YYTHD, ER_SP_LILABEL_MISMATCH, "ITERATE", $2.str); net_printf(YYTHD, ER_SP_LILABEL_MISMATCH, "ITERATE", $2.str);
YYABORT; YYABORT;
} }
else else
{ {
sp_instr_jump *i;
uint ip= sp->instructions();
sp_scope_t sdiff;
ctx->diff_scopes(lab->scopes, &sdiff);
if (sdiff.hndlrs)
sp->add_instr(new sp_instr_hpop(ip++, sdiff.hndlrs));
if (sdiff.curs)
sp->add_instr(new sp_instr_cpop(ip++, sdiff.curs));
i= new sp_instr_jump(ip, lab->ip); /* Jump back */
sp->add_instr(i);
}
}
| LABEL_SYM IDENT
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
sp_label_t *lab= ctx->find_label($2.str);
if (! lab)
lab= ctx->find_glabel($2.str);
if (lab)
{
net_printf(YYTHD, ER_SP_LABEL_REDEFINE, $2.str);
YYABORT;
}
else
{
lab= ctx->push_glabel($2.str, sp->instructions());
lab->type= SP_LAB_GOTO;
lab->scopes= ctx->scopes();
sp->backpatch(lab);
}
}
| GOTO_SYM IDENT
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= lex->sphead->instructions(); uint ip= lex->sphead->instructions();
sp_instr_jump *i= new sp_instr_jump(ip, lab->ip); /* Jump back */ sp_label_t *lab= ctx->find_label($2.str);
sp_scope_t sdiff;
sp_instr_jump *i;
sp_instr_hpop *ih;
sp_instr_cpop *ic;
lex->sphead->add_instr(i); if (! lab)
lab= ctx->find_glabel($2.str);
if (! lab)
{
lab= (sp_label_t *)YYTHD->alloc(sizeof(sp_label_t));
lab->name= $2.str;
lab->ip= 0;
lab->type= SP_LAB_REF;
lab->scopes= 0;
ctx->diff_scopes(0, &sdiff);
ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
sp->push_backpatch(ih, lab);
sp->add_instr(ih);
ic= new sp_instr_cpop(ip++, sdiff.curs);
sp->add_instr(ic);
sp->push_backpatch(ic, lab);
i= new sp_instr_jump(ip);
sp->push_backpatch(i, lab); /* Jumping forward */
sp->add_instr(i);
}
else
{
ctx->diff_scopes(lab->scopes, &sdiff);
if (sdiff.hndlrs)
{
ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
sp->add_instr(ih);
}
if (sdiff.curs)
{
ic= new sp_instr_cpop(ip++, sdiff.curs);
sp->add_instr(ic);
}
i= new sp_instr_jump(ip, lab->ip); /* Jump back */
sp->add_instr(i);
} }
} }
| OPEN_SYM ident | OPEN_SYM ident
...@@ -2041,7 +2143,8 @@ sp_labeled_control: ...@@ -2041,7 +2143,8 @@ sp_labeled_control:
IDENT ':' IDENT ':'
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_label_t *lab= lex->spcont->find_label($1.str); sp_pcontext *ctx= lex->spcont;
sp_label_t *lab= ctx->find_label($1.str);
if (lab) if (lab)
{ {
...@@ -2050,8 +2153,10 @@ sp_labeled_control: ...@@ -2050,8 +2153,10 @@ sp_labeled_control:
} }
else else
{ {
lex->spcont->push_label($1.str, lab= lex->spcont->push_label($1.str,
lex->sphead->instructions()); lex->sphead->instructions());
lab->type= SP_LAB_ITER;
lab->scopes= ctx->scopes();
} }
} }
sp_unlabeled_control sp_opt_label sp_unlabeled_control sp_opt_label
...@@ -2088,27 +2193,33 @@ sp_unlabeled_control: ...@@ -2088,27 +2193,33 @@ sp_unlabeled_control:
LEX *lex= Lex; LEX *lex= Lex;
sp_label_t *lab= lex->spcont->last_label(); sp_label_t *lab= lex->spcont->last_label();
lab->isbegin= TRUE; lab->type= SP_LAB_BEGIN;
/* Scope duplicate checking */ /* Scope duplicate checking */
lex->spcont->push_scope(); lex->spcont->push_scope();
} }
sp_decls sp_decls
{
Lex->spcont->push_handlers($3.hndlrs);
}
sp_proc_stmts sp_proc_stmts
END END
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont; sp_pcontext *ctx= lex->spcont;
sp_scope_t scope;
sp->backpatch(ctx->last_label()); /* We always has a label */ sp->backpatch(ctx->last_label()); /* We always have a label */
ctx->pop_pvar($3.vars); ctx->pop_pvar($3.vars);
ctx->pop_cond($3.conds); ctx->pop_cond($3.conds);
ctx->pop_handlers($3.hndlrs);
ctx->pop_cursor($3.curs); ctx->pop_cursor($3.curs);
if ($3.hndlrs) if ($3.hndlrs)
sp->add_instr(new sp_instr_hpop(sp->instructions(),$3.hndlrs)); sp->add_instr(new sp_instr_hpop(sp->instructions(), $3.hndlrs));
if ($3.curs) if ($3.curs)
sp->add_instr(new sp_instr_cpop(sp->instructions(), $3.curs)); sp->add_instr(new sp_instr_cpop(sp->instructions(), $3.curs));
ctx->pop_scope(); ctx->pop_scope(&scope);
ctx->pop_glabel(scope.glab);
} }
| LOOP_SYM | LOOP_SYM
sp_proc_stmts END LOOP_SYM sp_proc_stmts END LOOP_SYM
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment