winegstreamer: Use WAVE_FORMAT_PCM when possible for demux.
[wine] / dlls / vbscript / compile.c
1 /*
2  * Copyright 2011 Jacek Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include <assert.h>
20
21 #include "vbscript.h"
22 #include "parse.h"
23 #include "parser.tab.h"
24
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
28 WINE_DECLARE_DEBUG_CHANNEL(vbscript_disas);
29
30 typedef struct {
31     parser_ctx_t parser;
32
33     unsigned instr_cnt;
34     unsigned instr_size;
35     vbscode_t *code;
36
37     unsigned *labels;
38     unsigned labels_size;
39     unsigned labels_cnt;
40
41     unsigned sub_end_label;
42     unsigned func_end_label;
43
44     dim_decl_t *dim_decls;
45     dynamic_var_t *global_vars;
46
47     function_t *func;
48     function_t *funcs;
49     function_decl_t *func_decls;
50 } compile_ctx_t;
51
52 static HRESULT compile_expression(compile_ctx_t*,expression_t*);
53 static HRESULT compile_statement(compile_ctx_t*,statement_t*);
54
55 static const struct {
56     const char *op_str;
57     instr_arg_type_t arg1_type;
58     instr_arg_type_t arg2_type;
59 } instr_info[] = {
60 #define X(n,a,b,c) {#n,b,c},
61 OP_LIST
62 #undef X
63 };
64
65 static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg)
66 {
67     switch(type) {
68     case ARG_STR:
69     case ARG_BSTR:
70         TRACE_(vbscript_disas)("\t%s", debugstr_w(arg->str));
71         break;
72     case ARG_INT:
73         TRACE_(vbscript_disas)("\t%d", arg->uint);
74         break;
75     case ARG_UINT:
76     case ARG_ADDR:
77         TRACE_(vbscript_disas)("\t%u", arg->uint);
78         break;
79     case ARG_DOUBLE:
80         TRACE_(vbscript_disas)("\t%lf", *arg->dbl);
81         break;
82     case ARG_NONE:
83         break;
84     default:
85         assert(0);
86     }
87 }
88
89 static void dump_code(compile_ctx_t *ctx)
90 {
91     instr_t *instr;
92
93     for(instr = ctx->code->instrs; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
94         TRACE_(vbscript_disas)("%d:\t%s", instr-ctx->code->instrs, instr_info[instr->op].op_str);
95         dump_instr_arg(instr_info[instr->op].arg1_type, &instr->arg1);
96         dump_instr_arg(instr_info[instr->op].arg2_type, &instr->arg2);
97         TRACE_(vbscript_disas)("\n");
98     }
99 }
100
101 static inline void *compiler_alloc(vbscode_t *vbscode, size_t size)
102 {
103     return vbsheap_alloc(&vbscode->heap, size);
104 }
105
106 static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str)
107 {
108     size_t size;
109     WCHAR *ret;
110
111     size = (strlenW(str)+1)*sizeof(WCHAR);
112     ret = compiler_alloc(vbscode, size);
113     if(ret)
114         memcpy(ret, str, size);
115     return ret;
116 }
117
118 static inline instr_t *instr_ptr(compile_ctx_t *ctx, unsigned id)
119 {
120     assert(id < ctx->instr_cnt);
121     return ctx->code->instrs + id;
122 }
123
124 static unsigned push_instr(compile_ctx_t *ctx, vbsop_t op)
125 {
126     assert(ctx->instr_size && ctx->instr_size >= ctx->instr_cnt);
127
128     if(ctx->instr_size == ctx->instr_cnt) {
129         instr_t *new_instr;
130
131         new_instr = heap_realloc(ctx->code->instrs, ctx->instr_size*2*sizeof(instr_t));
132         if(!new_instr)
133             return -1;
134
135         ctx->code->instrs = new_instr;
136         ctx->instr_size *= 2;
137     }
138
139     ctx->code->instrs[ctx->instr_cnt].op = op;
140     return ctx->instr_cnt++;
141 }
142
143 static HRESULT push_instr_int(compile_ctx_t *ctx, vbsop_t op, LONG arg)
144 {
145     unsigned ret;
146
147     ret = push_instr(ctx, op);
148     if(ret == -1)
149         return E_OUTOFMEMORY;
150
151     instr_ptr(ctx, ret)->arg1.lng = arg;
152     return S_OK;
153 }
154
155 static HRESULT push_instr_addr(compile_ctx_t *ctx, vbsop_t op, unsigned arg)
156 {
157     unsigned ret;
158
159     ret = push_instr(ctx, op);
160     if(ret == -1)
161         return E_OUTOFMEMORY;
162
163     instr_ptr(ctx, ret)->arg1.uint = arg;
164     return S_OK;
165 }
166
167 static HRESULT push_instr_str(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
168 {
169     unsigned instr;
170     WCHAR *str;
171
172     str = compiler_alloc_string(ctx->code, arg);
173     if(!str)
174         return E_OUTOFMEMORY;
175
176     instr = push_instr(ctx, op);
177     if(instr == -1)
178         return E_OUTOFMEMORY;
179
180     instr_ptr(ctx, instr)->arg1.str = str;
181     return S_OK;
182 }
183
184 static HRESULT push_instr_double(compile_ctx_t *ctx, vbsop_t op, double arg)
185 {
186     unsigned instr;
187     double *d;
188
189     d = compiler_alloc(ctx->code, sizeof(double));
190     if(!d)
191         return E_OUTOFMEMORY;
192
193     instr = push_instr(ctx, op);
194     if(instr == -1)
195         return E_OUTOFMEMORY;
196
197     *d = arg;
198     instr_ptr(ctx, instr)->arg1.dbl = d;
199     return S_OK;
200 }
201
202 static BSTR alloc_bstr_arg(compile_ctx_t *ctx, const WCHAR *str)
203 {
204     if(!ctx->code->bstr_pool_size) {
205         ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR));
206         if(!ctx->code->bstr_pool)
207             return NULL;
208         ctx->code->bstr_pool_size = 8;
209     }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) {
210        BSTR *new_pool;
211
212         new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR));
213         if(!new_pool)
214             return NULL;
215
216         ctx->code->bstr_pool = new_pool;
217         ctx->code->bstr_pool_size *= 2;
218     }
219
220     ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str);
221     if(!ctx->code->bstr_pool[ctx->code->bstr_cnt])
222         return NULL;
223
224     return ctx->code->bstr_pool[ctx->code->bstr_cnt++];
225 }
226
227 static HRESULT push_instr_bstr(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg)
228 {
229     unsigned instr;
230     BSTR bstr;
231
232     bstr = alloc_bstr_arg(ctx, arg);
233     if(!bstr)
234         return E_OUTOFMEMORY;
235
236     instr = push_instr(ctx, op);
237     if(instr == -1)
238         return E_OUTOFMEMORY;
239
240     instr_ptr(ctx, instr)->arg1.bstr = bstr;
241     return S_OK;
242 }
243
244 static HRESULT push_instr_bstr_uint(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg1, unsigned arg2)
245 {
246     unsigned instr;
247     BSTR bstr;
248
249     bstr = alloc_bstr_arg(ctx, arg1);
250     if(!bstr)
251         return E_OUTOFMEMORY;
252
253     instr = push_instr(ctx, op);
254     if(instr == -1)
255         return E_OUTOFMEMORY;
256
257     instr_ptr(ctx, instr)->arg1.bstr = bstr;
258     instr_ptr(ctx, instr)->arg2.uint = arg2;
259     return S_OK;
260 }
261
262 #define LABEL_FLAG 0x80000000
263
264 static unsigned alloc_label(compile_ctx_t *ctx)
265 {
266     if(!ctx->labels_size) {
267         ctx->labels = heap_alloc(8 * sizeof(*ctx->labels));
268         if(!ctx->labels)
269             return -1;
270         ctx->labels_size = 8;
271     }else if(ctx->labels_size == ctx->labels_cnt) {
272         unsigned *new_labels;
273
274         new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels));
275         if(!new_labels)
276             return -1;
277
278         ctx->labels = new_labels;
279         ctx->labels_size *= 2;
280     }
281
282     return ctx->labels_cnt++ | LABEL_FLAG;
283 }
284
285 static inline void label_set_addr(compile_ctx_t *ctx, unsigned label)
286 {
287     assert(label & LABEL_FLAG);
288     ctx->labels[label & ~LABEL_FLAG] = ctx->instr_cnt;
289 }
290
291 static HRESULT compile_args(compile_ctx_t *ctx, expression_t *args, unsigned *ret)
292 {
293     unsigned arg_cnt = 0;
294     HRESULT hres;
295
296     while(args) {
297         hres = compile_expression(ctx, args);
298         if(FAILED(hres))
299             return hres;
300
301         arg_cnt++;
302         args = args->next;
303     }
304
305     *ret = arg_cnt;
306     return S_OK;
307 }
308
309 static HRESULT compile_member_expression(compile_ctx_t *ctx, member_expression_t *expr, BOOL ret_val)
310 {
311     unsigned arg_cnt = 0;
312     HRESULT hres;
313
314     hres = compile_args(ctx, expr->args, &arg_cnt);
315     if(FAILED(hres))
316         return hres;
317
318     if(expr->obj_expr) {
319         FIXME("obj_expr not implemented\n");
320         hres = E_NOTIMPL;
321     }else {
322         hres = push_instr_bstr_uint(ctx, ret_val ? OP_icall : OP_icallv, expr->identifier, arg_cnt);
323     }
324
325     return hres;
326 }
327
328 static HRESULT compile_unary_expression(compile_ctx_t *ctx, unary_expression_t *expr, vbsop_t op)
329 {
330     HRESULT hres;
331
332     hres = compile_expression(ctx, expr->subexpr);
333     if(FAILED(hres))
334         return hres;
335
336     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
337 }
338
339 static HRESULT compile_binary_expression(compile_ctx_t *ctx, binary_expression_t *expr, vbsop_t op)
340 {
341     HRESULT hres;
342
343     hres = compile_expression(ctx, expr->left);
344     if(FAILED(hres))
345         return hres;
346
347     hres = compile_expression(ctx, expr->right);
348     if(FAILED(hres))
349         return hres;
350
351     return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK;
352 }
353
354 static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr)
355 {
356     switch(expr->type) {
357     case EXPR_ADD:
358         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add);
359     case EXPR_AND:
360         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and);
361     case EXPR_BOOL:
362         return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value);
363     case EXPR_CONCAT:
364         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat);
365     case EXPR_DIV:
366         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
367     case EXPR_DOUBLE:
368         return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value);
369     case EXPR_EMPTY:
370         return push_instr(ctx, OP_empty) != -1 ? S_OK : E_OUTOFMEMORY;
371     case EXPR_EQUAL:
372         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal);
373     case EXPR_EQV:
374         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eqv);
375     case EXPR_EXP:
376         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp);
377     case EXPR_IDIV:
378         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv);
379     case EXPR_IMP:
380         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_imp);
381     case EXPR_MEMBER:
382         return compile_member_expression(ctx, (member_expression_t*)expr, TRUE);
383     case EXPR_MOD:
384         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
385     case EXPR_MUL:
386         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
387     case EXPR_NEG:
388         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
389     case EXPR_NEQUAL:
390         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal);
391     case EXPR_NOT:
392         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not);
393     case EXPR_NULL:
394         return push_instr(ctx, OP_null) != -1 ? S_OK : E_OUTOFMEMORY;
395     case EXPR_OR:
396         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or);
397     case EXPR_STRING:
398         return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value);
399     case EXPR_SUB:
400         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
401     case EXPR_USHORT:
402         return push_instr_int(ctx, OP_short, ((int_expression_t*)expr)->value);
403     case EXPR_ULONG:
404         return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value);
405     case EXPR_XOR:
406         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor);
407     default:
408         FIXME("Unimplemented expression type %d\n", expr->type);
409         return E_NOTIMPL;
410     }
411
412     return S_OK;
413 }
414
415 static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
416 {
417     unsigned cnd_jmp, endif_label = -1;
418     elseif_decl_t *elseif_decl;
419     HRESULT hres;
420
421     hres = compile_expression(ctx, stat->expr);
422     if(FAILED(hres))
423         return hres;
424
425     cnd_jmp = push_instr(ctx, OP_jmp_false);
426     if(cnd_jmp == -1)
427         return E_OUTOFMEMORY;
428
429     hres = compile_statement(ctx, stat->if_stat);
430     if(FAILED(hres))
431         return hres;
432
433     if(stat->else_stat || stat->elseifs) {
434         endif_label = alloc_label(ctx);
435         if(endif_label == -1)
436             return E_OUTOFMEMORY;
437
438         hres = push_instr_addr(ctx, OP_jmp, endif_label);
439         if(FAILED(hres))
440             return hres;
441     }
442
443     for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) {
444         instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
445
446         hres = compile_expression(ctx, elseif_decl->expr);
447         if(FAILED(hres))
448             return hres;
449
450         cnd_jmp = push_instr(ctx, OP_jmp_false);
451         if(cnd_jmp == -1)
452             return E_OUTOFMEMORY;
453
454         hres = compile_statement(ctx, elseif_decl->stat);
455         if(FAILED(hres))
456             return hres;
457
458         hres = push_instr_addr(ctx, OP_jmp, endif_label);
459         if(FAILED(hres))
460             return hres;
461     }
462
463     instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
464
465     if(stat->else_stat) {
466         hres = compile_statement(ctx, stat->else_stat);
467         if(FAILED(hres))
468             return hres;
469     }
470
471     if(endif_label != -1)
472         label_set_addr(ctx, endif_label);
473     return S_OK;
474 }
475
476 static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat)
477 {
478     HRESULT hres;
479
480     hres = compile_expression(ctx, stat->value_expr);
481     if(FAILED(hres))
482         return hres;
483
484     if(stat->member_expr->args) {
485         FIXME("arguments support not implemented\n");
486         return E_NOTIMPL;
487     }
488
489     if(stat->member_expr->obj_expr) {
490         hres = compile_expression(ctx, stat->member_expr->obj_expr);
491         if(FAILED(hres))
492             return hres;
493
494         hres = push_instr_bstr(ctx, OP_assign_member, stat->member_expr->identifier);
495     }else {
496         hres = push_instr_bstr(ctx, OP_assign_ident, stat->member_expr->identifier);
497     }
498
499     return hres;
500 }
501
502 static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
503 {
504     dim_decl_t *dim_decl;
505
506     for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
507         if(!strcmpiW(dim_decl->name, name))
508             return TRUE;
509     }
510
511     return FALSE;
512 }
513
514 static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
515 {
516     unsigned i;
517
518     for(i = 0; i < ctx->func->arg_cnt; i++) {
519         if(!strcmpiW(ctx->func->args[i].name, name))
520             return TRUE;
521     }
522
523     return FALSE;
524 }
525
526 static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
527 {
528     dim_decl_t *dim_decl = stat->dim_decls;
529
530     while(1) {
531         if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name)) {
532             FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name));
533             return E_FAIL;
534         }
535
536         if(!dim_decl->next)
537             break;
538         dim_decl = dim_decl->next;
539     }
540
541     dim_decl->next = ctx->dim_decls;
542     ctx->dim_decls = stat->dim_decls;
543     ctx->func->var_cnt++;
544     return S_OK;
545 }
546
547 static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat)
548 {
549     if(ctx->func != &ctx->code->global_code) {
550         FIXME("Function is not in the global code\n");
551         return E_FAIL;
552     }
553
554     stat->func_decl->next = ctx->func_decls;
555     ctx->func_decls = stat->func_decl;
556     return S_OK;
557 }
558
559 static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
560 {
561     if(ctx->sub_end_label == -1) {
562         FIXME("Exit Sub outside Sub?\n");
563         return E_FAIL;
564     }
565
566     return push_instr_addr(ctx, OP_jmp, ctx->sub_end_label);
567 }
568
569 static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx)
570 {
571     if(ctx->func_end_label == -1) {
572         FIXME("Exit Function outside Function?\n");
573         return E_FAIL;
574     }
575
576     return push_instr_addr(ctx, OP_jmp, ctx->func_end_label);
577 }
578
579 static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat)
580 {
581     HRESULT hres;
582
583     while(stat) {
584         switch(stat->type) {
585         case STAT_ASSIGN:
586             hres = compile_assign_statement(ctx, (assign_statement_t*)stat);
587             break;
588         case STAT_CALL:
589             hres = compile_member_expression(ctx, ((call_statement_t*)stat)->expr, FALSE);
590             break;
591         case STAT_DIM:
592             hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
593             break;
594         case STAT_EXITFUNC:
595             hres = compile_exitfunc_statement(ctx);
596             break;
597         case STAT_EXITSUB:
598             hres = compile_exitsub_statement(ctx);
599             break;
600         case STAT_FUNC:
601             hres = compile_function_statement(ctx, (function_statement_t*)stat);
602             break;
603         case STAT_IF:
604             hres = compile_if_statement(ctx, (if_statement_t*)stat);
605             break;
606         default:
607             FIXME("Unimplemented statement type %d\n", stat->type);
608             hres = E_NOTIMPL;
609         }
610
611         if(FAILED(hres))
612             return hres;
613         stat = stat->next;
614     }
615
616     return S_OK;
617 }
618
619 static void resolve_labels(compile_ctx_t *ctx, unsigned off)
620 {
621     instr_t *instr;
622
623     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
624         if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
625             assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
626             instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
627         }
628         assert(instr_info[instr->op].arg2_type != ARG_ADDR);
629     }
630
631     ctx->labels_cnt = 0;
632 }
633
634 static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func)
635 {
636     HRESULT hres;
637
638     func->code_off = ctx->instr_cnt;
639
640     ctx->sub_end_label = -1;
641     ctx->func_end_label = -1;
642
643     switch(func->type) {
644     case FUNC_FUNCTION:
645         ctx->func_end_label = alloc_label(ctx);
646         if(ctx->func_end_label == -1)
647             return E_OUTOFMEMORY; /* FIXME ! */
648         break;
649     case FUNC_SUB:
650         ctx->sub_end_label = alloc_label(ctx);
651         if(ctx->sub_end_label == -1)
652             return E_OUTOFMEMORY;
653         break;
654     case FUNC_GLOBAL:
655         break;
656     }
657
658     ctx->func = func;
659     ctx->dim_decls = NULL;
660     hres = compile_statement(ctx, stat);
661     ctx->func = NULL;
662     if(FAILED(hres))
663         return hres;
664
665     if(ctx->sub_end_label != -1)
666         label_set_addr(ctx, ctx->sub_end_label);
667     if(ctx->func_end_label != -1)
668         label_set_addr(ctx, ctx->func_end_label);
669
670     if(push_instr(ctx, OP_ret) == -1)
671         return E_OUTOFMEMORY;
672
673     resolve_labels(ctx, func->code_off);
674
675     if(func->var_cnt) {
676         dim_decl_t *dim_decl;
677
678         if(func->type == FUNC_GLOBAL) {
679             dynamic_var_t *new_var;
680
681             func->var_cnt = 0;
682
683             for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
684                 new_var = compiler_alloc(ctx->code, sizeof(*new_var));
685                 if(!new_var)
686                     return E_OUTOFMEMORY;
687
688                 new_var->name = compiler_alloc_string(ctx->code, dim_decl->name);
689                 if(!new_var->name)
690                     return E_OUTOFMEMORY;
691
692                 V_VT(&new_var->v) = VT_EMPTY;
693
694                 new_var->next = ctx->global_vars;
695                 ctx->global_vars = new_var;
696             }
697         }else {
698             unsigned i;
699
700             func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t));
701             if(!func->vars)
702                 return E_OUTOFMEMORY;
703
704             for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) {
705                 func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name);
706                 if(!func->vars[i].name)
707                     return E_OUTOFMEMORY;
708             }
709
710             assert(i == func->var_cnt);
711         }
712     }
713
714     return S_OK;
715 }
716
717 static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
718 {
719     function_t *iter;
720
721     for(iter = ctx->funcs; iter; iter = iter->next) {
722         if(!strcmpiW(iter->name, name))
723             return TRUE;
724     }
725
726     return FALSE;
727 }
728
729 static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret)
730 {
731     function_t *func;
732     HRESULT hres;
733
734     if(lookup_dim_decls(ctx, decl->name) || lookup_funcs_name(ctx, decl->name)) {
735         FIXME("%s: redefinition\n", debugstr_w(decl->name));
736         return E_FAIL;
737     }
738
739     func = compiler_alloc(ctx->code, sizeof(*func));
740     if(!func)
741         return E_OUTOFMEMORY;
742
743     func->name = compiler_alloc_string(ctx->code, decl->name);
744     if(!func->name)
745         return E_OUTOFMEMORY;
746
747     func->vars = NULL;
748     func->var_cnt = 0;
749     func->code_ctx = ctx->code;
750     func->type = decl->type;
751
752     func->arg_cnt = 0;
753     if(decl->args) {
754         arg_decl_t *arg;
755         unsigned i;
756
757         for(arg = decl->args; arg; arg = arg->next)
758             func->arg_cnt++;
759
760         func->args = compiler_alloc(ctx->code, func->arg_cnt * sizeof(arg_desc_t));
761         if(!func->args)
762             return E_OUTOFMEMORY;
763
764         for(i = 0, arg = decl->args; arg; arg = arg->next, i++) {
765             func->args[i].name = compiler_alloc_string(ctx->code, arg->name);
766             if(!func->args[i].name)
767                 return E_OUTOFMEMORY;
768             func->args[i].by_ref = arg->by_ref;
769         }
770     }else {
771         func->args = NULL;
772     }
773
774     hres = compile_func(ctx, decl->body, func);
775     if(FAILED(hres))
776         return hres;
777
778     *ret = func;
779     return S_OK;
780 }
781
782 static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier)
783 {
784     dynamic_var_t *var;
785     function_t *func;
786
787     for(var = script->global_vars; var; var = var->next) {
788         if(!strcmpiW(var->name, identifier))
789             return TRUE;
790     }
791
792     for(func = script->global_funcs; func; func = func->next) {
793         if(!strcmpiW(func->name, identifier))
794             return TRUE;
795     }
796
797     return FALSE;
798 }
799
800 static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
801 {
802     dynamic_var_t *var;
803     function_t *func;
804
805     for(var = ctx->global_vars; var; var = var->next) {
806         if(lookup_script_identifier(script, var->name)) {
807             FIXME("%s: redefined\n", debugstr_w(var->name));
808             return E_FAIL;
809         }
810     }
811
812     for(func = ctx->funcs; func; func = func->next) {
813         if(lookup_script_identifier(script, func->name)) {
814             FIXME("%s: redefined\n", debugstr_w(func->name));
815             return E_FAIL;
816         }
817     }
818
819     return S_OK;
820 }
821
822 void release_vbscode(vbscode_t *code)
823 {
824     unsigned i;
825
826     list_remove(&code->entry);
827
828     for(i=0; i < code->bstr_cnt; i++)
829         SysFreeString(code->bstr_pool[i]);
830
831     vbsheap_free(&code->heap);
832
833     heap_free(code->bstr_pool);
834     heap_free(code->source);
835     heap_free(code->instrs);
836     heap_free(code);
837 }
838
839 static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source)
840 {
841     vbscode_t *ret;
842
843     ret = heap_alloc(sizeof(*ret));
844     if(!ret)
845         return NULL;
846
847     ret->source = heap_strdupW(source);
848     if(!ret->source) {
849         heap_free(ret);
850         return NULL;
851     }
852
853     ret->instrs = heap_alloc(32*sizeof(instr_t));
854     if(!ret->instrs) {
855         release_vbscode(ret);
856         return NULL;
857     }
858
859     ctx->instr_cnt = 0;
860     ctx->instr_size = 32;
861     vbsheap_init(&ret->heap);
862
863     ret->option_explicit = ctx->parser.option_explicit;
864
865     ret->bstr_pool = NULL;
866     ret->bstr_pool_size = 0;
867     ret->bstr_cnt = 0;
868     ret->global_executed = FALSE;
869
870     ret->global_code.type = FUNC_GLOBAL;
871     ret->global_code.name = NULL;
872     ret->global_code.code_ctx = ret;
873     ret->global_code.vars = NULL;
874     ret->global_code.var_cnt = 0;
875     ret->global_code.arg_cnt = 0;
876     ret->global_code.args = NULL;
877
878     list_init(&ret->entry);
879     return ret;
880 }
881
882 static void release_compiler(compile_ctx_t *ctx)
883 {
884     parser_release(&ctx->parser);
885     heap_free(ctx->labels);
886     if(ctx->code)
887         release_vbscode(ctx->code);
888 }
889
890 HRESULT compile_script(script_ctx_t *script, const WCHAR *src, vbscode_t **ret)
891 {
892     function_t *new_func;
893     function_decl_t *func_decl;
894     compile_ctx_t ctx;
895     vbscode_t *code;
896     HRESULT hres;
897
898     hres = parse_script(&ctx.parser, src);
899     if(FAILED(hres))
900         return hres;
901
902     code = ctx.code = alloc_vbscode(&ctx, src);
903     if(!ctx.code)
904         return E_OUTOFMEMORY;
905
906     ctx.funcs = NULL;
907     ctx.func_decls = NULL;
908     ctx.global_vars = NULL;
909     ctx.dim_decls = NULL;
910     ctx.labels = NULL;
911     ctx.labels_cnt = ctx.labels_size = 0;
912
913     hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->global_code);
914     if(FAILED(hres)) {
915         release_compiler(&ctx);
916         return hres;
917     }
918
919     for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) {
920         hres = create_function(&ctx, func_decl, &new_func);
921         if(FAILED(hres)) {
922             release_compiler(&ctx);
923             return hres;
924         }
925
926         new_func->next = ctx.funcs;
927         ctx.funcs = new_func;
928     }
929
930     hres = check_script_collisions(&ctx, script);
931     if(FAILED(hres)) {
932         release_compiler(&ctx);
933         return hres;
934     }
935
936     if(ctx.global_vars) {
937         dynamic_var_t *var;
938
939         for(var = ctx.global_vars; var->next; var = var->next);
940
941         var->next = script->global_vars;
942         script->global_vars = ctx.global_vars;
943     }
944
945     if(ctx.funcs) {
946         for(new_func = ctx.funcs; new_func->next; new_func = new_func->next);
947
948         new_func->next = script->global_funcs;
949         script->global_funcs = ctx.funcs;
950     }
951
952     if(TRACE_ON(vbscript_disas))
953         dump_code(&ctx);
954
955     ctx.code = NULL;
956     release_compiler(&ctx);
957
958     list_add_tail(&script->code_list, &code->entry);
959     *ret = code;
960     return S_OK;
961 }