ReactOS 0.4.15-dev-7788-g1ad9096
lex.c
Go to the documentation of this file.
1/*
2 * Copyright 2008 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
20#include <limits.h>
21#include <math.h>
22
23#include "jscript.h"
24#include "activscp.h"
25#include "objsafe.h"
26#include "engine.h"
27#include "parser.h"
28
29#include "parser.tab.h"
30
31#include "wine/debug.h"
32
34
35static const struct {
36 const WCHAR *word;
37 int token;
39 unsigned min_version;
40} keywords[] = {
41 {L"break", kBREAK, TRUE},
42 {L"case", kCASE},
43 {L"catch", kCATCH},
44 {L"continue", kCONTINUE, TRUE},
45 {L"default", kDEFAULT},
46 {L"delete", kDELETE},
47 {L"do", kDO},
48 {L"else", kELSE},
49 {L"false", kFALSE},
50 {L"finally", kFINALLY},
51 {L"for", kFOR},
52 {L"function", kFUNCTION},
53 {L"get", kGET, FALSE, SCRIPTLANGUAGEVERSION_ES5},
54 {L"if", kIF},
55 {L"in", kIN},
56 {L"instanceof", kINSTANCEOF},
57 {L"new", kNEW},
58 {L"null", kNULL},
59 {L"return", kRETURN, TRUE},
60 {L"set", kSET, FALSE, SCRIPTLANGUAGEVERSION_ES5},
61 {L"switch", kSWITCH},
62 {L"this", kTHIS},
63 {L"throw", kTHROW},
64 {L"true", kTRUE},
65 {L"try", kTRY},
66 {L"typeof", kTYPEOF},
67 {L"var", kVAR},
68 {L"void", kVOID},
69 {L"while", kWHILE},
70 {L"with", kWITH}
71};
72
74{
75 ctx->hres = hres;
76 ctx->lexer_error = TRUE;
77 return -1;
78}
79
80/* ECMA-262 3rd Edition 7.6 */
82{
83 return iswalnum(c) || c == '$' || c == '_' || c == '\\';
84}
85
87{
88 return iswalpha(c) || c == '$' || c == '_' || c == '\\';
89}
90
91static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lval)
92{
93 const WCHAR *p1 = ctx->ptr;
94 const WCHAR *p2 = word;
95
96 while(p1 < ctx->end && *p2) {
97 if(*p1 != *p2)
98 return *p1 - *p2;
99 p1++;
100 p2++;
101 }
102
103 if(*p2 || (p1 < ctx->end && is_identifier_char(*p1)))
104 return 1;
105
106 if(lval)
107 *lval = word;
108 ctx->ptr = p1;
109 return 0;
110}
111
112/* ECMA-262 3rd Edition 7.3 */
114{
115 return c == '\n' || c == '\r' || c == 0x2028 || c == 0x2029;
116}
117
118static int hex_to_int(WCHAR c)
119{
120 if('0' <= c && c <= '9')
121 return c-'0';
122
123 if('a' <= c && c <= 'f')
124 return c-'a'+10;
125
126 if('A' <= c && c <= 'F')
127 return c-'A'+10;
128
129 return -1;
130}
131
132static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval)
133{
134 int min = 0, max = ARRAY_SIZE(keywords)-1, r, i;
135
136 while(min <= max) {
137 i = (min+max)/2;
138
139 r = check_keyword(ctx, keywords[i].word, lval);
140 if(!r) {
141 if(ctx->script->version < keywords[i].min_version) {
142 TRACE("ignoring keyword %s in incompatible mode\n",
144 ctx->ptr -= lstrlenW(keywords[i].word);
145 return 0;
146 }
147 ctx->implicit_nl_semicolon = keywords[i].no_nl;
148 return keywords[i].token;
149 }
150
151 if(r > 0)
152 min = i+1;
153 else
154 max = i-1;
155 }
156
157 return 0;
158}
159
161{
162 const WCHAR html_commentW[] = {'<','!','-','-',0};
163
164 if(!ctx->is_html || ctx->ptr+3 >= ctx->end ||
165 memcmp(ctx->ptr, html_commentW, sizeof(WCHAR)*4))
166 return FALSE;
167
168 ctx->nl = TRUE;
169 while(ctx->ptr < ctx->end && !is_endline(*ctx->ptr++));
170
171 return TRUE;
172}
173
175{
176 if(ctx->ptr+1 >= ctx->end)
177 return FALSE;
178
179 if(*ctx->ptr != '/') {
180 if(*ctx->ptr == '@' && ctx->ptr+2 < ctx->end && ctx->ptr[1] == '*' && ctx->ptr[2] == '/') {
181 ctx->ptr += 3;
182 return TRUE;
183 }
184
185 return FALSE;
186 }
187
188 switch(ctx->ptr[1]) {
189 case '*':
190 ctx->ptr += 2;
191 if(ctx->ptr+2 < ctx->end && *ctx->ptr == '@' && is_identifier_char(ctx->ptr[1]))
192 return FALSE;
193 while(ctx->ptr+1 < ctx->end && (ctx->ptr[0] != '*' || ctx->ptr[1] != '/'))
194 ctx->ptr++;
195
196 if(ctx->ptr[0] == '*' && ctx->ptr[1] == '/') {
197 ctx->ptr += 2;
198 }else {
199 WARN("unexpected end of file (missing end of comment)\n");
200 ctx->ptr = ctx->end;
201 }
202 break;
203 case '/':
204 ctx->ptr += 2;
205 if(ctx->ptr+2 < ctx->end && *ctx->ptr == '@' && is_identifier_char(ctx->ptr[1]))
206 return FALSE;
207 while(ctx->ptr < ctx->end && !is_endline(*ctx->ptr))
208 ctx->ptr++;
209 break;
210 default:
211 return FALSE;
212 }
213
214 return TRUE;
215}
216
218{
219 while(ctx->ptr < ctx->end && (iswspace(*ctx->ptr) || *ctx->ptr == 0xFEFF /* UTF16 BOM */)) {
220 if(is_endline(*ctx->ptr++))
221 ctx->nl = TRUE;
222 }
223
224 return ctx->ptr != ctx->end;
225}
226
228{
229 WCHAR *pd, *p, c, *end = str + *len;
230 int i;
231
232 pd = p = str;
233 while(p < end) {
234 if(*p != '\\') {
235 *pd++ = *p++;
236 continue;
237 }
238
239 if(++p == end)
240 return FALSE;
241
242 switch(*p) {
243 case '\'':
244 case '\"':
245 case '\\':
246 c = *p;
247 break;
248 case 'b':
249 c = '\b';
250 break;
251 case 't':
252 c = '\t';
253 break;
254 case 'n':
255 c = '\n';
256 break;
257 case 'f':
258 c = '\f';
259 break;
260 case 'r':
261 c = '\r';
262 break;
263 case 'x':
264 if(p + 2 >= end)
265 return FALSE;
266 i = hex_to_int(*++p);
267 if(i == -1)
268 return FALSE;
269 c = i << 4;
270
271 i = hex_to_int(*++p);
272 if(i == -1)
273 return FALSE;
274 c += i;
275 break;
276 case 'u':
277 if(p + 4 >= end)
278 return FALSE;
279 i = hex_to_int(*++p);
280 if(i == -1)
281 return FALSE;
282 c = i << 12;
283
284 i = hex_to_int(*++p);
285 if(i == -1)
286 return FALSE;
287 c += i << 8;
288
289 i = hex_to_int(*++p);
290 if(i == -1)
291 return FALSE;
292 c += i << 4;
293
294 i = hex_to_int(*++p);
295 if(i == -1)
296 return FALSE;
297 c += i;
298 break;
299 default:
300 if(iswdigit(*p)) {
301 c = *p++ - '0';
302 if(p < end && iswdigit(*p)) {
303 c = c*8 + (*p++ - '0');
304 if(p < end && iswdigit(*p))
305 c = c*8 + (*p++ - '0');
306 }
307 p--;
308 }
309 else
310 c = *p;
311 }
312
313 *pd++ = c;
314 p++;
315 }
316
317 *len = pd - str;
318 return TRUE;
319}
320
322{
323 const WCHAR *ptr = ctx->ptr++;
324 WCHAR *wstr;
325 int len;
326
327 while(ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr))
328 ctx->ptr++;
329
330 len = ctx->ptr-ptr;
331
332 *ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR));
333 memcpy(wstr, ptr, len*sizeof(WCHAR));
334 wstr[len] = 0;
335
336 /* FIXME: unescape */
337 return tIdentifier;
338}
339
341{
342 const WCHAR *ptr = ++ctx->ptr, *ret_str = ptr;
343 BOOL needs_unescape = FALSE;
344 WCHAR *unescape_str;
345 size_t len;
346
347 while(ctx->ptr < ctx->end && *ctx->ptr != endch) {
348 if(*ctx->ptr++ == '\\') {
349 ctx->ptr++;
350 needs_unescape = TRUE;
351 }
352 }
353
354 if(ctx->ptr == ctx->end)
356
357 len = ctx->ptr - ptr;
358 ctx->ptr++;
359
360 if(needs_unescape) {
361 ret_str = unescape_str = parser_alloc(ctx, len * sizeof(WCHAR));
362 if(!unescape_str)
363 return lex_error(ctx, E_OUTOFMEMORY);
364 memcpy(unescape_str, ptr, len * sizeof(WCHAR));
365 if(!unescape(unescape_str, &len)) {
366 WARN("unescape failed\n");
367 return lex_error(ctx, E_FAIL);
368 }
369 }
370
371 if(!(*ret = compiler_alloc_string_len(ctx->compiler, ret_str, len)))
372 return lex_error(ctx, E_OUTOFMEMORY);
373
374 /* FIXME: leaking string */
375 return tStringLiteral;
376}
377
379{
381
382 ret->type = LT_DOUBLE;
383 ret->u.dval = d;
384 return ret;
385}
386
388{
390
391 ret->type = LT_BOOL;
392 ret->u.bval = bval;
393
394 return ret;
395}
396
397HRESULT parse_decimal(const WCHAR **iter, const WCHAR *end, double *ret)
398{
399 const WCHAR *ptr = *iter;
400 LONGLONG d = 0, hlp;
401 int exp = 0;
402
403 while(ptr < end && iswdigit(*ptr)) {
404 hlp = d*10 + *(ptr++) - '0';
405 if(d>MAXLONGLONG/10 || hlp<0) {
406 exp++;
407 break;
408 }
409 else
410 d = hlp;
411 }
412 while(ptr < end && iswdigit(*ptr)) {
413 exp++;
414 ptr++;
415 }
416
417 if(*ptr == '.') {
418 ptr++;
419
420 while(ptr < end && iswdigit(*ptr)) {
421 hlp = d*10 + *(ptr++) - '0';
422 if(d>MAXLONGLONG/10 || hlp<0)
423 break;
424
425 d = hlp;
426 exp--;
427 }
428 while(ptr < end && iswdigit(*ptr))
429 ptr++;
430 }
431
432 if(ptr < end && (*ptr == 'e' || *ptr == 'E')) {
433 int sign = 1, e = 0;
434
435 if(++ptr < end) {
436 if(*ptr == '+') {
437 ptr++;
438 }else if(*ptr == '-') {
439 sign = -1;
440 ptr++;
441 }else if(!iswdigit(*ptr)) {
442 WARN("Expected exponent part\n");
443 return E_FAIL;
444 }
445 }
446
447 if(ptr == end) {
448 WARN("unexpected end of file\n");
449 return E_FAIL;
450 }
451
452 while(ptr < end && iswdigit(*ptr)) {
453 if(e > INT_MAX/10 || (e = e*10 + *ptr++ - '0')<0)
454 e = INT_MAX;
455 }
456 e *= sign;
457
458 if(exp<0 && e<0 && e+exp>0) exp = INT_MIN;
459 else if(exp>0 && e>0 && e+exp<0) exp = INT_MAX;
460 else exp += e;
461 }
462
463 if(is_identifier_char(*ptr)) {
464 WARN("wrong char after zero\n");
466 }
467
468 *ret = exp>=0 ? d*pow(10, exp) : d/pow(10, -exp);
469 *iter = ptr;
470 return S_OK;
471}
472
474{
476
477 if(*ctx->ptr == '0') {
478 ctx->ptr++;
479
480 if(*ctx->ptr == 'x' || *ctx->ptr == 'X') {
481 double r = 0;
482 int d;
483 if(++ctx->ptr == ctx->end) {
484 ERR("unexpected end of file\n");
485 return FALSE;
486 }
487
488 while(ctx->ptr < ctx->end && (d = hex_to_int(*ctx->ptr)) != -1) {
489 r = r*16 + d;
490 ctx->ptr++;
491 }
492
493 if(ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr)) {
494 WARN("unexpected identifier char\n");
496 return FALSE;
497 }
498
499 *ret = r;
500 return TRUE;
501 }
502
503 if(iswdigit(*ctx->ptr)) {
504 unsigned base = 8;
505 const WCHAR *ptr;
506 double val = 0;
507
508 for(ptr = ctx->ptr; ptr < ctx->end && iswdigit(*ptr); ptr++) {
509 if(*ptr > '7') {
510 base = 10;
511 break;
512 }
513 }
514
515 do {
516 val = val*base + *ctx->ptr-'0';
517 }while(++ctx->ptr < ctx->end && iswdigit(*ctx->ptr));
518
519 /* FIXME: Do we need it here? */
520 if(ctx->ptr < ctx->end && (is_identifier_char(*ctx->ptr) || *ctx->ptr == '.')) {
521 WARN("wrong char after octal literal: '%c'\n", *ctx->ptr);
523 return FALSE;
524 }
525
526 *ret = val;
527 return TRUE;
528 }
529
530 if(is_identifier_char(*ctx->ptr)) {
531 WARN("wrong char after zero\n");
533 return FALSE;
534 }
535 }
536
537 hres = parse_decimal(&ctx->ptr, ctx->end, ret);
538 if(FAILED(hres)) {
540 return FALSE;
541 }
542
543 return TRUE;
544}
545
546static int next_token(parser_ctx_t *ctx, void *lval)
547{
548 do {
549 if(!skip_spaces(ctx))
550 return tEOF;
552
553 if(ctx->implicit_nl_semicolon) {
554 if(ctx->nl)
555 return ';';
556 ctx->implicit_nl_semicolon = FALSE;
557 }
558
559 if(iswalpha(*ctx->ptr)) {
560 int ret = check_keywords(ctx, lval);
561 if(ret)
562 return ret;
563
564 return parse_identifier(ctx, lval);
565 }
566
567 if(iswdigit(*ctx->ptr)) {
568 double n;
569
571 return -1;
572
573 *(literal_t**)lval = new_double_literal(ctx, n);
574 return tNumericLiteral;
575 }
576
577 switch(*ctx->ptr) {
578 case '{':
579 case '(':
580 case ')':
581 case '[':
582 case ']':
583 case ';':
584 case ',':
585 case '~':
586 case '?':
587 return *ctx->ptr++;
588
589 case '}':
590 *(const WCHAR**)lval = ctx->ptr++;
591 return '}';
592
593 case '.':
594 if(ctx->ptr+1 < ctx->end && iswdigit(ctx->ptr[1])) {
595 double n;
597 hres = parse_decimal(&ctx->ptr, ctx->end, &n);
598 if(FAILED(hres)) {
600 return -1;
601 }
602 *(literal_t**)lval = new_double_literal(ctx, n);
603 return tNumericLiteral;
604 }
605 ctx->ptr++;
606 return '.';
607
608 case '<':
609 if(++ctx->ptr == ctx->end) {
610 *(int*)lval = EXPR_LESS;
611 return tRelOper;
612 }
613
614 switch(*ctx->ptr) {
615 case '=': /* <= */
616 ctx->ptr++;
617 *(int*)lval = EXPR_LESSEQ;
618 return tRelOper;
619 case '<': /* << */
620 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* <<= */
621 ctx->ptr++;
622 *(int*)lval = EXPR_ASSIGNLSHIFT;
623 return tAssignOper;
624 }
625 *(int*)lval = EXPR_LSHIFT;
626 return tShiftOper;
627 default: /* < */
628 *(int*)lval = EXPR_LESS;
629 return tRelOper;
630 }
631
632 case '>':
633 if(++ctx->ptr == ctx->end) { /* > */
634 *(int*)lval = EXPR_GREATER;
635 return tRelOper;
636 }
637
638 switch(*ctx->ptr) {
639 case '=': /* >= */
640 ctx->ptr++;
641 *(int*)lval = EXPR_GREATEREQ;
642 return tRelOper;
643 case '>': /* >> */
644 if(++ctx->ptr < ctx->end) {
645 if(*ctx->ptr == '=') { /* >>= */
646 ctx->ptr++;
647 *(int*)lval = EXPR_ASSIGNRSHIFT;
648 return tAssignOper;
649 }
650 if(*ctx->ptr == '>') { /* >>> */
651 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* >>>= */
652 ctx->ptr++;
653 *(int*)lval = EXPR_ASSIGNRRSHIFT;
654 return tAssignOper;
655 }
656 *(int*)lval = EXPR_RRSHIFT;
657 return tRelOper;
658 }
659 }
660 *(int*)lval = EXPR_RSHIFT;
661 return tShiftOper;
662 default:
663 *(int*)lval = EXPR_GREATER;
664 return tRelOper;
665 }
666
667 case '+':
668 ctx->ptr++;
669 if(ctx->ptr < ctx->end) {
670 switch(*ctx->ptr) {
671 case '+': /* ++ */
672 ctx->ptr++;
673 return tINC;
674 case '=': /* += */
675 ctx->ptr++;
676 *(int*)lval = EXPR_ASSIGNADD;
677 return tAssignOper;
678 }
679 }
680 return '+';
681
682 case '-':
683 ctx->ptr++;
684 if(ctx->ptr < ctx->end) {
685 switch(*ctx->ptr) {
686 case '-': /* -- or --> */
687 ctx->ptr++;
688 if(ctx->is_html && ctx->nl && ctx->ptr < ctx->end && *ctx->ptr == '>') {
689 ctx->ptr++;
690 return tHTMLCOMMENT;
691 }
692 return tDEC;
693 case '=': /* -= */
694 ctx->ptr++;
695 *(int*)lval = EXPR_ASSIGNSUB;
696 return tAssignOper;
697 }
698 }
699 return '-';
700
701 case '*':
702 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* *= */
703 ctx->ptr++;
704 *(int*)lval = EXPR_ASSIGNMUL;
705 return tAssignOper;
706 }
707 return '*';
708
709 case '%':
710 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* %= */
711 ctx->ptr++;
712 *(int*)lval = EXPR_ASSIGNMOD;
713 return tAssignOper;
714 }
715 return '%';
716
717 case '&':
718 if(++ctx->ptr < ctx->end) {
719 switch(*ctx->ptr) {
720 case '=': /* &= */
721 ctx->ptr++;
722 *(int*)lval = EXPR_ASSIGNAND;
723 return tAssignOper;
724 case '&': /* && */
725 ctx->ptr++;
726 return tANDAND;
727 }
728 }
729 return '&';
730
731 case '|':
732 if(++ctx->ptr < ctx->end) {
733 switch(*ctx->ptr) {
734 case '=': /* |= */
735 ctx->ptr++;
736 *(int*)lval = EXPR_ASSIGNOR;
737 return tAssignOper;
738 case '|': /* || */
739 ctx->ptr++;
740 return tOROR;
741 }
742 }
743 return '|';
744
745 case '^':
746 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* ^= */
747 ctx->ptr++;
748 *(int*)lval = EXPR_ASSIGNXOR;
749 return tAssignOper;
750 }
751 return '^';
752
753 case '!':
754 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* != */
755 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* !== */
756 ctx->ptr++;
757 *(int*)lval = EXPR_NOTEQEQ;
758 return tEqOper;
759 }
760 *(int*)lval = EXPR_NOTEQ;
761 return tEqOper;
762 }
763 return '!';
764
765 case '=':
766 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* == */
767 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* === */
768 ctx->ptr++;
769 *(int*)lval = EXPR_EQEQ;
770 return tEqOper;
771 }
772 *(int*)lval = EXPR_EQ;
773 return tEqOper;
774 }
775 return '=';
776
777 case '/':
778 if(++ctx->ptr < ctx->end) {
779 if(*ctx->ptr == '=') { /* /= */
780 ctx->ptr++;
781 *(int*)lval = EXPR_ASSIGNDIV;
782 return kDIVEQ;
783 }
784 }
785 return '/';
786
787 case ':':
788 if(++ctx->ptr < ctx->end && *ctx->ptr == ':') {
789 ctx->ptr++;
790 return kDCOL;
791 }
792 return ':';
793
794 case '\"':
795 case '\'':
796 return parse_string_literal(ctx, lval, *ctx->ptr);
797
798 case '_':
799 case '$':
800 return parse_identifier(ctx, lval);
801
802 case '@':
803 return '@';
804 }
805
806 WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr);
807 return 0;
808}
809
810struct _cc_var_t {
813 unsigned name_len;
815};
816
818{
819 cc_var_t *iter, *next;
820
821 for(iter = cc->vars; iter; iter = next) {
822 next = iter->next;
823 heap_free(iter);
824 }
825
826 heap_free(cc);
827}
828
830{
831 cc_var_t *new_v;
832
833 if(len == -1)
834 len = lstrlenW(name);
835
836 new_v = heap_alloc(sizeof(cc_var_t) + (len+1)*sizeof(WCHAR));
837 if(!new_v)
838 return FALSE;
839
840 new_v->val = v;
841 memcpy(new_v->name, name, (len+1)*sizeof(WCHAR));
842 new_v->name_len = len;
843 new_v->next = cc->vars;
844 cc->vars = new_v;
845 return TRUE;
846}
847
848static cc_var_t *find_cc_var(cc_ctx_t *cc, const WCHAR *name, unsigned name_len)
849{
850 cc_var_t *iter;
851
852 for(iter = cc->vars; iter; iter = iter->next) {
853 if(iter->name_len == name_len && !memcmp(iter->name, name, name_len*sizeof(WCHAR)))
854 return iter;
855 }
856
857 return NULL;
858}
859
861{
862 cc_ctx_t *cc;
863
864 if(ctx->script->cc)
865 return TRUE;
866
867 cc = heap_alloc(sizeof(cc_ctx_t));
868 if(!cc) {
870 return FALSE;
871 }
872
873 cc->vars = NULL;
874
875 if(!new_cc_var(cc, L"_jscript", -1, ccval_bool(TRUE))
876 || !new_cc_var(cc, sizeof(void*) == 8 ? L"_win64" : L"_win32", -1, ccval_bool(TRUE))
877 || !new_cc_var(cc, sizeof(void*) == 8 ? L"_amd64" : L"_x86", -1, ccval_bool(TRUE))
878 || !new_cc_var(cc, L"_jscript_version", -1, ccval_num(JSCRIPT_MAJOR_VERSION + (DOUBLE)JSCRIPT_MINOR_VERSION/10.0))
879 || !new_cc_var(cc, L"_jscript_build", -1, ccval_num(JSCRIPT_BUILD_VERSION))) {
880 release_cc(cc);
882 return FALSE;
883 }
884
885 ctx->script->cc = cc;
886 return TRUE;
887}
888
890{
891 if(*ctx->ptr != '@') {
893 return FALSE;
894 }
895
896 if(!is_identifier_first_char(*++ctx->ptr)) {
898 return FALSE;
899 }
900
901 *ret = ctx->ptr;
902 while(++ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr));
903 *ret_len = ctx->ptr - *ret;
904 return TRUE;
905}
906
908{
909 if(!skip_spaces(ctx))
910 return -1;
911
912 if(iswdigit(*ctx->ptr)) {
913 double n;
914
916 return -1;
917
918 *r = ccval_num(n);
919 return 1;
920 }
921
922 if(*ctx->ptr == '@') {
923 const WCHAR *ident;
924 unsigned ident_len;
925 cc_var_t *cc_var;
926
928 return -1;
929
930 cc_var = find_cc_var(ctx->script->cc, ident, ident_len);
931 *r = cc_var ? cc_var->val : ccval_num(NAN);
932 return 1;
933 }
934
935 if(!check_keyword(ctx, L"true", NULL)) {
936 *r = ccval_bool(TRUE);
937 return 1;
938 }
939
940 if(!check_keyword(ctx, L"false", NULL)) {
941 *r = ccval_bool(FALSE);
942 return 1;
943 }
944
945 return 0;
946}
947
948static int skip_code(parser_ctx_t *ctx, BOOL exec_else)
949{
950 int if_depth = 1;
951 const WCHAR *ptr;
952
953 while(1) {
954 ptr = wcschr(ctx->ptr, '@');
955 if(!ptr) {
956 WARN("No @end\n");
958 }
959 ctx->ptr = ptr+1;
960
961 if(!check_keyword(ctx, L"end", NULL)) {
962 if(--if_depth)
963 continue;
964 return 0;
965 }
966
967 if(exec_else && !check_keyword(ctx, L"elif", NULL)) {
968 if(if_depth > 1)
969 continue;
970
971 if(!skip_spaces(ctx) || *ctx->ptr != '(')
973
974 if(!parse_cc_expr(ctx))
975 return -1;
976
977 if(!get_ccbool(ctx->ccval))
978 continue; /* skip block of code */
979
980 /* continue parsing */
981 ctx->cc_if_depth++;
982 return 0;
983 }
984
985 if(exec_else && !check_keyword(ctx, L"else", NULL)) {
986 if(if_depth > 1)
987 continue;
988
989 /* parse else block */
990 ctx->cc_if_depth++;
991 return 0;
992 }
993
994 if(!check_keyword(ctx, L"if", NULL)) {
995 if_depth++;
996 continue;
997 }
998
999 ctx->ptr++;
1000 }
1001}
1002
1003static int cc_token(parser_ctx_t *ctx, void *lval)
1004{
1005 unsigned id_len = 0;
1006 cc_var_t *var;
1007
1008 ctx->ptr++;
1009
1010 if(!check_keyword(ctx, L"cc_on", NULL))
1011 return init_cc(ctx) ? 0 : -1;
1012
1013 if(!check_keyword(ctx, L"set", NULL)) {
1014 const WCHAR *ident;
1015 unsigned ident_len;
1016 cc_var_t *var;
1017
1018 if(!init_cc(ctx))
1019 return -1;
1020
1021 if(!skip_spaces(ctx))
1023
1025 return -1;
1026
1027 if(!skip_spaces(ctx) || *ctx->ptr != '=')
1029 ctx->ptr++;
1030
1031 if(!parse_cc_expr(ctx)) {
1032 WARN("parsing CC expression failed\n");
1033 return -1;
1034 }
1035
1036 var = find_cc_var(ctx->script->cc, ident, ident_len);
1037 if(var) {
1038 var->val = ctx->ccval;
1039 }else {
1040 if(!new_cc_var(ctx->script->cc, ident, ident_len, ctx->ccval))
1041 return lex_error(ctx, E_OUTOFMEMORY);
1042 }
1043
1044 return 0;
1045 }
1046
1047 if(!check_keyword(ctx, L"if", NULL)) {
1048 if(!init_cc(ctx))
1049 return -1;
1050
1051 if(!skip_spaces(ctx) || *ctx->ptr != '(')
1053
1054 if(!parse_cc_expr(ctx))
1055 return -1;
1056
1057 if(get_ccbool(ctx->ccval)) {
1058 /* continue parsing block inside if */
1059 ctx->cc_if_depth++;
1060 return 0;
1061 }
1062
1063 return skip_code(ctx, TRUE);
1064 }
1065
1066 if(!check_keyword(ctx, L"elif", NULL) || !check_keyword(ctx, L"else", NULL)) {
1067 if(!ctx->cc_if_depth)
1068 return lex_error(ctx, JS_E_SYNTAX);
1069
1070 return skip_code(ctx, FALSE);
1071 }
1072
1073 if(!check_keyword(ctx, L"end", NULL)) {
1074 if(!ctx->cc_if_depth)
1075 return lex_error(ctx, JS_E_SYNTAX);
1076
1077 ctx->cc_if_depth--;
1078 return 0;
1079 }
1080
1081 if(!ctx->script->cc)
1083
1084 while(ctx->ptr+id_len < ctx->end && is_identifier_char(ctx->ptr[id_len]))
1085 id_len++;
1086 if(!id_len)
1087 return '@';
1088
1089 TRACE("var %s\n", debugstr_wn(ctx->ptr, id_len));
1090
1091 var = find_cc_var(ctx->script->cc, ctx->ptr, id_len);
1092 ctx->ptr += id_len;
1093 if(!var || var->val.is_num) {
1094 *(literal_t**)lval = new_double_literal(ctx, var ? var->val.u.n : NAN);
1095 return tNumericLiteral;
1096 }
1097
1098 *(literal_t**)lval = new_boolean_literal(ctx, var->val.u.b);
1099 return tBooleanLiteral;
1100}
1101
1102int parser_lex(void *lval, parser_ctx_t *ctx)
1103{
1104 int ret;
1105
1106 ctx->nl = ctx->ptr == ctx->begin;
1107
1108 do {
1109 ret = next_token(ctx, lval);
1110 } while(ret == '@' && !(ret = cc_token(ctx, lval)));
1111
1112 return ret;
1113}
1114
1116{
1117 const WCHAR *re, *flags_ptr;
1119 DWORD re_len, flags;
1120 literal_t *ret;
1121 HRESULT hres;
1122
1123 TRACE("\n");
1124
1125 while(*--ctx->ptr != '/');
1126
1127 /* Simple regexp pre-parser; '/' if used in char class does not terminate regexp literal */
1128 re = ++ctx->ptr;
1129 while(ctx->ptr < ctx->end) {
1130 if(*ctx->ptr == '\\') {
1131 if(++ctx->ptr == ctx->end)
1132 break;
1133 }else if(in_class) {
1134 if(*ctx->ptr == '\n')
1135 break;
1136 if(*ctx->ptr == ']')
1137 in_class = FALSE;
1138 }else {
1139 if(*ctx->ptr == '/')
1140 break;
1141
1142 if(*ctx->ptr == '[')
1143 in_class = TRUE;
1144 }
1145 ctx->ptr++;
1146 }
1147
1148 if(ctx->ptr == ctx->end || *ctx->ptr != '/') {
1149 WARN("pre-parsing failed\n");
1150 return NULL;
1151 }
1152
1153 re_len = ctx->ptr-re;
1154
1155 flags_ptr = ++ctx->ptr;
1156 while(ctx->ptr < ctx->end && iswalnum(*ctx->ptr))
1157 ctx->ptr++;
1158
1159 hres = parse_regexp_flags(flags_ptr, ctx->ptr-flags_ptr, &flags);
1160 if(FAILED(hres))
1161 return NULL;
1162
1163 ret = parser_alloc(ctx, sizeof(literal_t));
1164 ret->type = LT_REGEXP;
1165 ret->u.regexp.str = compiler_alloc_string_len(ctx->compiler, re, re_len);
1166 ret->u.regexp.flags = flags;
1167 return ret;
1168}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:33
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
float bval
Definition: cylfrac.c:48
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define wcschr
Definition: compat.h:17
#define lstrlenW
Definition: compat.h:750
static void * parser_alloc(parser_ctx_t *ctx, DWORD size)
Definition: parser.h:58
@ EXPR_RSHIFT
Definition: parser.h:250
@ EXPR_LESS
Definition: parser.h:243
@ EXPR_ASSIGNADD
Definition: parser.h:256
@ EXPR_GREATER
Definition: parser.h:245
@ EXPR_EQEQ
Definition: parser.h:240
@ EXPR_ASSIGNRRSHIFT
Definition: parser.h:255
@ EXPR_ASSIGNDIV
Definition: parser.h:259
@ EXPR_ASSIGNMUL
Definition: parser.h:258
@ EXPR_ASSIGNMOD
Definition: parser.h:260
@ EXPR_ASSIGNOR
Definition: parser.h:262
@ EXPR_GREATEREQ
Definition: parser.h:246
@ EXPR_ASSIGNLSHIFT
Definition: parser.h:253
@ EXPR_LSHIFT
Definition: parser.h:249
@ EXPR_NOTEQ
Definition: parser.h:241
@ EXPR_NOTEQEQ
Definition: parser.h:242
@ EXPR_ASSIGNAND
Definition: parser.h:261
@ EXPR_RRSHIFT
Definition: parser.h:251
@ EXPR_ASSIGNSUB
Definition: parser.h:257
@ EXPR_EQ
Definition: parser.h:239
@ EXPR_ASSIGNRSHIFT
Definition: parser.h:254
@ EXPR_LESSEQ
Definition: parser.h:244
@ EXPR_ASSIGNXOR
Definition: parser.h:263
static ccval_t ccval_bool(BOOL b)
Definition: parser.h:387
@ LT_BOOL
Definition: parser.h:75
@ LT_REGEXP
Definition: parser.h:77
@ LT_DOUBLE
Definition: parser.h:73
BOOL parse_cc_expr(parser_ctx_t *) DECLSPEC_HIDDEN
static ccval_t ccval_num(double n)
Definition: parser.h:379
static BOOL get_ccbool(ccval_t v)
Definition: parser.h:395
#define JSCRIPT_MAJOR_VERSION
Definition: resource.h:23
#define JSCRIPT_BUILD_VERSION
Definition: resource.h:25
#define JSCRIPT_MINOR_VERSION
Definition: resource.h:24
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
double pow(double x, double y)
Definition: freeldr.c:112
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint end
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble n
Definition: glext.h:7729
const GLubyte * c
Definition: glext.h:8905
GLbitfield flags
Definition: glext.h:7161
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define iswspace(_c)
Definition: ctype.h:669
#define iswdigit(_c)
Definition: ctype.h:667
#define iswalnum(_c)
Definition: ctype.h:671
#define iswalpha(_c)
Definition: ctype.h:664
#define INT_MIN
Definition: limits.h:39
#define INT_MAX
Definition: limits.h:40
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t cc
Definition: isohybrid.c:75
jsstr_t * compiler_alloc_string_len(compiler_ctx_t *ctx, const WCHAR *str, unsigned len)
Definition: compile.c:133
literal_t * parse_regexp(parser_ctx_t *ctx)
Definition: lex.c:1115
static literal_t * new_double_literal(parser_ctx_t *ctx, DOUBLE d)
Definition: lex.c:378
static BOOL skip_spaces(parser_ctx_t *ctx)
Definition: lex.c:217
static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval)
Definition: lex.c:132
HRESULT parse_decimal(const WCHAR **iter, const WCHAR *end, double *ret)
Definition: lex.c:397
static BOOL is_endline(WCHAR c)
Definition: lex.c:113
static cc_var_t * find_cc_var(cc_ctx_t *cc, const WCHAR *name, unsigned name_len)
Definition: lex.c:848
BOOL unescape(WCHAR *str, size_t *len)
Definition: lex.c:227
static BOOL init_cc(parser_ctx_t *ctx)
Definition: lex.c:860
static BOOL parse_cc_identifier(parser_ctx_t *ctx, const WCHAR **ret, unsigned *ret_len)
Definition: lex.c:889
static int parse_string_literal(parser_ctx_t *ctx, jsstr_t **ret, WCHAR endch)
Definition: lex.c:340
static const struct @445 keywords[]
int token
Definition: lex.c:37
BOOL no_nl
Definition: lex.c:38
static BOOL new_cc_var(cc_ctx_t *cc, const WCHAR *name, int len, ccval_t v)
Definition: lex.c:829
static int cc_token(parser_ctx_t *ctx, void *lval)
Definition: lex.c:1003
static int lex_error(parser_ctx_t *ctx, HRESULT hres)
Definition: lex.c:73
static BOOL is_identifier_first_char(WCHAR c)
Definition: lex.c:86
int try_parse_ccval(parser_ctx_t *ctx, ccval_t *r)
Definition: lex.c:907
static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lval)
Definition: lex.c:91
static int skip_code(parser_ctx_t *ctx, BOOL exec_else)
Definition: lex.c:948
literal_t * new_boolean_literal(parser_ctx_t *ctx, BOOL bval)
Definition: lex.c:387
static int next_token(parser_ctx_t *ctx, void *lval)
Definition: lex.c:546
void release_cc(cc_ctx_t *cc)
Definition: lex.c:817
unsigned min_version
Definition: lex.c:39
BOOL is_identifier_char(WCHAR c)
Definition: lex.c:81
static BOOL skip_comment(parser_ctx_t *ctx)
Definition: lex.c:174
const WCHAR * word
Definition: lex.c:36
static int parse_identifier(parser_ctx_t *ctx, const WCHAR **ret)
Definition: lex.c:321
static BOOL skip_html_comment(parser_ctx_t *ctx)
Definition: lex.c:160
static BOOL parse_numeric_literal(parser_ctx_t *ctx, double *ret)
Definition: lex.c:473
static int hex_to_int(WCHAR c)
Definition: lex.c:118
#define JS_E_DISABLED_CC
Definition: jscript.h:550
#define JS_E_EXPECTED_CCEND
Definition: jscript.h:549
#define JS_E_SYNTAX
Definition: jscript.h:536
#define JS_E_EXPECTED_IDENTIFIER
Definition: jscript.h:540
#define JS_E_UNTERMINATED_STRING
Definition: jscript.h:543
#define JS_E_EXPECTED_ASSIGN
Definition: jscript.h:541
#define SCRIPTLANGUAGEVERSION_ES5
Definition: jscript.h:52
HRESULT parse_regexp_flags(const WCHAR *, DWORD, DWORD *) DECLSPEC_HIDDEN
Definition: jsregexp.c:1022
#define JS_E_MISSING_SEMICOLON
Definition: jscript.h:537
#define JS_E_MISSING_LBRACKET
Definition: jscript.h:538
#define JS_E_EXPECTED_AT
Definition: jscript.h:551
#define d
Definition: ke_i.h:81
#define e
Definition: ke_i.h:82
#define c
Definition: ke_i.h:80
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
#define sign(x)
Definition: mapdesc.cc:613
#define in_class(found, pat, c)
Definition: match.c:168
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
#define NAN
Definition: mesh.c:39
const char * var
Definition: shader.c:5666
HRESULT hres
Definition: protocol.c:465
static JOBOBJECTINFOCLASS LPVOID DWORD LPDWORD ret_len
Definition: process.c:79
DWORD exp
Definition: msg.c:16058
#define min(a, b)
Definition: monoChain.cc:55
#define MAXLONGLONG
#define L(x)
Definition: ntvdm.h:50
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * str
int parser_lex(void)
static INT ident_len(LPCTSTR p)
Definition: set.c:259
#define TRACE(s)
Definition: solgame.cpp:4
Definition: lex.c:810
struct _cc_var_t * next
Definition: lex.c:812
ccval_t val
Definition: lex.c:811
WCHAR name[0]
Definition: lex.c:814
unsigned name_len
Definition: lex.c:813
Definition: jsstr.h:39
Definition: parser.h:25
Definition: name.c:39
#define max(a, b)
Definition: svc.c:63
int64_t LONGLONG
Definition: typedefs.h:68
double DOUBLE
Definition: typedefs.h:70
int ret
_In_ ULONG _In_ ULONG_PTR ident
Definition: winddi.h:3994
__wchar_t WCHAR
Definition: xmlstorage.h:180