vbscript: Added Exit Function statement implementation.
[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_BOOL:
360         return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value);
361     case EXPR_CONCAT:
362         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat);
363     case EXPR_DIV:
364         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div);
365     case EXPR_DOUBLE:
366         return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value);
367     case EXPR_EMPTY:
368         return push_instr(ctx, OP_empty) != -1 ? S_OK : E_OUTOFMEMORY;
369     case EXPR_EQUAL:
370         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal);
371     case EXPR_EXP:
372         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp);
373     case EXPR_IDIV:
374         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv);
375     case EXPR_MEMBER:
376         return compile_member_expression(ctx, (member_expression_t*)expr, TRUE);
377     case EXPR_MOD:
378         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod);
379     case EXPR_MUL:
380         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul);
381     case EXPR_NEG:
382         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg);
383     case EXPR_NEQUAL:
384         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal);
385     case EXPR_NOT:
386         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not);
387     case EXPR_NULL:
388         return push_instr(ctx, OP_null) != -1 ? S_OK : E_OUTOFMEMORY;
389     case EXPR_STRING:
390         return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value);
391     case EXPR_SUB:
392         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
393     case EXPR_USHORT:
394         return push_instr_int(ctx, OP_short, ((int_expression_t*)expr)->value);
395     case EXPR_ULONG:
396         return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value);
397     default:
398         FIXME("Unimplemented expression type %d\n", expr->type);
399         return E_NOTIMPL;
400     }
401
402     return S_OK;
403 }
404
405 static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat)
406 {
407     unsigned cnd_jmp, endif_label = -1;
408     elseif_decl_t *elseif_decl;
409     HRESULT hres;
410
411     hres = compile_expression(ctx, stat->expr);
412     if(FAILED(hres))
413         return hres;
414
415     cnd_jmp = push_instr(ctx, OP_jmp_false);
416     if(cnd_jmp == -1)
417         return E_OUTOFMEMORY;
418
419     hres = compile_statement(ctx, stat->if_stat);
420     if(FAILED(hres))
421         return hres;
422
423     if(stat->else_stat || stat->elseifs) {
424         endif_label = alloc_label(ctx);
425         if(endif_label == -1)
426             return E_OUTOFMEMORY;
427
428         hres = push_instr_addr(ctx, OP_jmp, endif_label);
429         if(FAILED(hres))
430             return hres;
431     }
432
433     for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) {
434         instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
435
436         hres = compile_expression(ctx, elseif_decl->expr);
437         if(FAILED(hres))
438             return hres;
439
440         cnd_jmp = push_instr(ctx, OP_jmp_false);
441         if(cnd_jmp == -1)
442             return E_OUTOFMEMORY;
443
444         hres = compile_statement(ctx, elseif_decl->stat);
445         if(FAILED(hres))
446             return hres;
447
448         hres = push_instr_addr(ctx, OP_jmp, endif_label);
449         if(FAILED(hres))
450             return hres;
451     }
452
453     instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt;
454
455     if(stat->else_stat) {
456         hres = compile_statement(ctx, stat->else_stat);
457         if(FAILED(hres))
458             return hres;
459     }
460
461     if(endif_label != -1)
462         label_set_addr(ctx, endif_label);
463     return S_OK;
464 }
465
466 static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat)
467 {
468     HRESULT hres;
469
470     hres = compile_expression(ctx, stat->value_expr);
471     if(FAILED(hres))
472         return hres;
473
474     if(stat->member_expr->args) {
475         FIXME("arguments support not implemented\n");
476         return E_NOTIMPL;
477     }
478
479     if(stat->member_expr->obj_expr) {
480         hres = compile_expression(ctx, stat->member_expr->obj_expr);
481         if(FAILED(hres))
482             return hres;
483
484         hres = push_instr_bstr(ctx, OP_assign_member, stat->member_expr->identifier);
485     }else {
486         hres = push_instr_bstr(ctx, OP_assign_ident, stat->member_expr->identifier);
487     }
488
489     return hres;
490 }
491
492 static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name)
493 {
494     dim_decl_t *dim_decl;
495
496     for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
497         if(!strcmpiW(dim_decl->name, name))
498             return TRUE;
499     }
500
501     return FALSE;
502 }
503
504 static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name)
505 {
506     unsigned i;
507
508     for(i = 0; i < ctx->func->arg_cnt; i++) {
509         if(!strcmpiW(ctx->func->args[i].name, name))
510             return TRUE;
511     }
512
513     return FALSE;
514 }
515
516 static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat)
517 {
518     dim_decl_t *dim_decl = stat->dim_decls;
519
520     while(1) {
521         if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name)) {
522             FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name));
523             return E_FAIL;
524         }
525
526         if(!dim_decl->next)
527             break;
528         dim_decl = dim_decl->next;
529     }
530
531     dim_decl->next = ctx->dim_decls;
532     ctx->dim_decls = stat->dim_decls;
533     ctx->func->var_cnt++;
534     return S_OK;
535 }
536
537 static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat)
538 {
539     if(ctx->func != &ctx->code->global_code) {
540         FIXME("Function is not in the global code\n");
541         return E_FAIL;
542     }
543
544     stat->func_decl->next = ctx->func_decls;
545     ctx->func_decls = stat->func_decl;
546     return S_OK;
547 }
548
549 static HRESULT compile_exitsub_statement(compile_ctx_t *ctx)
550 {
551     if(ctx->sub_end_label == -1) {
552         FIXME("Exit Sub outside Sub?\n");
553         return E_FAIL;
554     }
555
556     return push_instr_addr(ctx, OP_jmp, ctx->sub_end_label);
557 }
558
559 static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx)
560 {
561     if(ctx->func_end_label == -1) {
562         FIXME("Exit Function outside Function?\n");
563         return E_FAIL;
564     }
565
566     return push_instr_addr(ctx, OP_jmp, ctx->func_end_label);
567 }
568
569 static HRESULT compile_statement(compile_ctx_t *ctx, statement_t *stat)
570 {
571     HRESULT hres;
572
573     while(stat) {
574         switch(stat->type) {
575         case STAT_ASSIGN:
576             hres = compile_assign_statement(ctx, (assign_statement_t*)stat);
577             break;
578         case STAT_CALL:
579             hres = compile_member_expression(ctx, ((call_statement_t*)stat)->expr, FALSE);
580             break;
581         case STAT_DIM:
582             hres = compile_dim_statement(ctx, (dim_statement_t*)stat);
583             break;
584         case STAT_EXITFUNC:
585             hres = compile_exitfunc_statement(ctx);
586             break;
587         case STAT_EXITSUB:
588             hres = compile_exitsub_statement(ctx);
589             break;
590         case STAT_FUNC:
591             hres = compile_function_statement(ctx, (function_statement_t*)stat);
592             break;
593         case STAT_IF:
594             hres = compile_if_statement(ctx, (if_statement_t*)stat);
595             break;
596         default:
597             FIXME("Unimplemented statement type %d\n", stat->type);
598             hres = E_NOTIMPL;
599         }
600
601         if(FAILED(hres))
602             return hres;
603         stat = stat->next;
604     }
605
606     return S_OK;
607 }
608
609 static void resolve_labels(compile_ctx_t *ctx, unsigned off)
610 {
611     instr_t *instr;
612
613     for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) {
614         if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) {
615             assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt);
616             instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG];
617         }
618         assert(instr_info[instr->op].arg2_type != ARG_ADDR);
619     }
620
621     ctx->labels_cnt = 0;
622 }
623
624 static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func)
625 {
626     HRESULT hres;
627
628     func->code_off = ctx->instr_cnt;
629
630     ctx->sub_end_label = -1;
631     ctx->func_end_label = -1;
632
633     switch(func->type) {
634     case FUNC_FUNCTION:
635         ctx->func_end_label = alloc_label(ctx);
636         if(ctx->func_end_label == -1)
637             return E_OUTOFMEMORY; /* FIXME ! */
638         break;
639     case FUNC_SUB:
640         ctx->sub_end_label = alloc_label(ctx);
641         if(ctx->sub_end_label == -1)
642             return E_OUTOFMEMORY;
643         break;
644     case FUNC_GLOBAL:
645         break;
646     }
647
648     ctx->func = func;
649     ctx->dim_decls = NULL;
650     hres = compile_statement(ctx, stat);
651     ctx->func = NULL;
652     if(FAILED(hres))
653         return hres;
654
655     if(ctx->sub_end_label != -1)
656         label_set_addr(ctx, ctx->sub_end_label);
657     if(ctx->func_end_label != -1)
658         label_set_addr(ctx, ctx->func_end_label);
659
660     if(push_instr(ctx, OP_ret) == -1)
661         return E_OUTOFMEMORY;
662
663     resolve_labels(ctx, func->code_off);
664
665     if(func->var_cnt) {
666         dim_decl_t *dim_decl;
667
668         if(func->type == FUNC_GLOBAL) {
669             dynamic_var_t *new_var;
670
671             func->var_cnt = 0;
672
673             for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) {
674                 new_var = compiler_alloc(ctx->code, sizeof(*new_var));
675                 if(!new_var)
676                     return E_OUTOFMEMORY;
677
678                 new_var->name = compiler_alloc_string(ctx->code, dim_decl->name);
679                 if(!new_var->name)
680                     return E_OUTOFMEMORY;
681
682                 V_VT(&new_var->v) = VT_EMPTY;
683
684                 new_var->next = ctx->global_vars;
685                 ctx->global_vars = new_var;
686             }
687         }else {
688             unsigned i;
689
690             func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t));
691             if(!func->vars)
692                 return E_OUTOFMEMORY;
693
694             for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) {
695                 func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name);
696                 if(!func->vars[i].name)
697                     return E_OUTOFMEMORY;
698             }
699
700             assert(i == func->var_cnt);
701         }
702     }
703
704     return S_OK;
705 }
706
707 static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name)
708 {
709     function_t *iter;
710
711     for(iter = ctx->funcs; iter; iter = iter->next) {
712         if(!strcmpiW(iter->name, name))
713             return TRUE;
714     }
715
716     return FALSE;
717 }
718
719 static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret)
720 {
721     function_t *func;
722     HRESULT hres;
723
724     if(lookup_dim_decls(ctx, decl->name) || lookup_funcs_name(ctx, decl->name)) {
725         FIXME("%s: redefinition\n", debugstr_w(decl->name));
726         return E_FAIL;
727     }
728
729     func = compiler_alloc(ctx->code, sizeof(*func));
730     if(!func)
731         return E_OUTOFMEMORY;
732
733     func->name = compiler_alloc_string(ctx->code, decl->name);
734     if(!func->name)
735         return E_OUTOFMEMORY;
736
737     func->vars = NULL;
738     func->var_cnt = 0;
739     func->code_ctx = ctx->code;
740     func->type = decl->type;
741
742     func->arg_cnt = 0;
743     if(decl->args) {
744         arg_decl_t *arg;
745         unsigned i;
746
747         for(arg = decl->args; arg; arg = arg->next)
748             func->arg_cnt++;
749
750         func->args = compiler_alloc(ctx->code, func->arg_cnt * sizeof(arg_desc_t));
751         if(!func->args)
752             return E_OUTOFMEMORY;
753
754         for(i = 0, arg = decl->args; arg; arg = arg->next, i++) {
755             func->args[i].name = compiler_alloc_string(ctx->code, arg->name);
756             if(!func->args[i].name)
757                 return E_OUTOFMEMORY;
758             func->args[i].by_ref = arg->by_ref;
759         }
760     }else {
761         func->args = NULL;
762     }
763
764     hres = compile_func(ctx, decl->body, func);
765     if(FAILED(hres))
766         return hres;
767
768     *ret = func;
769     return S_OK;
770 }
771
772 static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier)
773 {
774     dynamic_var_t *var;
775     function_t *func;
776
777     for(var = script->global_vars; var; var = var->next) {
778         if(!strcmpiW(var->name, identifier))
779             return TRUE;
780     }
781
782     for(func = script->global_funcs; func; func = func->next) {
783         if(!strcmpiW(func->name, identifier))
784             return TRUE;
785     }
786
787     return FALSE;
788 }
789
790 static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script)
791 {
792     dynamic_var_t *var;
793     function_t *func;
794
795     for(var = ctx->global_vars; var; var = var->next) {
796         if(lookup_script_identifier(script, var->name)) {
797             FIXME("%s: redefined\n", debugstr_w(var->name));
798             return E_FAIL;
799         }
800     }
801
802     for(func = ctx->funcs; func; func = func->next) {
803         if(lookup_script_identifier(script, func->name)) {
804             FIXME("%s: redefined\n", debugstr_w(func->name));
805             return E_FAIL;
806         }
807     }
808
809     return S_OK;
810 }
811
812 void release_vbscode(vbscode_t *code)
813 {
814     unsigned i;
815
816     list_remove(&code->entry);
817
818     for(i=0; i < code->bstr_cnt; i++)
819         SysFreeString(code->bstr_pool[i]);
820
821     vbsheap_free(&code->heap);
822
823     heap_free(code->bstr_pool);
824     heap_free(code->source);
825     heap_free(code->instrs);
826     heap_free(code);
827 }
828
829 static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source)
830 {
831     vbscode_t *ret;
832
833     ret = heap_alloc(sizeof(*ret));
834     if(!ret)
835         return NULL;
836
837     ret->source = heap_strdupW(source);
838     if(!ret->source) {
839         heap_free(ret);
840         return NULL;
841     }
842
843     ret->instrs = heap_alloc(32*sizeof(instr_t));
844     if(!ret->instrs) {
845         release_vbscode(ret);
846         return NULL;
847     }
848
849     ctx->instr_cnt = 0;
850     ctx->instr_size = 32;
851     vbsheap_init(&ret->heap);
852
853     ret->option_explicit = ctx->parser.option_explicit;
854
855     ret->bstr_pool = NULL;
856     ret->bstr_pool_size = 0;
857     ret->bstr_cnt = 0;
858     ret->global_executed = FALSE;
859
860     ret->global_code.type = FUNC_GLOBAL;
861     ret->global_code.name = NULL;
862     ret->global_code.code_ctx = ret;
863     ret->global_code.vars = NULL;
864     ret->global_code.var_cnt = 0;
865     ret->global_code.arg_cnt = 0;
866     ret->global_code.args = NULL;
867
868     list_init(&ret->entry);
869     return ret;
870 }
871
872 static void release_compiler(compile_ctx_t *ctx)
873 {
874     parser_release(&ctx->parser);
875     heap_free(ctx->labels);
876     if(ctx->code)
877         release_vbscode(ctx->code);
878 }
879
880 HRESULT compile_script(script_ctx_t *script, const WCHAR *src, vbscode_t **ret)
881 {
882     function_t *new_func;
883     function_decl_t *func_decl;
884     compile_ctx_t ctx;
885     vbscode_t *code;
886     HRESULT hres;
887
888     hres = parse_script(&ctx.parser, src);
889     if(FAILED(hres))
890         return hres;
891
892     code = ctx.code = alloc_vbscode(&ctx, src);
893     if(!ctx.code)
894         return E_OUTOFMEMORY;
895
896     ctx.funcs = NULL;
897     ctx.func_decls = NULL;
898     ctx.global_vars = NULL;
899     ctx.dim_decls = NULL;
900     ctx.labels = NULL;
901     ctx.labels_cnt = ctx.labels_size = 0;
902
903     hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->global_code);
904     if(FAILED(hres)) {
905         release_compiler(&ctx);
906         return hres;
907     }
908
909     for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) {
910         hres = create_function(&ctx, func_decl, &new_func);
911         if(FAILED(hres)) {
912             release_compiler(&ctx);
913             return hres;
914         }
915
916         new_func->next = ctx.funcs;
917         ctx.funcs = new_func;
918     }
919
920     hres = check_script_collisions(&ctx, script);
921     if(FAILED(hres)) {
922         release_compiler(&ctx);
923         return hres;
924     }
925
926     if(ctx.global_vars) {
927         dynamic_var_t *var;
928
929         for(var = ctx.global_vars; var->next; var = var->next);
930
931         var->next = script->global_vars;
932         script->global_vars = ctx.global_vars;
933     }
934
935     if(ctx.funcs) {
936         for(new_func = ctx.funcs; new_func->next; new_func = new_func->next);
937
938         new_func->next = script->global_funcs;
939         script->global_funcs = ctx.funcs;
940     }
941
942     if(TRACE_ON(vbscript_disas))
943         dump_code(&ctx);
944
945     ctx.code = NULL;
946     release_compiler(&ctx);
947
948     list_add_tail(&script->code_list, &code->entry);
949     *ret = code;
950     return S_OK;
951 }