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 _statement_ctx_t { 31 unsigned stack_use; 32 33 unsigned while_end_label; 34 unsigned for_end_label; 35 36 struct _statement_ctx_t *next; 37 } statement_ctx_t; 38 39 typedef struct { 40 parser_ctx_t parser; 41 42 unsigned instr_cnt; 43 unsigned instr_size; 44 vbscode_t *code; 45 46 statement_ctx_t *stat_ctx; 47 48 unsigned *labels; 49 unsigned labels_size; 50 unsigned labels_cnt; 51 52 unsigned sub_end_label; 53 unsigned func_end_label; 54 unsigned prop_end_label; 55 56 dim_decl_t *dim_decls; 57 dim_decl_t *dim_decls_tail; 58 dynamic_var_t *global_vars; 59 60 const_decl_t *const_decls; 61 const_decl_t *global_consts; 62 63 function_t *func; 64 function_t *funcs; 65 function_decl_t *func_decls; 66 67 class_desc_t *classes; 68 } compile_ctx_t; 69 70 static HRESULT compile_expression(compile_ctx_t*,expression_t*); 71 static HRESULT compile_statement(compile_ctx_t*,statement_ctx_t*,statement_t*); 72 73 static const struct { 74 const char *op_str; 75 instr_arg_type_t arg1_type; 76 instr_arg_type_t arg2_type; 77 } instr_info[] = { 78 #define X(n,a,b,c) {#n,b,c}, 79 OP_LIST 80 #undef X 81 }; 82 83 static void dump_instr_arg(instr_arg_type_t type, instr_arg_t *arg) 84 { 85 switch(type) { 86 case ARG_STR: 87 case ARG_BSTR: 88 TRACE_(vbscript_disas)("\t%s", debugstr_w(arg->str)); 89 break; 90 case ARG_INT: 91 TRACE_(vbscript_disas)("\t%d", arg->uint); 92 break; 93 case ARG_UINT: 94 case ARG_ADDR: 95 TRACE_(vbscript_disas)("\t%u", arg->uint); 96 break; 97 case ARG_DOUBLE: 98 TRACE_(vbscript_disas)("\t%lf", *arg->dbl); 99 break; 100 case ARG_NONE: 101 break; 102 DEFAULT_UNREACHABLE; 103 } 104 } 105 106 static void dump_code(compile_ctx_t *ctx) 107 { 108 instr_t *instr; 109 110 for(instr = ctx->code->instrs+1; instr < ctx->code->instrs+ctx->instr_cnt; instr++) { 111 assert(instr->op < OP_LAST); 112 TRACE_(vbscript_disas)("%d:\t%s", (int)(instr-ctx->code->instrs), instr_info[instr->op].op_str); 113 dump_instr_arg(instr_info[instr->op].arg1_type, &instr->arg1); 114 dump_instr_arg(instr_info[instr->op].arg2_type, &instr->arg2); 115 TRACE_(vbscript_disas)("\n"); 116 } 117 } 118 119 static inline void *compiler_alloc(vbscode_t *vbscode, size_t size) 120 { 121 return heap_pool_alloc(&vbscode->heap, size); 122 } 123 124 static inline void *compiler_alloc_zero(vbscode_t *vbscode, size_t size) 125 { 126 void *ret; 127 128 ret = heap_pool_alloc(&vbscode->heap, size); 129 if(ret) 130 memset(ret, 0, size); 131 return ret; 132 } 133 134 static WCHAR *compiler_alloc_string(vbscode_t *vbscode, const WCHAR *str) 135 { 136 size_t size; 137 WCHAR *ret; 138 139 size = (strlenW(str)+1)*sizeof(WCHAR); 140 ret = compiler_alloc(vbscode, size); 141 if(ret) 142 memcpy(ret, str, size); 143 return ret; 144 } 145 146 static inline instr_t *instr_ptr(compile_ctx_t *ctx, unsigned id) 147 { 148 assert(id < ctx->instr_cnt); 149 return ctx->code->instrs + id; 150 } 151 152 static unsigned push_instr(compile_ctx_t *ctx, vbsop_t op) 153 { 154 assert(ctx->instr_size && ctx->instr_size >= ctx->instr_cnt); 155 156 if(ctx->instr_size == ctx->instr_cnt) { 157 instr_t *new_instr; 158 159 new_instr = heap_realloc(ctx->code->instrs, ctx->instr_size*2*sizeof(instr_t)); 160 if(!new_instr) 161 return 0; 162 163 ctx->code->instrs = new_instr; 164 ctx->instr_size *= 2; 165 } 166 167 ctx->code->instrs[ctx->instr_cnt].op = op; 168 return ctx->instr_cnt++; 169 } 170 171 static HRESULT push_instr_int(compile_ctx_t *ctx, vbsop_t op, LONG arg) 172 { 173 unsigned ret; 174 175 ret = push_instr(ctx, op); 176 if(!ret) 177 return E_OUTOFMEMORY; 178 179 instr_ptr(ctx, ret)->arg1.lng = arg; 180 return S_OK; 181 } 182 183 static HRESULT push_instr_uint(compile_ctx_t *ctx, vbsop_t op, unsigned arg) 184 { 185 unsigned ret; 186 187 ret = push_instr(ctx, op); 188 if(!ret) 189 return E_OUTOFMEMORY; 190 191 instr_ptr(ctx, ret)->arg1.uint = arg; 192 return S_OK; 193 } 194 195 static HRESULT push_instr_addr(compile_ctx_t *ctx, vbsop_t op, unsigned arg) 196 { 197 unsigned ret; 198 199 ret = push_instr(ctx, op); 200 if(!ret) 201 return E_OUTOFMEMORY; 202 203 instr_ptr(ctx, ret)->arg1.uint = arg; 204 return S_OK; 205 } 206 207 static HRESULT push_instr_str(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg) 208 { 209 unsigned instr; 210 WCHAR *str; 211 212 str = compiler_alloc_string(ctx->code, arg); 213 if(!str) 214 return E_OUTOFMEMORY; 215 216 instr = push_instr(ctx, op); 217 if(!instr) 218 return E_OUTOFMEMORY; 219 220 instr_ptr(ctx, instr)->arg1.str = str; 221 return S_OK; 222 } 223 224 static HRESULT push_instr_double(compile_ctx_t *ctx, vbsop_t op, double arg) 225 { 226 unsigned instr; 227 double *d; 228 229 d = compiler_alloc(ctx->code, sizeof(double)); 230 if(!d) 231 return E_OUTOFMEMORY; 232 233 instr = push_instr(ctx, op); 234 if(!instr) 235 return E_OUTOFMEMORY; 236 237 *d = arg; 238 instr_ptr(ctx, instr)->arg1.dbl = d; 239 return S_OK; 240 } 241 242 static BSTR alloc_bstr_arg(compile_ctx_t *ctx, const WCHAR *str) 243 { 244 if(!ctx->code->bstr_pool_size) { 245 ctx->code->bstr_pool = heap_alloc(8 * sizeof(BSTR)); 246 if(!ctx->code->bstr_pool) 247 return NULL; 248 ctx->code->bstr_pool_size = 8; 249 }else if(ctx->code->bstr_pool_size == ctx->code->bstr_cnt) { 250 BSTR *new_pool; 251 252 new_pool = heap_realloc(ctx->code->bstr_pool, ctx->code->bstr_pool_size*2*sizeof(BSTR)); 253 if(!new_pool) 254 return NULL; 255 256 ctx->code->bstr_pool = new_pool; 257 ctx->code->bstr_pool_size *= 2; 258 } 259 260 ctx->code->bstr_pool[ctx->code->bstr_cnt] = SysAllocString(str); 261 if(!ctx->code->bstr_pool[ctx->code->bstr_cnt]) 262 return NULL; 263 264 return ctx->code->bstr_pool[ctx->code->bstr_cnt++]; 265 } 266 267 static HRESULT push_instr_bstr(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg) 268 { 269 unsigned instr; 270 BSTR bstr; 271 272 bstr = alloc_bstr_arg(ctx, arg); 273 if(!bstr) 274 return E_OUTOFMEMORY; 275 276 instr = push_instr(ctx, op); 277 if(!instr) 278 return E_OUTOFMEMORY; 279 280 instr_ptr(ctx, instr)->arg1.bstr = bstr; 281 return S_OK; 282 } 283 284 static HRESULT push_instr_bstr_uint(compile_ctx_t *ctx, vbsop_t op, const WCHAR *arg1, unsigned arg2) 285 { 286 unsigned instr; 287 BSTR bstr; 288 289 bstr = alloc_bstr_arg(ctx, arg1); 290 if(!bstr) 291 return E_OUTOFMEMORY; 292 293 instr = push_instr(ctx, op); 294 if(!instr) 295 return E_OUTOFMEMORY; 296 297 instr_ptr(ctx, instr)->arg1.bstr = bstr; 298 instr_ptr(ctx, instr)->arg2.uint = arg2; 299 return S_OK; 300 } 301 302 static HRESULT push_instr_uint_bstr(compile_ctx_t *ctx, vbsop_t op, unsigned arg1, const WCHAR *arg2) 303 { 304 unsigned instr; 305 BSTR bstr; 306 307 bstr = alloc_bstr_arg(ctx, arg2); 308 if(!bstr) 309 return E_OUTOFMEMORY; 310 311 instr = push_instr(ctx, op); 312 if(!instr) 313 return E_OUTOFMEMORY; 314 315 instr_ptr(ctx, instr)->arg1.uint = arg1; 316 instr_ptr(ctx, instr)->arg2.bstr = bstr; 317 return S_OK; 318 } 319 320 #define LABEL_FLAG 0x80000000 321 322 static unsigned alloc_label(compile_ctx_t *ctx) 323 { 324 if(!ctx->labels_size) { 325 ctx->labels = heap_alloc(8 * sizeof(*ctx->labels)); 326 if(!ctx->labels) 327 return 0; 328 ctx->labels_size = 8; 329 }else if(ctx->labels_size == ctx->labels_cnt) { 330 unsigned *new_labels; 331 332 new_labels = heap_realloc(ctx->labels, 2*ctx->labels_size*sizeof(*ctx->labels)); 333 if(!new_labels) 334 return 0; 335 336 ctx->labels = new_labels; 337 ctx->labels_size *= 2; 338 } 339 340 return ctx->labels_cnt++ | LABEL_FLAG; 341 } 342 343 static inline void label_set_addr(compile_ctx_t *ctx, unsigned label) 344 { 345 assert(label & LABEL_FLAG); 346 ctx->labels[label & ~LABEL_FLAG] = ctx->instr_cnt; 347 } 348 349 static inline unsigned stack_offset(compile_ctx_t *ctx) 350 { 351 statement_ctx_t *iter; 352 unsigned ret = 0; 353 354 for(iter = ctx->stat_ctx; iter; iter = iter->next) 355 ret += iter->stack_use; 356 357 return ret; 358 } 359 360 static BOOL emit_catch_jmp(compile_ctx_t *ctx, unsigned stack_off, unsigned code_off) 361 { 362 unsigned code; 363 364 code = push_instr(ctx, OP_catch); 365 if(!code) 366 return FALSE; 367 368 instr_ptr(ctx, code)->arg1.uint = code_off; 369 instr_ptr(ctx, code)->arg2.uint = stack_off + stack_offset(ctx); 370 return TRUE; 371 } 372 373 static inline BOOL emit_catch(compile_ctx_t *ctx, unsigned off) 374 { 375 return emit_catch_jmp(ctx, off, ctx->instr_cnt); 376 } 377 378 static expression_t *lookup_const_decls(compile_ctx_t *ctx, const WCHAR *name, BOOL lookup_global) 379 { 380 const_decl_t *decl; 381 382 for(decl = ctx->const_decls; decl; decl = decl->next) { 383 if(!strcmpiW(decl->name, name)) 384 return decl->value_expr; 385 } 386 387 if(!lookup_global) 388 return NULL; 389 390 for(decl = ctx->global_consts; decl; decl = decl->next) { 391 if(!strcmpiW(decl->name, name)) 392 return decl->value_expr; 393 } 394 395 return NULL; 396 } 397 398 static HRESULT compile_args(compile_ctx_t *ctx, expression_t *args, unsigned *ret) 399 { 400 unsigned arg_cnt = 0; 401 HRESULT hres; 402 403 while(args) { 404 hres = compile_expression(ctx, args); 405 if(FAILED(hres)) 406 return hres; 407 408 arg_cnt++; 409 args = args->next; 410 } 411 412 *ret = arg_cnt; 413 return S_OK; 414 } 415 416 static HRESULT compile_member_expression(compile_ctx_t *ctx, member_expression_t *expr, BOOL ret_val) 417 { 418 unsigned arg_cnt = 0; 419 HRESULT hres; 420 421 if(ret_val && !expr->args) { 422 expression_t *const_expr; 423 424 const_expr = lookup_const_decls(ctx, expr->identifier, TRUE); 425 if(const_expr) 426 return compile_expression(ctx, const_expr); 427 } 428 429 hres = compile_args(ctx, expr->args, &arg_cnt); 430 if(FAILED(hres)) 431 return hres; 432 433 if(expr->obj_expr) { 434 hres = compile_expression(ctx, expr->obj_expr); 435 if(FAILED(hres)) 436 return hres; 437 438 hres = push_instr_bstr_uint(ctx, ret_val ? OP_mcall : OP_mcallv, expr->identifier, arg_cnt); 439 }else { 440 hres = push_instr_bstr_uint(ctx, ret_val ? OP_icall : OP_icallv, expr->identifier, arg_cnt); 441 } 442 443 return hres; 444 } 445 446 static HRESULT compile_unary_expression(compile_ctx_t *ctx, unary_expression_t *expr, vbsop_t op) 447 { 448 HRESULT hres; 449 450 hres = compile_expression(ctx, expr->subexpr); 451 if(FAILED(hres)) 452 return hres; 453 454 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY; 455 } 456 457 static HRESULT compile_binary_expression(compile_ctx_t *ctx, binary_expression_t *expr, vbsop_t op) 458 { 459 HRESULT hres; 460 461 hres = compile_expression(ctx, expr->left); 462 if(FAILED(hres)) 463 return hres; 464 465 hres = compile_expression(ctx, expr->right); 466 if(FAILED(hres)) 467 return hres; 468 469 return push_instr(ctx, op) ? S_OK : E_OUTOFMEMORY; 470 } 471 472 static HRESULT compile_expression(compile_ctx_t *ctx, expression_t *expr) 473 { 474 switch(expr->type) { 475 case EXPR_ADD: 476 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_add); 477 case EXPR_AND: 478 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_and); 479 case EXPR_BOOL: 480 return push_instr_int(ctx, OP_bool, ((bool_expression_t*)expr)->value); 481 case EXPR_BRACKETS: 482 return compile_expression(ctx, ((unary_expression_t*)expr)->subexpr); 483 case EXPR_CONCAT: 484 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_concat); 485 case EXPR_DIV: 486 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_div); 487 case EXPR_DOUBLE: 488 return push_instr_double(ctx, OP_double, ((double_expression_t*)expr)->value); 489 case EXPR_EMPTY: 490 return push_instr(ctx, OP_empty) ? S_OK : E_OUTOFMEMORY; 491 case EXPR_EQUAL: 492 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_equal); 493 case EXPR_EQV: 494 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eqv); 495 case EXPR_EXP: 496 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_exp); 497 case EXPR_GT: 498 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt); 499 case EXPR_GTEQ: 500 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq); 501 case EXPR_IDIV: 502 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_idiv); 503 case EXPR_IS: 504 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_is); 505 case EXPR_IMP: 506 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_imp); 507 case EXPR_LT: 508 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lt); 509 case EXPR_LTEQ: 510 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_lteq); 511 case EXPR_ME: 512 return push_instr(ctx, OP_me) ? S_OK : E_OUTOFMEMORY; 513 case EXPR_MEMBER: 514 return compile_member_expression(ctx, (member_expression_t*)expr, TRUE); 515 case EXPR_MOD: 516 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mod); 517 case EXPR_MUL: 518 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_mul); 519 case EXPR_NEG: 520 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_neg); 521 case EXPR_NEQUAL: 522 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_nequal); 523 case EXPR_NEW: 524 return push_instr_str(ctx, OP_new, ((string_expression_t*)expr)->value); 525 case EXPR_NOARG: 526 return push_instr_int(ctx, OP_hres, DISP_E_PARAMNOTFOUND); 527 case EXPR_NOT: 528 return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_not); 529 case EXPR_NOTHING: 530 return push_instr(ctx, OP_nothing) ? S_OK : E_OUTOFMEMORY; 531 case EXPR_NULL: 532 return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY; 533 case EXPR_OR: 534 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_or); 535 case EXPR_STRING: 536 return push_instr_str(ctx, OP_string, ((string_expression_t*)expr)->value); 537 case EXPR_SUB: 538 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub); 539 case EXPR_USHORT: 540 return push_instr_int(ctx, OP_short, ((int_expression_t*)expr)->value); 541 case EXPR_ULONG: 542 return push_instr_int(ctx, OP_long, ((int_expression_t*)expr)->value); 543 case EXPR_XOR: 544 return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_xor); 545 default: 546 FIXME("Unimplemented expression type %d\n", expr->type); 547 return E_NOTIMPL; 548 } 549 550 return S_OK; 551 } 552 553 static HRESULT compile_if_statement(compile_ctx_t *ctx, if_statement_t *stat) 554 { 555 unsigned cnd_jmp, endif_label = 0; 556 elseif_decl_t *elseif_decl; 557 HRESULT hres; 558 559 hres = compile_expression(ctx, stat->expr); 560 if(FAILED(hres)) 561 return hres; 562 563 cnd_jmp = push_instr(ctx, OP_jmp_false); 564 if(!cnd_jmp) 565 return E_OUTOFMEMORY; 566 567 if(!emit_catch(ctx, 0)) 568 return E_OUTOFMEMORY; 569 570 hres = compile_statement(ctx, NULL, stat->if_stat); 571 if(FAILED(hres)) 572 return hres; 573 574 if(stat->else_stat || stat->elseifs) { 575 endif_label = alloc_label(ctx); 576 if(!endif_label) 577 return E_OUTOFMEMORY; 578 579 hres = push_instr_addr(ctx, OP_jmp, endif_label); 580 if(FAILED(hres)) 581 return hres; 582 } 583 584 for(elseif_decl = stat->elseifs; elseif_decl; elseif_decl = elseif_decl->next) { 585 instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt; 586 587 hres = compile_expression(ctx, elseif_decl->expr); 588 if(FAILED(hres)) 589 return hres; 590 591 cnd_jmp = push_instr(ctx, OP_jmp_false); 592 if(!cnd_jmp) 593 return E_OUTOFMEMORY; 594 595 if(!emit_catch(ctx, 0)) 596 return E_OUTOFMEMORY; 597 598 hres = compile_statement(ctx, NULL, elseif_decl->stat); 599 if(FAILED(hres)) 600 return hres; 601 602 hres = push_instr_addr(ctx, OP_jmp, endif_label); 603 if(FAILED(hres)) 604 return hres; 605 } 606 607 instr_ptr(ctx, cnd_jmp)->arg1.uint = ctx->instr_cnt; 608 609 if(stat->else_stat) { 610 hres = compile_statement(ctx, NULL, stat->else_stat); 611 if(FAILED(hres)) 612 return hres; 613 } 614 615 if(endif_label) 616 label_set_addr(ctx, endif_label); 617 return S_OK; 618 } 619 620 static HRESULT compile_while_statement(compile_ctx_t *ctx, while_statement_t *stat) 621 { 622 statement_ctx_t stat_ctx = {0}, *loop_ctx; 623 unsigned start_addr; 624 unsigned jmp_end; 625 HRESULT hres; 626 627 start_addr = ctx->instr_cnt; 628 629 hres = compile_expression(ctx, stat->expr); 630 if(FAILED(hres)) 631 return hres; 632 633 jmp_end = push_instr(ctx, stat->stat.type == STAT_UNTIL ? OP_jmp_true : OP_jmp_false); 634 if(!jmp_end) 635 return E_OUTOFMEMORY; 636 637 if(!emit_catch(ctx, 0)) 638 return E_OUTOFMEMORY; 639 640 if(stat->stat.type == STAT_WHILE) { 641 loop_ctx = NULL; 642 }else { 643 if(!(stat_ctx.while_end_label = alloc_label(ctx))) 644 return E_OUTOFMEMORY; 645 loop_ctx = &stat_ctx; 646 } 647 648 hres = compile_statement(ctx, loop_ctx, stat->body); 649 if(FAILED(hres)) 650 return hres; 651 652 hres = push_instr_addr(ctx, OP_jmp, start_addr); 653 if(FAILED(hres)) 654 return hres; 655 656 instr_ptr(ctx, jmp_end)->arg1.uint = ctx->instr_cnt; 657 658 if(loop_ctx) 659 label_set_addr(ctx, stat_ctx.while_end_label); 660 661 return S_OK; 662 } 663 664 static HRESULT compile_dowhile_statement(compile_ctx_t *ctx, while_statement_t *stat) 665 { 666 statement_ctx_t loop_ctx = {0}; 667 unsigned start_addr; 668 vbsop_t jmp_op; 669 HRESULT hres; 670 671 start_addr = ctx->instr_cnt; 672 673 if(!(loop_ctx.while_end_label = alloc_label(ctx))) 674 return E_OUTOFMEMORY; 675 676 hres = compile_statement(ctx, &loop_ctx, stat->body); 677 if(FAILED(hres)) 678 return hres; 679 680 if(stat->expr) { 681 hres = compile_expression(ctx, stat->expr); 682 if(FAILED(hres)) 683 return hres; 684 685 jmp_op = stat->stat.type == STAT_DOUNTIL ? OP_jmp_false : OP_jmp_true; 686 }else { 687 jmp_op = OP_jmp; 688 } 689 690 hres = push_instr_addr(ctx, jmp_op, start_addr); 691 if(FAILED(hres)) 692 return hres; 693 694 label_set_addr(ctx, loop_ctx.while_end_label); 695 696 if(!emit_catch(ctx, 0)) 697 return E_OUTOFMEMORY; 698 699 return S_OK; 700 } 701 702 static HRESULT compile_foreach_statement(compile_ctx_t *ctx, foreach_statement_t *stat) 703 { 704 statement_ctx_t loop_ctx = {1}; 705 unsigned loop_start; 706 HRESULT hres; 707 708 /* Preserve a place on the stack in case we throw before having proper enum collection. */ 709 if(!push_instr(ctx, OP_empty)) 710 return E_OUTOFMEMORY; 711 712 hres = compile_expression(ctx, stat->group_expr); 713 if(FAILED(hres)) 714 return hres; 715 716 if(!push_instr(ctx, OP_newenum)) 717 return E_OUTOFMEMORY; 718 719 if(!(loop_ctx.for_end_label = alloc_label(ctx))) 720 return E_OUTOFMEMORY; 721 722 hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier); 723 if(FAILED(hres)) 724 return hres; 725 726 if(!emit_catch(ctx, 1)) 727 return E_OUTOFMEMORY; 728 729 loop_start = ctx->instr_cnt; 730 hres = compile_statement(ctx, &loop_ctx, stat->body); 731 if(FAILED(hres)) 732 return hres; 733 734 /* We need a separated enumnext here, because we need to jump out of the loop on exception. */ 735 hres = push_instr_uint_bstr(ctx, OP_enumnext, loop_ctx.for_end_label, stat->identifier); 736 if(FAILED(hres)) 737 return hres; 738 739 hres = push_instr_addr(ctx, OP_jmp, loop_start); 740 if(FAILED(hres)) 741 return hres; 742 743 label_set_addr(ctx, loop_ctx.for_end_label); 744 return S_OK; 745 } 746 747 static HRESULT compile_forto_statement(compile_ctx_t *ctx, forto_statement_t *stat) 748 { 749 statement_ctx_t loop_ctx = {2}; 750 unsigned step_instr, instr; 751 BSTR identifier; 752 HRESULT hres; 753 754 identifier = alloc_bstr_arg(ctx, stat->identifier); 755 if(!identifier) 756 return E_OUTOFMEMORY; 757 758 hres = compile_expression(ctx, stat->from_expr); 759 if(FAILED(hres)) 760 return hres; 761 762 /* FIXME: Assign should happen after both expressions evaluation. */ 763 instr = push_instr(ctx, OP_assign_ident); 764 if(!instr) 765 return E_OUTOFMEMORY; 766 instr_ptr(ctx, instr)->arg1.bstr = identifier; 767 instr_ptr(ctx, instr)->arg2.uint = 0; 768 769 hres = compile_expression(ctx, stat->to_expr); 770 if(FAILED(hres)) 771 return hres; 772 773 if(!push_instr(ctx, OP_val)) 774 return E_OUTOFMEMORY; 775 776 if(stat->step_expr) { 777 hres = compile_expression(ctx, stat->step_expr); 778 if(FAILED(hres)) 779 return hres; 780 781 if(!push_instr(ctx, OP_val)) 782 return E_OUTOFMEMORY; 783 }else { 784 hres = push_instr_int(ctx, OP_short, 1); 785 if(FAILED(hres)) 786 return hres; 787 } 788 789 loop_ctx.for_end_label = alloc_label(ctx); 790 if(!loop_ctx.for_end_label) 791 return E_OUTOFMEMORY; 792 793 step_instr = push_instr(ctx, OP_step); 794 if(!step_instr) 795 return E_OUTOFMEMORY; 796 instr_ptr(ctx, step_instr)->arg2.bstr = identifier; 797 instr_ptr(ctx, step_instr)->arg1.uint = loop_ctx.for_end_label; 798 799 if(!emit_catch(ctx, 2)) 800 return E_OUTOFMEMORY; 801 802 hres = compile_statement(ctx, &loop_ctx, stat->body); 803 if(FAILED(hres)) 804 return hres; 805 806 /* FIXME: Error handling can't be done compatible with native using OP_incc here. */ 807 instr = push_instr(ctx, OP_incc); 808 if(!instr) 809 return E_OUTOFMEMORY; 810 instr_ptr(ctx, instr)->arg1.bstr = identifier; 811 812 hres = push_instr_addr(ctx, OP_jmp, step_instr); 813 if(FAILED(hres)) 814 return hres; 815 816 hres = push_instr_uint(ctx, OP_pop, 2); 817 if(FAILED(hres)) 818 return hres; 819 820 label_set_addr(ctx, loop_ctx.for_end_label); 821 822 /* FIXME: reconsider after OP_incc fixup. */ 823 if(!emit_catch(ctx, 0)) 824 return E_OUTOFMEMORY; 825 826 return S_OK; 827 } 828 829 static HRESULT compile_select_statement(compile_ctx_t *ctx, select_statement_t *stat) 830 { 831 unsigned end_label, case_cnt = 0, *case_labels = NULL, i; 832 case_clausule_t *case_iter; 833 expression_t *expr_iter; 834 HRESULT hres; 835 836 hres = compile_expression(ctx, stat->expr); 837 if(FAILED(hres)) 838 return hres; 839 840 if(!push_instr(ctx, OP_val)) 841 return E_OUTOFMEMORY; 842 843 end_label = alloc_label(ctx); 844 if(!end_label) 845 return E_OUTOFMEMORY; 846 847 if(!emit_catch_jmp(ctx, 0, end_label)) 848 return E_OUTOFMEMORY; 849 850 for(case_iter = stat->case_clausules; case_iter; case_iter = case_iter->next) 851 case_cnt++; 852 853 if(case_cnt) { 854 case_labels = heap_alloc(case_cnt*sizeof(*case_labels)); 855 if(!case_labels) 856 return E_OUTOFMEMORY; 857 } 858 859 for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) { 860 case_labels[i] = alloc_label(ctx); 861 if(!case_labels[i]) { 862 hres = E_OUTOFMEMORY; 863 break; 864 } 865 866 if(!case_iter->expr) 867 break; 868 869 for(expr_iter = case_iter->expr; expr_iter; expr_iter = expr_iter->next) { 870 hres = compile_expression(ctx, expr_iter); 871 if(FAILED(hres)) 872 break; 873 874 hres = push_instr_addr(ctx, OP_case, case_labels[i]); 875 if(FAILED(hres)) 876 break; 877 878 if(!emit_catch_jmp(ctx, 0, case_labels[i])) { 879 hres = E_OUTOFMEMORY; 880 break; 881 } 882 } 883 } 884 885 if(FAILED(hres)) { 886 heap_free(case_labels); 887 return hres; 888 } 889 890 hres = push_instr_uint(ctx, OP_pop, 1); 891 if(FAILED(hres)) { 892 heap_free(case_labels); 893 return hres; 894 } 895 896 hres = push_instr_addr(ctx, OP_jmp, case_iter ? case_labels[i] : end_label); 897 if(FAILED(hres)) { 898 heap_free(case_labels); 899 return hres; 900 } 901 902 for(case_iter = stat->case_clausules, i=0; case_iter; case_iter = case_iter->next, i++) { 903 label_set_addr(ctx, case_labels[i]); 904 hres = compile_statement(ctx, NULL, case_iter->stat); 905 if(FAILED(hres)) 906 break; 907 908 if(!case_iter->next) 909 break; 910 911 hres = push_instr_addr(ctx, OP_jmp, end_label); 912 if(FAILED(hres)) 913 break; 914 } 915 916 heap_free(case_labels); 917 if(FAILED(hres)) 918 return hres; 919 920 label_set_addr(ctx, end_label); 921 return S_OK; 922 } 923 924 static HRESULT compile_assignment(compile_ctx_t *ctx, member_expression_t *member_expr, expression_t *value_expr, BOOL is_set) 925 { 926 unsigned args_cnt; 927 vbsop_t op; 928 HRESULT hres; 929 930 if(member_expr->obj_expr) { 931 hres = compile_expression(ctx, member_expr->obj_expr); 932 if(FAILED(hres)) 933 return hres; 934 935 op = is_set ? OP_set_member : OP_assign_member; 936 }else { 937 op = is_set ? OP_set_ident : OP_assign_ident; 938 } 939 940 hres = compile_expression(ctx, value_expr); 941 if(FAILED(hres)) 942 return hres; 943 944 hres = compile_args(ctx, member_expr->args, &args_cnt); 945 if(FAILED(hres)) 946 return hres; 947 948 hres = push_instr_bstr_uint(ctx, op, member_expr->identifier, args_cnt); 949 if(FAILED(hres)) 950 return hres; 951 952 if(!emit_catch(ctx, 0)) 953 return E_OUTOFMEMORY; 954 955 return S_OK; 956 } 957 958 static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *stat, BOOL is_set) 959 { 960 return compile_assignment(ctx, stat->member_expr, stat->value_expr, is_set); 961 } 962 963 static HRESULT compile_call_statement(compile_ctx_t *ctx, call_statement_t *stat) 964 { 965 HRESULT hres; 966 967 /* It's challenging for parser to distinguish parameterized assignment with one argument from call 968 * with equality expression argument, so we do it in compiler. */ 969 if(!stat->is_strict && stat->expr->args && !stat->expr->args->next && stat->expr->args->type == EXPR_EQUAL) { 970 binary_expression_t *eqexpr = (binary_expression_t*)stat->expr->args; 971 972 if(eqexpr->left->type == EXPR_BRACKETS) { 973 member_expression_t new_member = *stat->expr; 974 975 WARN("converting call expr to assign expr\n"); 976 977 new_member.args = ((unary_expression_t*)eqexpr->left)->subexpr; 978 return compile_assignment(ctx, &new_member, eqexpr->right, FALSE); 979 } 980 } 981 982 hres = compile_member_expression(ctx, stat->expr, FALSE); 983 if(FAILED(hres)) 984 return hres; 985 986 if(!emit_catch(ctx, 0)) 987 return E_OUTOFMEMORY; 988 989 return S_OK; 990 } 991 992 static BOOL lookup_dim_decls(compile_ctx_t *ctx, const WCHAR *name) 993 { 994 dim_decl_t *dim_decl; 995 996 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) { 997 if(!strcmpiW(dim_decl->name, name)) 998 return TRUE; 999 } 1000 1001 return FALSE; 1002 } 1003 1004 static BOOL lookup_args_name(compile_ctx_t *ctx, const WCHAR *name) 1005 { 1006 unsigned i; 1007 1008 for(i = 0; i < ctx->func->arg_cnt; i++) { 1009 if(!strcmpiW(ctx->func->args[i].name, name)) 1010 return TRUE; 1011 } 1012 1013 return FALSE; 1014 } 1015 1016 static HRESULT compile_dim_statement(compile_ctx_t *ctx, dim_statement_t *stat) 1017 { 1018 dim_decl_t *dim_decl = stat->dim_decls; 1019 1020 while(1) { 1021 if(lookup_dim_decls(ctx, dim_decl->name) || lookup_args_name(ctx, dim_decl->name) 1022 || lookup_const_decls(ctx, dim_decl->name, FALSE)) { 1023 FIXME("dim %s name redefined\n", debugstr_w(dim_decl->name)); 1024 return E_FAIL; 1025 } 1026 1027 ctx->func->var_cnt++; 1028 1029 if(dim_decl->is_array) { 1030 HRESULT hres = push_instr_bstr_uint(ctx, OP_dim, dim_decl->name, ctx->func->array_cnt++); 1031 if(FAILED(hres)) 1032 return hres; 1033 1034 if(!emit_catch(ctx, 0)) 1035 return E_OUTOFMEMORY; 1036 } 1037 1038 if(!dim_decl->next) 1039 break; 1040 dim_decl = dim_decl->next; 1041 } 1042 1043 if(ctx->dim_decls_tail) 1044 ctx->dim_decls_tail->next = stat->dim_decls; 1045 else 1046 ctx->dim_decls = stat->dim_decls; 1047 ctx->dim_decls_tail = dim_decl; 1048 return S_OK; 1049 } 1050 1051 static HRESULT compile_const_statement(compile_ctx_t *ctx, const_statement_t *stat) 1052 { 1053 const_decl_t *decl, *next_decl = stat->decls; 1054 1055 do { 1056 decl = next_decl; 1057 1058 if(lookup_const_decls(ctx, decl->name, FALSE) || lookup_args_name(ctx, decl->name) 1059 || lookup_dim_decls(ctx, decl->name)) { 1060 FIXME("%s redefined\n", debugstr_w(decl->name)); 1061 return E_FAIL; 1062 } 1063 1064 if(ctx->func->type == FUNC_GLOBAL) { 1065 HRESULT hres; 1066 1067 hres = compile_expression(ctx, decl->value_expr); 1068 if(FAILED(hres)) 1069 return hres; 1070 1071 hres = push_instr_bstr(ctx, OP_const, decl->name); 1072 if(FAILED(hres)) 1073 return hres; 1074 1075 if(!emit_catch(ctx, 0)) 1076 return E_OUTOFMEMORY; 1077 } 1078 1079 next_decl = decl->next; 1080 decl->next = ctx->const_decls; 1081 ctx->const_decls = decl; 1082 } while(next_decl); 1083 1084 return S_OK; 1085 } 1086 1087 static HRESULT compile_function_statement(compile_ctx_t *ctx, function_statement_t *stat) 1088 { 1089 if(ctx->func != &ctx->code->main_code) { 1090 FIXME("Function is not in the global code\n"); 1091 return E_FAIL; 1092 } 1093 1094 stat->func_decl->next = ctx->func_decls; 1095 ctx->func_decls = stat->func_decl; 1096 return S_OK; 1097 } 1098 1099 static HRESULT compile_exitdo_statement(compile_ctx_t *ctx) 1100 { 1101 statement_ctx_t *iter; 1102 unsigned pop_cnt = 0; 1103 1104 for(iter = ctx->stat_ctx; iter; iter = iter->next) { 1105 pop_cnt += iter->stack_use; 1106 if(iter->while_end_label) 1107 break; 1108 } 1109 if(!iter) { 1110 FIXME("Exit Do outside Do Loop\n"); 1111 return E_FAIL; 1112 } 1113 1114 if(pop_cnt) { 1115 HRESULT hres; 1116 1117 hres = push_instr_uint(ctx, OP_pop, pop_cnt); 1118 if(FAILED(hres)) 1119 return hres; 1120 } 1121 1122 return push_instr_addr(ctx, OP_jmp, iter->while_end_label); 1123 } 1124 1125 static HRESULT compile_exitfor_statement(compile_ctx_t *ctx) 1126 { 1127 statement_ctx_t *iter; 1128 unsigned pop_cnt = 0; 1129 1130 for(iter = ctx->stat_ctx; iter; iter = iter->next) { 1131 pop_cnt += iter->stack_use; 1132 if(iter->for_end_label) 1133 break; 1134 } 1135 if(!iter) { 1136 FIXME("Exit For outside For loop\n"); 1137 return E_FAIL; 1138 } 1139 1140 if(pop_cnt) { 1141 HRESULT hres; 1142 1143 hres = push_instr_uint(ctx, OP_pop, pop_cnt); 1144 if(FAILED(hres)) 1145 return hres; 1146 } 1147 1148 return push_instr_addr(ctx, OP_jmp, iter->for_end_label); 1149 } 1150 1151 static HRESULT exit_label(compile_ctx_t *ctx, unsigned jmp_label) 1152 { 1153 unsigned pop_cnt = stack_offset(ctx); 1154 1155 if(pop_cnt) { 1156 HRESULT hres; 1157 1158 hres = push_instr_uint(ctx, OP_pop, pop_cnt); 1159 if(FAILED(hres)) 1160 return hres; 1161 } 1162 1163 return push_instr_addr(ctx, OP_jmp, jmp_label); 1164 } 1165 1166 static HRESULT compile_exitsub_statement(compile_ctx_t *ctx) 1167 { 1168 if(!ctx->sub_end_label) { 1169 FIXME("Exit Sub outside Sub?\n"); 1170 return E_FAIL; 1171 } 1172 1173 return exit_label(ctx, ctx->sub_end_label); 1174 } 1175 1176 static HRESULT compile_exitfunc_statement(compile_ctx_t *ctx) 1177 { 1178 if(!ctx->func_end_label) { 1179 FIXME("Exit Function outside Function?\n"); 1180 return E_FAIL; 1181 } 1182 1183 return exit_label(ctx, ctx->func_end_label); 1184 } 1185 1186 static HRESULT compile_exitprop_statement(compile_ctx_t *ctx) 1187 { 1188 if(!ctx->prop_end_label) { 1189 FIXME("Exit Property outside Property?\n"); 1190 return E_FAIL; 1191 } 1192 1193 return exit_label(ctx, ctx->prop_end_label); 1194 } 1195 1196 static HRESULT compile_onerror_statement(compile_ctx_t *ctx, onerror_statement_t *stat) 1197 { 1198 return push_instr_int(ctx, OP_errmode, stat->resume_next); 1199 } 1200 1201 static HRESULT compile_statement(compile_ctx_t *ctx, statement_ctx_t *stat_ctx, statement_t *stat) 1202 { 1203 HRESULT hres; 1204 1205 if(stat_ctx) { 1206 stat_ctx->next = ctx->stat_ctx; 1207 ctx->stat_ctx = stat_ctx; 1208 } 1209 1210 while(stat) { 1211 switch(stat->type) { 1212 case STAT_ASSIGN: 1213 hres = compile_assign_statement(ctx, (assign_statement_t*)stat, FALSE); 1214 break; 1215 case STAT_CALL: 1216 hres = compile_call_statement(ctx, (call_statement_t*)stat); 1217 break; 1218 case STAT_CONST: 1219 hres = compile_const_statement(ctx, (const_statement_t*)stat); 1220 break; 1221 case STAT_DIM: 1222 hres = compile_dim_statement(ctx, (dim_statement_t*)stat); 1223 break; 1224 case STAT_DOWHILE: 1225 case STAT_DOUNTIL: 1226 hres = compile_dowhile_statement(ctx, (while_statement_t*)stat); 1227 break; 1228 case STAT_EXITDO: 1229 hres = compile_exitdo_statement(ctx); 1230 break; 1231 case STAT_EXITFOR: 1232 hres = compile_exitfor_statement(ctx); 1233 break; 1234 case STAT_EXITFUNC: 1235 hres = compile_exitfunc_statement(ctx); 1236 break; 1237 case STAT_EXITPROP: 1238 hres = compile_exitprop_statement(ctx); 1239 break; 1240 case STAT_EXITSUB: 1241 hres = compile_exitsub_statement(ctx); 1242 break; 1243 case STAT_FOREACH: 1244 hres = compile_foreach_statement(ctx, (foreach_statement_t*)stat); 1245 break; 1246 case STAT_FORTO: 1247 hres = compile_forto_statement(ctx, (forto_statement_t*)stat); 1248 break; 1249 case STAT_FUNC: 1250 hres = compile_function_statement(ctx, (function_statement_t*)stat); 1251 break; 1252 case STAT_IF: 1253 hres = compile_if_statement(ctx, (if_statement_t*)stat); 1254 break; 1255 case STAT_ONERROR: 1256 hres = compile_onerror_statement(ctx, (onerror_statement_t*)stat); 1257 break; 1258 case STAT_SELECT: 1259 hres = compile_select_statement(ctx, (select_statement_t*)stat); 1260 break; 1261 case STAT_SET: 1262 hres = compile_assign_statement(ctx, (assign_statement_t*)stat, TRUE); 1263 break; 1264 case STAT_STOP: 1265 hres = push_instr(ctx, OP_stop) ? S_OK : E_OUTOFMEMORY; 1266 break; 1267 case STAT_UNTIL: 1268 case STAT_WHILE: 1269 case STAT_WHILELOOP: 1270 hres = compile_while_statement(ctx, (while_statement_t*)stat); 1271 break; 1272 default: 1273 FIXME("Unimplemented statement type %d\n", stat->type); 1274 hres = E_NOTIMPL; 1275 } 1276 1277 if(FAILED(hres)) 1278 return hres; 1279 stat = stat->next; 1280 } 1281 1282 if(stat_ctx) { 1283 assert(ctx->stat_ctx == stat_ctx); 1284 ctx->stat_ctx = stat_ctx->next; 1285 } 1286 1287 return S_OK; 1288 } 1289 1290 static void resolve_labels(compile_ctx_t *ctx, unsigned off) 1291 { 1292 instr_t *instr; 1293 1294 for(instr = ctx->code->instrs+off; instr < ctx->code->instrs+ctx->instr_cnt; instr++) { 1295 if(instr_info[instr->op].arg1_type == ARG_ADDR && (instr->arg1.uint & LABEL_FLAG)) { 1296 assert((instr->arg1.uint & ~LABEL_FLAG) < ctx->labels_cnt); 1297 instr->arg1.uint = ctx->labels[instr->arg1.uint & ~LABEL_FLAG]; 1298 } 1299 assert(instr_info[instr->op].arg2_type != ARG_ADDR); 1300 } 1301 1302 ctx->labels_cnt = 0; 1303 } 1304 1305 static HRESULT fill_array_desc(compile_ctx_t *ctx, dim_decl_t *dim_decl, array_desc_t *array_desc) 1306 { 1307 unsigned dim_cnt = 0, i; 1308 dim_list_t *iter; 1309 1310 for(iter = dim_decl->dims; iter; iter = iter->next) 1311 dim_cnt++; 1312 1313 array_desc->bounds = compiler_alloc(ctx->code, dim_cnt * sizeof(SAFEARRAYBOUND)); 1314 if(!array_desc->bounds) 1315 return E_OUTOFMEMORY; 1316 1317 array_desc->dim_cnt = dim_cnt; 1318 1319 for(iter = dim_decl->dims, i=0; iter; iter = iter->next, i++) { 1320 array_desc->bounds[i].cElements = iter->val+1; 1321 array_desc->bounds[i].lLbound = 0; 1322 } 1323 1324 return S_OK; 1325 } 1326 1327 static HRESULT compile_func(compile_ctx_t *ctx, statement_t *stat, function_t *func) 1328 { 1329 HRESULT hres; 1330 1331 func->code_off = ctx->instr_cnt; 1332 1333 ctx->sub_end_label = 0; 1334 ctx->func_end_label = 0; 1335 ctx->prop_end_label = 0; 1336 1337 switch(func->type) { 1338 case FUNC_FUNCTION: 1339 ctx->func_end_label = alloc_label(ctx); 1340 if(!ctx->func_end_label) 1341 return E_OUTOFMEMORY; 1342 break; 1343 case FUNC_SUB: 1344 ctx->sub_end_label = alloc_label(ctx); 1345 if(!ctx->sub_end_label) 1346 return E_OUTOFMEMORY; 1347 break; 1348 case FUNC_PROPGET: 1349 case FUNC_PROPLET: 1350 case FUNC_PROPSET: 1351 case FUNC_DEFGET: 1352 ctx->prop_end_label = alloc_label(ctx); 1353 if(!ctx->prop_end_label) 1354 return E_OUTOFMEMORY; 1355 break; 1356 case FUNC_GLOBAL: 1357 break; 1358 } 1359 1360 ctx->func = func; 1361 ctx->dim_decls = ctx->dim_decls_tail = NULL; 1362 ctx->const_decls = NULL; 1363 hres = compile_statement(ctx, NULL, stat); 1364 ctx->func = NULL; 1365 if(FAILED(hres)) 1366 return hres; 1367 1368 if(ctx->sub_end_label) 1369 label_set_addr(ctx, ctx->sub_end_label); 1370 if(ctx->func_end_label) 1371 label_set_addr(ctx, ctx->func_end_label); 1372 if(ctx->prop_end_label) 1373 label_set_addr(ctx, ctx->prop_end_label); 1374 1375 if(!push_instr(ctx, OP_ret)) 1376 return E_OUTOFMEMORY; 1377 1378 resolve_labels(ctx, func->code_off); 1379 1380 if(func->var_cnt) { 1381 dim_decl_t *dim_decl; 1382 1383 if(func->type == FUNC_GLOBAL) { 1384 dynamic_var_t *new_var; 1385 1386 func->var_cnt = 0; 1387 1388 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) { 1389 new_var = compiler_alloc(ctx->code, sizeof(*new_var)); 1390 if(!new_var) 1391 return E_OUTOFMEMORY; 1392 1393 new_var->name = compiler_alloc_string(ctx->code, dim_decl->name); 1394 if(!new_var->name) 1395 return E_OUTOFMEMORY; 1396 1397 V_VT(&new_var->v) = VT_EMPTY; 1398 new_var->is_const = FALSE; 1399 1400 new_var->next = ctx->global_vars; 1401 ctx->global_vars = new_var; 1402 } 1403 }else { 1404 unsigned i; 1405 1406 func->vars = compiler_alloc(ctx->code, func->var_cnt * sizeof(var_desc_t)); 1407 if(!func->vars) 1408 return E_OUTOFMEMORY; 1409 1410 for(dim_decl = ctx->dim_decls, i=0; dim_decl; dim_decl = dim_decl->next, i++) { 1411 func->vars[i].name = compiler_alloc_string(ctx->code, dim_decl->name); 1412 if(!func->vars[i].name) 1413 return E_OUTOFMEMORY; 1414 } 1415 1416 assert(i == func->var_cnt); 1417 } 1418 } 1419 1420 if(func->array_cnt) { 1421 unsigned array_id = 0; 1422 dim_decl_t *dim_decl; 1423 1424 func->array_descs = compiler_alloc(ctx->code, func->array_cnt * sizeof(array_desc_t)); 1425 if(!func->array_descs) 1426 return E_OUTOFMEMORY; 1427 1428 for(dim_decl = ctx->dim_decls; dim_decl; dim_decl = dim_decl->next) { 1429 if(dim_decl->is_array) { 1430 hres = fill_array_desc(ctx, dim_decl, func->array_descs + array_id++); 1431 if(FAILED(hres)) 1432 return hres; 1433 } 1434 } 1435 1436 assert(array_id == func->array_cnt); 1437 } 1438 1439 return S_OK; 1440 } 1441 1442 static BOOL lookup_funcs_name(compile_ctx_t *ctx, const WCHAR *name) 1443 { 1444 function_t *iter; 1445 1446 for(iter = ctx->funcs; iter; iter = iter->next) { 1447 if(!strcmpiW(iter->name, name)) 1448 return TRUE; 1449 } 1450 1451 return FALSE; 1452 } 1453 1454 static HRESULT create_function(compile_ctx_t *ctx, function_decl_t *decl, function_t **ret) 1455 { 1456 function_t *func; 1457 HRESULT hres; 1458 1459 if(lookup_dim_decls(ctx, decl->name) || lookup_funcs_name(ctx, decl->name) || lookup_const_decls(ctx, decl->name, FALSE)) { 1460 FIXME("%s: redefinition\n", debugstr_w(decl->name)); 1461 return E_FAIL; 1462 } 1463 1464 func = compiler_alloc(ctx->code, sizeof(*func)); 1465 if(!func) 1466 return E_OUTOFMEMORY; 1467 1468 func->name = compiler_alloc_string(ctx->code, decl->name); 1469 if(!func->name) 1470 return E_OUTOFMEMORY; 1471 1472 func->vars = NULL; 1473 func->var_cnt = 0; 1474 func->array_cnt = 0; 1475 func->code_ctx = ctx->code; 1476 func->type = decl->type; 1477 func->is_public = decl->is_public; 1478 1479 func->arg_cnt = 0; 1480 if(decl->args) { 1481 arg_decl_t *arg; 1482 unsigned i; 1483 1484 for(arg = decl->args; arg; arg = arg->next) 1485 func->arg_cnt++; 1486 1487 func->args = compiler_alloc(ctx->code, func->arg_cnt * sizeof(arg_desc_t)); 1488 if(!func->args) 1489 return E_OUTOFMEMORY; 1490 1491 for(i = 0, arg = decl->args; arg; arg = arg->next, i++) { 1492 func->args[i].name = compiler_alloc_string(ctx->code, arg->name); 1493 if(!func->args[i].name) 1494 return E_OUTOFMEMORY; 1495 func->args[i].by_ref = arg->by_ref; 1496 } 1497 }else { 1498 func->args = NULL; 1499 } 1500 1501 hres = compile_func(ctx, decl->body, func); 1502 if(FAILED(hres)) 1503 return hres; 1504 1505 *ret = func; 1506 return S_OK; 1507 } 1508 1509 static BOOL lookup_class_name(compile_ctx_t *ctx, const WCHAR *name) 1510 { 1511 class_desc_t *iter; 1512 1513 for(iter = ctx->classes; iter; iter = iter->next) { 1514 if(!strcmpiW(iter->name, name)) 1515 return TRUE; 1516 } 1517 1518 return FALSE; 1519 } 1520 1521 static HRESULT create_class_funcprop(compile_ctx_t *ctx, function_decl_t *func_decl, vbdisp_funcprop_desc_t *desc) 1522 { 1523 vbdisp_invoke_type_t invoke_type; 1524 function_decl_t *funcprop_decl; 1525 HRESULT hres; 1526 1527 desc->name = compiler_alloc_string(ctx->code, func_decl->name); 1528 if(!desc->name) 1529 return E_OUTOFMEMORY; 1530 1531 for(funcprop_decl = func_decl; funcprop_decl; funcprop_decl = funcprop_decl->next_prop_func) { 1532 switch(funcprop_decl->type) { 1533 case FUNC_FUNCTION: 1534 case FUNC_SUB: 1535 case FUNC_PROPGET: 1536 case FUNC_DEFGET: 1537 invoke_type = VBDISP_CALLGET; 1538 break; 1539 case FUNC_PROPLET: 1540 invoke_type = VBDISP_LET; 1541 break; 1542 case FUNC_PROPSET: 1543 invoke_type = VBDISP_SET; 1544 break; 1545 DEFAULT_UNREACHABLE; 1546 } 1547 1548 assert(!desc->entries[invoke_type]); 1549 1550 if(funcprop_decl->is_public) 1551 desc->is_public = TRUE; 1552 1553 hres = create_function(ctx, funcprop_decl, desc->entries+invoke_type); 1554 if(FAILED(hres)) 1555 return hres; 1556 } 1557 1558 return S_OK; 1559 } 1560 1561 static BOOL lookup_class_funcs(class_desc_t *class_desc, const WCHAR *name) 1562 { 1563 unsigned i; 1564 1565 for(i=0; i < class_desc->func_cnt; i++) { 1566 if(class_desc->funcs[i].name && !strcmpiW(class_desc->funcs[i].name, name)) 1567 return TRUE; 1568 } 1569 1570 return FALSE; 1571 } 1572 1573 static HRESULT compile_class(compile_ctx_t *ctx, class_decl_t *class_decl) 1574 { 1575 function_decl_t *func_decl, *func_prop_decl; 1576 class_desc_t *class_desc; 1577 dim_decl_t *prop_decl; 1578 unsigned i; 1579 HRESULT hres; 1580 1581 static const WCHAR class_initializeW[] = {'c','l','a','s','s','_','i','n','i','t','i','a','l','i','z','e',0}; 1582 static const WCHAR class_terminateW[] = {'c','l','a','s','s','_','t','e','r','m','i','n','a','t','e',0}; 1583 1584 if(lookup_dim_decls(ctx, class_decl->name) || lookup_funcs_name(ctx, class_decl->name) 1585 || lookup_const_decls(ctx, class_decl->name, FALSE) || lookup_class_name(ctx, class_decl->name)) { 1586 FIXME("%s: redefinition\n", debugstr_w(class_decl->name)); 1587 return E_FAIL; 1588 } 1589 1590 class_desc = compiler_alloc_zero(ctx->code, sizeof(*class_desc)); 1591 if(!class_desc) 1592 return E_OUTOFMEMORY; 1593 1594 class_desc->name = compiler_alloc_string(ctx->code, class_decl->name); 1595 if(!class_desc->name) 1596 return E_OUTOFMEMORY; 1597 1598 class_desc->func_cnt = 1; /* always allocate slot for default getter */ 1599 1600 for(func_decl = class_decl->funcs; func_decl; func_decl = func_decl->next) { 1601 for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) { 1602 if(func_prop_decl->type == FUNC_DEFGET) 1603 break; 1604 } 1605 if(!func_prop_decl) 1606 class_desc->func_cnt++; 1607 } 1608 1609 class_desc->funcs = compiler_alloc(ctx->code, class_desc->func_cnt*sizeof(*class_desc->funcs)); 1610 if(!class_desc->funcs) 1611 return E_OUTOFMEMORY; 1612 memset(class_desc->funcs, 0, class_desc->func_cnt*sizeof(*class_desc->funcs)); 1613 1614 for(func_decl = class_decl->funcs, i=1; func_decl; func_decl = func_decl->next, i++) { 1615 for(func_prop_decl = func_decl; func_prop_decl; func_prop_decl = func_prop_decl->next_prop_func) { 1616 if(func_prop_decl->type == FUNC_DEFGET) { 1617 i--; 1618 break; 1619 } 1620 } 1621 1622 if(!strcmpiW(class_initializeW, func_decl->name)) { 1623 if(func_decl->type != FUNC_SUB) { 1624 FIXME("class initializer is not sub\n"); 1625 return E_FAIL; 1626 } 1627 1628 class_desc->class_initialize_id = i; 1629 }else if(!strcmpiW(class_terminateW, func_decl->name)) { 1630 if(func_decl->type != FUNC_SUB) { 1631 FIXME("class terminator is not sub\n"); 1632 return E_FAIL; 1633 } 1634 1635 class_desc->class_terminate_id = i; 1636 } 1637 1638 hres = create_class_funcprop(ctx, func_decl, class_desc->funcs + (func_prop_decl ? 0 : i)); 1639 if(FAILED(hres)) 1640 return hres; 1641 } 1642 1643 for(prop_decl = class_decl->props; prop_decl; prop_decl = prop_decl->next) 1644 class_desc->prop_cnt++; 1645 1646 class_desc->props = compiler_alloc(ctx->code, class_desc->prop_cnt*sizeof(*class_desc->props)); 1647 if(!class_desc->props) 1648 return E_OUTOFMEMORY; 1649 1650 for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next, i++) { 1651 if(lookup_class_funcs(class_desc, prop_decl->name)) { 1652 FIXME("Property %s redefined\n", debugstr_w(prop_decl->name)); 1653 return E_FAIL; 1654 } 1655 1656 class_desc->props[i].name = compiler_alloc_string(ctx->code, prop_decl->name); 1657 if(!class_desc->props[i].name) 1658 return E_OUTOFMEMORY; 1659 1660 class_desc->props[i].is_public = prop_decl->is_public; 1661 class_desc->props[i].is_array = prop_decl->is_array; 1662 1663 if(prop_decl->is_array) 1664 class_desc->array_cnt++; 1665 } 1666 1667 if(class_desc->array_cnt) { 1668 class_desc->array_descs = compiler_alloc(ctx->code, class_desc->array_cnt*sizeof(*class_desc->array_descs)); 1669 if(!class_desc->array_descs) 1670 return E_OUTOFMEMORY; 1671 1672 for(prop_decl = class_decl->props, i=0; prop_decl; prop_decl = prop_decl->next) { 1673 if(prop_decl->is_array) { 1674 hres = fill_array_desc(ctx, prop_decl, class_desc->array_descs + i++); 1675 if(FAILED(hres)) 1676 return hres; 1677 } 1678 } 1679 } 1680 1681 class_desc->next = ctx->classes; 1682 ctx->classes = class_desc; 1683 return S_OK; 1684 } 1685 1686 static BOOL lookup_script_identifier(script_ctx_t *script, const WCHAR *identifier) 1687 { 1688 class_desc_t *class; 1689 dynamic_var_t *var; 1690 function_t *func; 1691 1692 for(var = script->global_vars; var; var = var->next) { 1693 if(!strcmpiW(var->name, identifier)) 1694 return TRUE; 1695 } 1696 1697 for(func = script->global_funcs; func; func = func->next) { 1698 if(!strcmpiW(func->name, identifier)) 1699 return TRUE; 1700 } 1701 1702 for(class = script->classes; class; class = class->next) { 1703 if(!strcmpiW(class->name, identifier)) 1704 return TRUE; 1705 } 1706 1707 return FALSE; 1708 } 1709 1710 static HRESULT check_script_collisions(compile_ctx_t *ctx, script_ctx_t *script) 1711 { 1712 class_desc_t *class; 1713 dynamic_var_t *var; 1714 function_t *func; 1715 1716 for(var = ctx->global_vars; var; var = var->next) { 1717 if(lookup_script_identifier(script, var->name)) { 1718 FIXME("%s: redefined\n", debugstr_w(var->name)); 1719 return E_FAIL; 1720 } 1721 } 1722 1723 for(func = ctx->funcs; func; func = func->next) { 1724 if(lookup_script_identifier(script, func->name)) { 1725 FIXME("%s: redefined\n", debugstr_w(func->name)); 1726 return E_FAIL; 1727 } 1728 } 1729 1730 for(class = ctx->classes; class; class = class->next) { 1731 if(lookup_script_identifier(script, class->name)) { 1732 FIXME("%s: redefined\n", debugstr_w(class->name)); 1733 return E_FAIL; 1734 } 1735 } 1736 1737 return S_OK; 1738 } 1739 1740 void release_vbscode(vbscode_t *code) 1741 { 1742 unsigned i; 1743 1744 list_remove(&code->entry); 1745 1746 for(i=0; i < code->bstr_cnt; i++) 1747 SysFreeString(code->bstr_pool[i]); 1748 1749 heap_pool_free(&code->heap); 1750 1751 heap_free(code->bstr_pool); 1752 heap_free(code->source); 1753 heap_free(code->instrs); 1754 heap_free(code); 1755 } 1756 1757 static vbscode_t *alloc_vbscode(compile_ctx_t *ctx, const WCHAR *source) 1758 { 1759 vbscode_t *ret; 1760 1761 ret = heap_alloc(sizeof(*ret)); 1762 if(!ret) 1763 return NULL; 1764 1765 ret->source = heap_strdupW(source); 1766 if(!ret->source) { 1767 heap_free(ret); 1768 return NULL; 1769 } 1770 1771 ret->instrs = heap_alloc(32*sizeof(instr_t)); 1772 if(!ret->instrs) { 1773 release_vbscode(ret); 1774 return NULL; 1775 } 1776 1777 ctx->instr_cnt = 1; 1778 ctx->instr_size = 32; 1779 heap_pool_init(&ret->heap); 1780 1781 ret->option_explicit = ctx->parser.option_explicit; 1782 1783 ret->bstr_pool = NULL; 1784 ret->bstr_pool_size = 0; 1785 ret->bstr_cnt = 0; 1786 ret->pending_exec = FALSE; 1787 1788 ret->main_code.type = FUNC_GLOBAL; 1789 ret->main_code.name = NULL; 1790 ret->main_code.code_ctx = ret; 1791 ret->main_code.vars = NULL; 1792 ret->main_code.var_cnt = 0; 1793 ret->main_code.array_cnt = 0; 1794 ret->main_code.arg_cnt = 0; 1795 ret->main_code.args = NULL; 1796 1797 list_init(&ret->entry); 1798 return ret; 1799 } 1800 1801 static void release_compiler(compile_ctx_t *ctx) 1802 { 1803 parser_release(&ctx->parser); 1804 heap_free(ctx->labels); 1805 if(ctx->code) 1806 release_vbscode(ctx->code); 1807 } 1808 1809 HRESULT compile_script(script_ctx_t *script, const WCHAR *src, const WCHAR *delimiter, vbscode_t **ret) 1810 { 1811 function_t *new_func; 1812 function_decl_t *func_decl; 1813 class_decl_t *class_decl; 1814 compile_ctx_t ctx; 1815 vbscode_t *code; 1816 HRESULT hres; 1817 1818 hres = parse_script(&ctx.parser, src, delimiter); 1819 if(FAILED(hres)) 1820 return hres; 1821 1822 code = ctx.code = alloc_vbscode(&ctx, src); 1823 if(!ctx.code) 1824 return E_OUTOFMEMORY; 1825 1826 ctx.funcs = NULL; 1827 ctx.func_decls = NULL; 1828 ctx.global_vars = NULL; 1829 ctx.classes = NULL; 1830 ctx.labels = NULL; 1831 ctx.global_consts = NULL; 1832 ctx.stat_ctx = NULL; 1833 ctx.labels_cnt = ctx.labels_size = 0; 1834 1835 hres = compile_func(&ctx, ctx.parser.stats, &ctx.code->main_code); 1836 if(FAILED(hres)) { 1837 release_compiler(&ctx); 1838 return hres; 1839 } 1840 1841 ctx.global_consts = ctx.const_decls; 1842 1843 for(func_decl = ctx.func_decls; func_decl; func_decl = func_decl->next) { 1844 hres = create_function(&ctx, func_decl, &new_func); 1845 if(FAILED(hres)) { 1846 release_compiler(&ctx); 1847 return hres; 1848 } 1849 1850 new_func->next = ctx.funcs; 1851 ctx.funcs = new_func; 1852 } 1853 1854 for(class_decl = ctx.parser.class_decls; class_decl; class_decl = class_decl->next) { 1855 hres = compile_class(&ctx, class_decl); 1856 if(FAILED(hres)) { 1857 release_compiler(&ctx); 1858 return hres; 1859 } 1860 } 1861 1862 hres = check_script_collisions(&ctx, script); 1863 if(FAILED(hres)) { 1864 release_compiler(&ctx); 1865 return hres; 1866 } 1867 1868 if(ctx.global_vars) { 1869 dynamic_var_t *var; 1870 1871 for(var = ctx.global_vars; var->next; var = var->next); 1872 1873 var->next = script->global_vars; 1874 script->global_vars = ctx.global_vars; 1875 } 1876 1877 if(ctx.funcs) { 1878 for(new_func = ctx.funcs; new_func->next; new_func = new_func->next); 1879 1880 new_func->next = script->global_funcs; 1881 script->global_funcs = ctx.funcs; 1882 } 1883 1884 if(ctx.classes) { 1885 class_desc_t *class = ctx.classes; 1886 1887 while(1) { 1888 class->ctx = script; 1889 if(!class->next) 1890 break; 1891 class = class->next; 1892 } 1893 1894 class->next = script->classes; 1895 script->classes = ctx.classes; 1896 } 1897 1898 if(TRACE_ON(vbscript_disas)) 1899 dump_code(&ctx); 1900 1901 ctx.code = NULL; 1902 release_compiler(&ctx); 1903 1904 list_add_tail(&script->code_list, &code->entry); 1905 *ret = code; 1906 return S_OK; 1907 } 1908