2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "parser.tab.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(vbscript
);
37 static HRESULT
compile_expression(compile_ctx_t
*,expression_t
*);
39 static inline void *compiler_alloc(vbscode_t
*vbscode
, size_t size
)
41 return vbsheap_alloc(&vbscode
->heap
, size
);
44 static WCHAR
*compiler_alloc_string(vbscode_t
*vbscode
, const WCHAR
*str
)
49 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
50 ret
= compiler_alloc(vbscode
, size
);
52 memcpy(ret
, str
, size
);
56 static inline instr_t
*instr_ptr(compile_ctx_t
*ctx
, unsigned id
)
58 assert(id
< ctx
->instr_cnt
);
59 return ctx
->code
->instrs
+ id
;
62 static unsigned push_instr(compile_ctx_t
*ctx
, vbsop_t op
)
64 assert(ctx
->instr_size
&& ctx
->instr_size
>= ctx
->instr_cnt
);
66 if(ctx
->instr_size
== ctx
->instr_cnt
) {
69 new_instr
= heap_realloc(ctx
->code
->instrs
, ctx
->instr_size
*2*sizeof(instr_t
));
73 ctx
->code
->instrs
= new_instr
;
77 ctx
->code
->instrs
[ctx
->instr_cnt
].op
= op
;
78 return ctx
->instr_cnt
++;
81 static HRESULT
push_instr_int(compile_ctx_t
*ctx
, vbsop_t op
, LONG arg
)
85 ret
= push_instr(ctx
, op
);
89 instr_ptr(ctx
, ret
)->arg1
.lng
= arg
;
93 static HRESULT
push_instr_str(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg
)
98 str
= compiler_alloc_string(ctx
->code
, arg
);
100 return E_OUTOFMEMORY
;
102 instr
= push_instr(ctx
, op
);
104 return E_OUTOFMEMORY
;
106 instr_ptr(ctx
, instr
)->arg1
.str
= str
;
110 static HRESULT
push_instr_double(compile_ctx_t
*ctx
, vbsop_t op
, double arg
)
115 d
= compiler_alloc(ctx
->code
, sizeof(double));
117 return E_OUTOFMEMORY
;
119 instr
= push_instr(ctx
, op
);
121 return E_OUTOFMEMORY
;
124 instr_ptr(ctx
, instr
)->arg1
.dbl
= d
;
128 static BSTR
alloc_bstr_arg(compile_ctx_t
*ctx
, const WCHAR
*str
)
130 if(!ctx
->code
->bstr_pool_size
) {
131 ctx
->code
->bstr_pool
= heap_alloc(8 * sizeof(BSTR
));
132 if(!ctx
->code
->bstr_pool
)
134 ctx
->code
->bstr_pool_size
= 8;
135 }else if(ctx
->code
->bstr_pool_size
== ctx
->code
->bstr_cnt
) {
138 new_pool
= heap_realloc(ctx
->code
->bstr_pool
, ctx
->code
->bstr_pool_size
*2*sizeof(BSTR
));
142 ctx
->code
->bstr_pool
= new_pool
;
143 ctx
->code
->bstr_pool_size
*= 2;
146 ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
] = SysAllocString(str
);
147 if(!ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
])
150 return ctx
->code
->bstr_pool
[ctx
->code
->bstr_cnt
++];
153 static HRESULT
push_instr_bstr_uint(compile_ctx_t
*ctx
, vbsop_t op
, const WCHAR
*arg1
, unsigned arg2
)
158 bstr
= alloc_bstr_arg(ctx
, arg1
);
160 return E_OUTOFMEMORY
;
162 instr
= push_instr(ctx
, op
);
164 return E_OUTOFMEMORY
;
166 instr_ptr(ctx
, instr
)->arg1
.bstr
= bstr
;
167 instr_ptr(ctx
, instr
)->arg2
.uint
= arg2
;
171 static HRESULT
compile_args(compile_ctx_t
*ctx
, expression_t
*args
, unsigned *ret
)
173 unsigned arg_cnt
= 0;
177 hres
= compile_expression(ctx
, args
);
189 static HRESULT
compile_member_expression(compile_ctx_t
*ctx
, member_expression_t
*expr
, BOOL ret_val
)
191 unsigned arg_cnt
= 0;
194 hres
= compile_args(ctx
, expr
->args
, &arg_cnt
);
199 FIXME("obj_expr not implemented\n");
202 hres
= push_instr_bstr_uint(ctx
, ret_val
? OP_icall
: OP_icallv
, expr
->identifier
, arg_cnt
);
208 static HRESULT
compile_unary_expression(compile_ctx_t
*ctx
, unary_expression_t
*expr
, vbsop_t op
)
212 hres
= compile_expression(ctx
, expr
->subexpr
);
216 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
219 static HRESULT
compile_binary_expression(compile_ctx_t
*ctx
, binary_expression_t
*expr
, vbsop_t op
)
223 hres
= compile_expression(ctx
, expr
->left
);
227 hres
= compile_expression(ctx
, expr
->right
);
231 return push_instr(ctx
, op
) == -1 ? E_OUTOFMEMORY
: S_OK
;
234 static HRESULT
compile_expression(compile_ctx_t
*ctx
, expression_t
*expr
)
238 return push_instr_int(ctx
, OP_bool
, ((bool_expression_t
*)expr
)->value
);
240 return push_instr_double(ctx
, OP_double
, ((double_expression_t
*)expr
)->value
);
242 return push_instr(ctx
, OP_empty
) != -1 ? S_OK
: E_OUTOFMEMORY
;
244 return compile_binary_expression(ctx
, (binary_expression_t
*)expr
, OP_equal
);
246 return compile_member_expression(ctx
, (member_expression_t
*)expr
, TRUE
);
248 return compile_unary_expression(ctx
, (unary_expression_t
*)expr
, OP_not
);
250 return push_instr(ctx
, OP_null
) != -1 ? S_OK
: E_OUTOFMEMORY
;
252 return push_instr_str(ctx
, OP_string
, ((string_expression_t
*)expr
)->value
);
254 return push_instr_int(ctx
, OP_short
, ((int_expression_t
*)expr
)->value
);
256 return push_instr_int(ctx
, OP_long
, ((int_expression_t
*)expr
)->value
);
258 FIXME("Unimplemented expression type %d\n", expr
->type
);
265 static HRESULT
compile_statement(compile_ctx_t
*ctx
, statement_t
*stat
)
272 hres
= compile_member_expression(ctx
, ((call_statement_t
*)stat
)->expr
, FALSE
);
275 FIXME("Unimplemented statement type %d\n", stat
->type
);
287 static HRESULT
compile_func(compile_ctx_t
*ctx
, statement_t
*stat
, function_t
*func
)
291 func
->code_off
= ctx
->instr_cnt
;
293 hres
= compile_statement(ctx
, stat
);
297 if(push_instr(ctx
, OP_ret
) == -1)
298 return E_OUTOFMEMORY
;
303 void release_vbscode(vbscode_t
*code
)
307 list_remove(&code
->entry
);
309 for(i
=0; i
< code
->bstr_cnt
; i
++)
310 SysFreeString(code
->bstr_pool
[i
]);
312 vbsheap_free(&code
->heap
);
314 heap_free(code
->bstr_pool
);
315 heap_free(code
->source
);
316 heap_free(code
->instrs
);
320 static vbscode_t
*alloc_vbscode(compile_ctx_t
*ctx
, const WCHAR
*source
)
324 ret
= heap_alloc(sizeof(*ret
));
328 ret
->source
= heap_strdupW(source
);
334 ret
->instrs
= heap_alloc(32*sizeof(instr_t
));
336 release_vbscode(ret
);
341 ctx
->instr_size
= 32;
342 vbsheap_init(&ret
->heap
);
344 ret
->option_explicit
= ctx
->parser
.option_explicit
;
346 ret
->bstr_pool
= NULL
;
347 ret
->bstr_pool_size
= 0;
350 ret
->global_code
.code_ctx
= ret
;
352 list_init(&ret
->entry
);
356 HRESULT
compile_script(script_ctx_t
*script
, const WCHAR
*src
, vbscode_t
**ret
)
361 hres
= parse_script(&ctx
.parser
, src
);
365 ctx
.code
= alloc_vbscode(&ctx
, src
);
367 return E_OUTOFMEMORY
;
369 hres
= compile_func(&ctx
, ctx
.parser
.stats
, &ctx
.code
->global_code
);
371 release_vbscode(ctx
.code
);
375 list_add_tail(&script
->code_list
, &ctx
.code
->entry
);