Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
fc0ef22a
Commit
fc0ef22a
authored
Mar 21, 2014
by
Jacek Caban
Committed by
Alexandre Julliard
Mar 21, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
vbscript: Added support for exception unwinding.
parent
ce75124a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
155 additions
and
17 deletions
+155
-17
compile.c
dlls/vbscript/compile.c
+96
-8
interp.c
dlls/vbscript/interp.c
+56
-9
vbscript.h
dlls/vbscript/vbscript.h
+3
-0
No files found.
dlls/vbscript/compile.c
View file @
fc0ef22a
...
...
@@ -346,6 +346,35 @@ static inline void label_set_addr(compile_ctx_t *ctx, unsigned label)
ctx
->
labels
[
label
&
~
LABEL_FLAG
]
=
ctx
->
instr_cnt
;
}
static
inline
unsigned
stack_offset
(
compile_ctx_t
*
ctx
)
{
statement_ctx_t
*
iter
;
unsigned
ret
=
0
;
for
(
iter
=
ctx
->
stat_ctx
;
iter
;
iter
=
iter
->
next
)
ret
+=
iter
->
stack_use
;
return
ret
;
}
static
BOOL
emit_catch_jmp
(
compile_ctx_t
*
ctx
,
unsigned
stack_off
,
unsigned
code_off
)
{
unsigned
code
;
code
=
push_instr
(
ctx
,
OP_catch
);
if
(
!
code
)
return
FALSE
;
instr_ptr
(
ctx
,
code
)
->
arg1
.
uint
=
code_off
;
instr_ptr
(
ctx
,
code
)
->
arg2
.
uint
=
stack_off
+
stack_offset
(
ctx
);
return
TRUE
;
}
static
inline
BOOL
emit_catch
(
compile_ctx_t
*
ctx
,
unsigned
off
)
{
return
emit_catch_jmp
(
ctx
,
off
,
ctx
->
instr_cnt
);
}
static
expression_t
*
lookup_const_decls
(
compile_ctx_t
*
ctx
,
const
WCHAR
*
name
,
BOOL
lookup_global
)
{
const_decl_t
*
decl
;
...
...
@@ -533,6 +562,9 @@ static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
if
(
!
cnd_jmp
)
return
E_OUTOFMEMORY
;
if
(
!
emit_catch
(
ctx
,
0
))
return
E_OUTOFMEMORY
;
hres
=
compile_statement
(
ctx
,
NULL
,
stat
->
if_stat
);
if
(
FAILED
(
hres
))
return
hres
;
...
...
@@ -558,6 +590,9 @@ static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
if
(
!
cnd_jmp
)
return
E_OUTOFMEMORY
;
if
(
!
emit_catch
(
ctx
,
0
))
return
E_OUTOFMEMORY
;
hres
=
compile_statement
(
ctx
,
NULL
,
elseif_decl
->
stat
);
if
(
FAILED
(
hres
))
return
hres
;
...
...
@@ -597,6 +632,9 @@ static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *st
if
(
!
jmp_end
)
return
E_OUTOFMEMORY
;
if
(
!
emit_catch
(
ctx
,
0
))
return
E_OUTOFMEMORY
;
if
(
stat
->
stat
.
type
==
STAT_WHILE
)
{
loop_ctx
=
NULL
;
}
else
{
...
...
@@ -652,6 +690,10 @@ static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t *
return
hres
;
label_set_addr
(
ctx
,
loop_ctx
.
while_end_label
);
if
(
!
emit_catch
(
ctx
,
0
))
return
E_OUTOFMEMORY
;
return
S_OK
;
}
...
...
@@ -661,6 +703,10 @@ static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t
unsigned
loop_start
;
HRESULT
hres
;
/* Preserve a place on the stack in case we throw before having proper enum collection. */
if
(
!
push_instr
(
ctx
,
OP_empty
))
return
E_OUTOFMEMORY
;
hres
=
compile_expression
(
ctx
,
stat
->
group_expr
);
if
(
FAILED
(
hres
))
return
hres
;
...
...
@@ -668,7 +714,6 @@ static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t
if
(
!
push_instr
(
ctx
,
OP_newenum
))
return
E_OUTOFMEMORY
;
loop_start
=
ctx
->
instr_cnt
;
if
(
!
(
loop_ctx
.
for_end_label
=
alloc_label
(
ctx
)))
return
E_OUTOFMEMORY
;
...
...
@@ -676,10 +721,19 @@ static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t
if
(
FAILED
(
hres
))
return
hres
;
if
(
!
emit_catch
(
ctx
,
1
))
return
E_OUTOFMEMORY
;
loop_start
=
ctx
->
instr_cnt
;
hres
=
compile_statement
(
ctx
,
&
loop_ctx
,
stat
->
body
);
if
(
FAILED
(
hres
))
return
hres
;
/* We need a separated enumnext here, because we need to jump out of the loop on exception. */
hres
=
push_instr_uint_bstr
(
ctx
,
OP_enumnext
,
loop_ctx
.
for_end_label
,
stat
->
identifier
);
if
(
FAILED
(
hres
))
return
hres
;
hres
=
push_instr_addr
(
ctx
,
OP_jmp
,
loop_start
);
if
(
FAILED
(
hres
))
return
hres
;
...
...
@@ -703,6 +757,7 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st
if
(
FAILED
(
hres
))
return
hres
;
/* FIXME: Assign should happen after both expressions evaluation. */
instr
=
push_instr
(
ctx
,
OP_assign_ident
);
if
(
!
instr
)
return
E_OUTOFMEMORY
;
...
...
@@ -739,10 +794,14 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st
instr_ptr
(
ctx
,
step_instr
)
->
arg2
.
bstr
=
identifier
;
instr_ptr
(
ctx
,
step_instr
)
->
arg1
.
uint
=
loop_ctx
.
for_end_label
;
if
(
!
emit_catch
(
ctx
,
2
))
return
E_OUTOFMEMORY
;
hres
=
compile_statement
(
ctx
,
&
loop_ctx
,
stat
->
body
);
if
(
FAILED
(
hres
))
return
hres
;
/* FIXME: Error handling can't be done compatible with native using OP_incc here. */
instr
=
push_instr
(
ctx
,
OP_incc
);
if
(
!
instr
)
return
E_OUTOFMEMORY
;
...
...
@@ -757,6 +816,11 @@ static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *st
return
hres
;
label_set_addr
(
ctx
,
loop_ctx
.
for_end_label
);
/* FIXME: reconsider after OP_incc fixup. */
if
(
!
emit_catch
(
ctx
,
0
))
return
E_OUTOFMEMORY
;
return
S_OK
;
}
...
...
@@ -778,6 +842,9 @@ static HRESULT compile_select_statement(compile_ctx_t *ctx, select_statement_t *
if
(
!
end_label
)
return
E_OUTOFMEMORY
;
if
(
!
emit_catch_jmp
(
ctx
,
0
,
end_label
))
return
E_OUTOFMEMORY
;
for
(
case_iter
=
stat
->
case_clausules
;
case_iter
;
case_iter
=
case_iter
->
next
)
case_cnt
++
;
...
...
@@ -805,6 +872,9 @@ static HRESULT compile_select_statement(compile_ctx_t *ctx, select_statement_t *
hres
=
push_instr_addr
(
ctx
,
OP_case
,
case_labels
[
i
]);
if
(
FAILED
(
hres
))
break
;
if
(
!
emit_catch_jmp
(
ctx
,
0
,
case_labels
[
i
]))
return
E_OUTOFMEMORY
;
}
}
...
...
@@ -871,7 +941,14 @@ static HRESULT compile_assignment(compile_ctx_t *ctx, member_expression_t *membe
if
(
FAILED
(
hres
))
return
hres
;
return
push_instr_bstr_uint
(
ctx
,
op
,
member_expr
->
identifier
,
args_cnt
);
hres
=
push_instr_bstr_uint
(
ctx
,
op
,
member_expr
->
identifier
,
args_cnt
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
!
emit_catch
(
ctx
,
0
))
return
E_OUTOFMEMORY
;
return
S_OK
;
}
static
HRESULT
compile_assign_statement
(
compile_ctx_t
*
ctx
,
assign_statement_t
*
stat
,
BOOL
is_set
)
...
...
@@ -881,6 +958,8 @@ static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *
static
HRESULT
compile_call_statement
(
compile_ctx_t
*
ctx
,
call_statement_t
*
stat
)
{
HRESULT
hres
;
/* It's challenging for parser to distinguish parameterized assignment with one argument from call
* with equality expression argument, so we do it in compiler. */
if
(
!
stat
->
is_strict
&&
stat
->
expr
->
args
&&
!
stat
->
expr
->
args
->
next
&&
stat
->
expr
->
args
->
type
==
EXPR_EQUAL
)
{
...
...
@@ -896,7 +975,14 @@ static HRESULT compile_call_statement(compile_ctx_t *ctx, call_statement_t *stat
}
}
return
compile_member_expression
(
ctx
,
stat
->
expr
,
FALSE
);
hres
=
compile_member_expression
(
ctx
,
stat
->
expr
,
FALSE
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
!
emit_catch
(
ctx
,
0
))
return
E_OUTOFMEMORY
;
return
S_OK
;
}
static
BOOL
lookup_dim_decls
(
compile_ctx_t
*
ctx
,
const
WCHAR
*
name
)
...
...
@@ -940,6 +1026,9 @@ static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
HRESULT
hres
=
push_instr_bstr_uint
(
ctx
,
OP_dim
,
dim_decl
->
name
,
ctx
->
func
->
array_cnt
++
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
!
emit_catch
(
ctx
,
0
))
return
E_OUTOFMEMORY
;
}
if
(
!
dim_decl
->
next
)
...
...
@@ -978,6 +1067,9 @@ static HRESULT compile_const_statement(compile_ctx_t *ctx, const_statement_t *st
hres
=
push_instr_bstr
(
ctx
,
OP_const
,
decl
->
name
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
!
emit_catch
(
ctx
,
0
))
return
E_OUTOFMEMORY
;
}
next_decl
=
decl
->
next
;
...
...
@@ -1054,11 +1146,7 @@ static HRESULT compile_exitfor_statement(compile_ctx_t *ctx)
static
HRESULT
exit_label
(
compile_ctx_t
*
ctx
,
unsigned
jmp_label
)
{
statement_ctx_t
*
iter
;
unsigned
pop_cnt
=
0
;
for
(
iter
=
ctx
->
stat_ctx
;
iter
;
iter
=
iter
->
next
)
pop_cnt
+=
iter
->
stack_use
;
unsigned
pop_cnt
=
stack_offset
(
ctx
);
if
(
pop_cnt
)
{
HRESULT
hres
;
...
...
dlls/vbscript/interp.c
View file @
fc0ef22a
...
...
@@ -1094,12 +1094,14 @@ static HRESULT interp_step(exec_ctx_t *ctx)
static
HRESULT
interp_newenum
(
exec_ctx_t
*
ctx
)
{
variant_val_t
v
;
VARIANT
r
;
VARIANT
*
r
;
HRESULT
hres
;
TRACE
(
"
\n
"
);
stack_pop_deref
(
ctx
,
&
v
);
assert
(
V_VT
(
stack_top
(
ctx
,
0
))
==
VT_EMPTY
);
r
=
stack_top
(
ctx
,
0
);
switch
(
V_VT
(
v
.
v
))
{
case
VT_DISPATCH
|
VT_BYREF
:
...
...
@@ -1126,8 +1128,8 @@ static HRESULT interp_newenum(exec_ctx_t *ctx)
return
hres
;
}
V_VT
(
&
r
)
=
VT_UNKNOWN
;
V_UNKNOWN
(
&
r
)
=
(
IUnknown
*
)
iter
;
V_VT
(
r
)
=
VT_UNKNOWN
;
V_UNKNOWN
(
r
)
=
(
IUnknown
*
)
iter
;
break
;
}
default:
...
...
@@ -1136,7 +1138,7 @@ static HRESULT interp_newenum(exec_ctx_t *ctx)
return
E_NOTIMPL
;
}
return
stack_push
(
ctx
,
&
r
)
;
return
S_OK
;
}
static
HRESULT
interp_enumnext
(
exec_ctx_t
*
ctx
)
...
...
@@ -1151,6 +1153,11 @@ static HRESULT interp_enumnext(exec_ctx_t *ctx)
TRACE
(
"
\n
"
);
if
(
V_VT
(
stack_top
(
ctx
,
0
))
==
VT_EMPTY
)
{
FIXME
(
"uninitialized
\n
"
);
return
E_FAIL
;
}
assert
(
V_VT
(
stack_top
(
ctx
,
0
))
==
VT_UNKNOWN
);
iter
=
(
IEnumVARIANT
*
)
V_UNKNOWN
(
stack_top
(
ctx
,
0
));
...
...
@@ -1960,6 +1967,12 @@ static HRESULT interp_incc(exec_ctx_t *ctx)
return
S_OK
;
}
static
HRESULT
interp_catch
(
exec_ctx_t
*
ctx
)
{
/* Nothing to do here, the OP is for unwinding only. */
return
S_OK
;
}
static
const
instr_func_t
op_funcs
[]
=
{
#define X(x,n,a,b) interp_ ## x,
OP_LIST
...
...
@@ -2094,12 +2107,46 @@ HRESULT exec_script(script_ctx_t *ctx, function_t *func, vbdisp_t *vbthis, DISPP
op
=
exec
.
instr
->
op
;
hres
=
op_funcs
[
op
](
&
exec
);
if
(
FAILED
(
hres
))
{
if
(
exec
.
resume_next
)
FIXME
(
"Failed %08x in resume next mode
\n
"
,
hres
);
else
ctx
->
err_number
=
hres
;
if
(
exec
.
resume_next
)
{
unsigned
stack_off
;
WARN
(
"Failed %08x in resume next mode
\n
"
,
hres
);
/*
* Unwinding here is simple. We need to find the next OP_catch, which contains
* information about expected stack size and jump offset on error. Generated
* bytecode needs to guarantee, that simple jump and stack adjustment will
* guarantee proper execution continuation.
*/
while
((
++
exec
.
instr
)
->
op
!=
OP_catch
);
TRACE
(
"unwind jmp %d stack_off %d
\n
"
,
exec
.
instr
->
arg1
.
uint
,
exec
.
instr
->
arg2
.
uint
);
instr_jmp
(
&
exec
,
exec
.
instr
->
arg1
.
uint
);
stack_off
=
exec
.
instr
->
arg2
.
uint
;
if
(
exec
.
top
>
stack_off
)
{
stack_popn
(
&
exec
,
exec
.
top
-
stack_off
);
}
else
if
(
exec
.
top
<
stack_off
)
{
VARIANT
v
;
V_VT
(
&
v
)
=
VT_EMPTY
;
while
(
exec
.
top
<
stack_off
)
{
hres
=
stack_push
(
&
exec
,
&
v
);
if
(
FAILED
(
hres
))
break
;
}
}
continue
;
}
else
{
WARN
(
"Failed %08x
\n
"
,
hres
);
stack_popn
(
&
exec
,
exec
.
top
);
break
;
stack_popn
(
&
exec
,
exec
.
top
);
break
;
}
}
exec
.
instr
+=
op_move
[
op
];
...
...
dlls/vbscript/vbscript.h
View file @
fc0ef22a
...
...
@@ -189,6 +189,8 @@ struct _script_ctx_t {
class_desc_t
err_desc
;
vbdisp_t
*
err_obj
;
HRESULT
err_number
;
dynamic_var_t
*
global_vars
;
function_t
*
global_funcs
;
class_desc_t
*
classes
;
...
...
@@ -222,6 +224,7 @@ typedef enum {
X(assign_ident, 1, ARG_BSTR, ARG_UINT) \
X(assign_member, 1, ARG_BSTR, ARG_UINT) \
X(bool, 1, ARG_INT, 0) \
X(catch, 1, ARG_ADDR, ARG_UINT) \
X(case, 0, ARG_ADDR, 0) \
X(concat, 1, 0, 0) \
X(const, 1, ARG_BSTR, 0) \
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment