Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / BIFS codec sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : /*
27 : script encoder is IM1 version
28 : */
29 :
30 : #include "script.h"
31 :
32 : #include <gpac/internal/scenegraph_dev.h>
33 :
34 : #if !defined(GPAC_DISABLE_BIFS) && !defined(GPAC_DISABLE_BIFS_ENC) && defined(GPAC_HAS_QJS)
35 :
36 : typedef struct
37 : {
38 : GF_Node *script;
39 : GF_BifsEncoder *codec;
40 : GF_BitStream *bs;
41 : GF_List *identifiers;
42 : GF_Err err;
43 :
44 : char *cur_buf;
45 : char token[500];
46 : u32 token_code;
47 :
48 : u32 cur_line;
49 :
50 : Bool emul;
51 :
52 : char expr_toks[500];
53 : u32 expr_toks_len;
54 : GF_List *id_buf;
55 : } ScriptEnc;
56 :
57 :
58 : #define SFE_WRITE_INT(sc_enc, val, nbBits, str1, str2) \
59 : if (!sc_enc->emul) GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, val, nbBits, str1, str2); \
60 :
61 :
62 20 : static GF_Err EncScriptFields(ScriptEnc *sc_enc)
63 : {
64 : u32 nbFields, nbBits, eType, nbBitsProto, i;
65 : Bool use_list;
66 : GF_Err e;
67 : GF_FieldInfo info;
68 :
69 20 : nbFields = gf_node_get_num_fields_in_mode(sc_enc->script, GF_SG_FIELD_CODING_ALL) - 3;
70 : use_list = GF_TRUE;
71 20 : nbBits = gf_get_bit_size(nbFields);
72 20 : if (nbFields+1 > 4 + gf_get_bit_size(nbFields)) use_list = GF_FALSE;
73 20 : if (!nbFields) {
74 0 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "Script::isList", NULL);
75 0 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "end", NULL);
76 : return GF_OK;
77 : }
78 20 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, use_list ? 1 : 0, 1, "Script::isList", NULL);
79 20 : if (!use_list) {
80 0 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, nbBits, 4, "nbBits", NULL);
81 0 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, nbFields, nbBits, "count", NULL);
82 : }
83 :
84 : nbBitsProto = 0;
85 20 : if (sc_enc->codec->encoding_proto) nbBitsProto = gf_get_bit_size(gf_sg_proto_get_field_count(sc_enc->codec->encoding_proto) - 1);
86 :
87 60 : for (i=0; i<nbFields; i++) {
88 40 : if (use_list) GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "end", NULL);
89 :
90 40 : gf_node_get_field(sc_enc->script, i+3, &info);
91 40 : switch (info.eventType) {
92 : case GF_SG_EVENT_IN:
93 : eType = GF_SG_SCRIPT_TYPE_EVENT_IN;
94 : break;
95 0 : case GF_SG_EVENT_OUT:
96 : eType = GF_SG_SCRIPT_TYPE_EVENT_OUT;
97 0 : break;
98 20 : default:
99 : eType = GF_SG_SCRIPT_TYPE_FIELD;
100 20 : break;
101 : }
102 40 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, eType, 2, "eventType", NULL);
103 40 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, info.fieldType, 6, "fieldType", NULL);
104 40 : gf_bifs_enc_name(sc_enc->codec, sc_enc->bs, (char *) info.name);
105 : /*this is an identifier for script*/
106 40 : gf_list_add(sc_enc->identifiers, gf_strdup(info.name));
107 :
108 40 : if (sc_enc->codec->encoding_proto) {
109 0 : GF_Route *isedField = gf_bifs_enc_is_field_ised(sc_enc->codec, sc_enc->script, i+3);
110 0 : if (isedField) {
111 0 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "isedField", NULL);
112 :
113 0 : if (isedField->ToNode == sc_enc->script) {
114 0 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, isedField->FromField.fieldIndex, nbBitsProto, "protoField", NULL);
115 : } else {
116 0 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, isedField->ToField.fieldIndex, nbBitsProto, "protoField", NULL);
117 : }
118 0 : continue;
119 : }
120 0 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "isedField", NULL);
121 : }
122 : /*default value*/
123 40 : if (eType == GF_SG_SCRIPT_TYPE_FIELD) {
124 20 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, (info.far_ptr) ? 1 : 0, 1, "hasInitialValue", NULL);
125 20 : if (info.far_ptr) {
126 20 : e = gf_bifs_enc_field(sc_enc->codec, sc_enc->bs, sc_enc->script, &info);
127 20 : if (e) return e;
128 : }
129 : }
130 : }
131 20 : if (use_list) GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "end", NULL);
132 : return GF_OK;
133 : }
134 :
135 :
136 :
137 : enum
138 : {
139 : TOK_FUNCTION,
140 : TOK_IF,
141 : TOK_ELSE,
142 : TOK_FOR,
143 : TOK_WHILE,
144 : TOK_RETURN,
145 : TOK_BREAK,
146 : TOK_CONTINUE,
147 : TOK_NEW,
148 : TOK_SWITCH,
149 : TOK_CASE,
150 : TOK_DEFAULT,
151 : TOK_VAR,
152 : NUMBER_OF_KEYWORD,
153 : TOK_LEFT_BRACE = NUMBER_OF_KEYWORD,
154 : TOK_RIGHT_BRACE,
155 : TOK_LEFT_CURVE,
156 : TOK_RIGHT_CURVE,
157 : TOK_LEFT_BRACKET,
158 : TOK_RIGHT_BRACKET,
159 : TOK_PERIOD,
160 : TOK_NOT,
161 : TOK_ONESCOMP,
162 : TOK_NEGATIVE,
163 : TOK_INCREMENT,
164 : TOK_DECREMENT,
165 : TOK_MULTIPLY,
166 : TOK_DIVIDE,
167 : TOK_MOD,
168 : TOK_PLUS,
169 : TOK_MINUS,
170 : TOK_LSHIFT,
171 : TOK_RSHIFT,
172 : TOK_RSHIFTFILL,
173 : TOK_LT,
174 : TOK_LE,
175 : TOK_GT,
176 : TOK_GE,
177 : TOK_EQ,
178 : TOK_NE,
179 : TOK_AND,
180 : TOK_XOR,
181 : TOK_OR,
182 : TOK_LAND,
183 : TOK_LOR,
184 : TOK_CONDTEST,
185 : TOK_ASSIGN,
186 : TOK_PLUSEQ,
187 : TOK_MINUSEQ,
188 : TOK_MULTIPLYEQ,
189 : TOK_DIVIDEEQ,
190 : TOK_MODEQ,
191 : TOK_LSHIFTEQ,
192 : TOK_RSHIFTEQ,
193 : TOK_RSHIFTFILLEQ,
194 : TOK_ANDEQ,
195 : TOK_XOREQ,
196 : TOK_OREQ,
197 : TOK_COMMA,
198 : TOK_SEMICOLON,
199 : TOK_CONDSEP,
200 : TOK_IDENTIFIER,
201 : TOK_STRING,
202 : TOK_NUMBER,
203 : TOK_EOF,
204 : TOK_BOOLEAN
205 : };
206 :
207 : const char *tok_names[] =
208 : {
209 : "function",
210 : "if",
211 : "else",
212 : "for",
213 : "while",
214 : "return",
215 : "break",
216 : "continue",
217 : "new",
218 : "switch",
219 : "case",
220 : "default",
221 : "var",
222 : "{",
223 : "}",
224 : "(",
225 : ")",
226 : "[",
227 : "]",
228 : ".",
229 : "!",
230 : "~",
231 : "-",
232 : "++",
233 : "--",
234 : "*",
235 : "/",
236 : "%",
237 : "+",
238 : "-",
239 : "<<",
240 : ">>",
241 : ">>>",
242 : "<",
243 : "<=",
244 : ">",
245 : ">=",
246 : "==",
247 : "!=",
248 : "&",
249 : "^",
250 : "|",
251 : "&&",
252 : "||",
253 : "?",
254 : "=",
255 : "+=",
256 : "-=",
257 : "*=",
258 : "/=",
259 : "%=",
260 : "<<=",
261 : ">>=",
262 : ">>>=",
263 : "&=",
264 : "^=",
265 : "|=",
266 : ",",
267 : ";",
268 : ":",
269 : "identifier",
270 : "string",
271 : "number",
272 : "boolean",
273 : "end of script"
274 : };
275 :
276 : const char* sc_keywords [] =
277 : {
278 : "function",
279 : "if",
280 : "else",
281 : "for",
282 : "while",
283 : "return",
284 : "break",
285 : "continue",
286 : "new",
287 : "switch",
288 : "case",
289 : "default",
290 : "var"
291 : };
292 :
293 827 : Bool SFE_GetNumber(ScriptEnc *sc_enc)
294 : {
295 : u32 i = 0;
296 : Bool exp = GF_FALSE;
297 2542 : while ( isdigit(sc_enc->cur_buf[i])
298 834 : || (toupper(sc_enc->cur_buf[i])=='X')
299 834 : || ((toupper(sc_enc->cur_buf[i]) >='A') && (toupper(sc_enc->cur_buf[i])<='F'))
300 834 : || (sc_enc->cur_buf[i]=='.')
301 827 : || (tolower(sc_enc->cur_buf[i])=='e')
302 827 : || (exp && (sc_enc->cur_buf[i] == '-'))
303 : ) {
304 888 : sc_enc->token[i] = sc_enc->cur_buf[i];
305 888 : if (tolower(sc_enc->cur_buf[i])=='e') exp = GF_TRUE;
306 888 : i++;
307 888 : if (!sc_enc->cur_buf[i]) {
308 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Invalid number syntax (%s)\n", sc_enc->cur_buf));
309 0 : sc_enc->err = GF_BAD_PARAM;
310 0 : return GF_FALSE;
311 : }
312 : }
313 827 : sc_enc->token[i] = 0;
314 827 : sc_enc->cur_buf += i;
315 827 : sc_enc->token_code = TOK_NUMBER;
316 827 : return GF_TRUE;
317 : }
318 :
319 7928 : Bool SFE_NextToken(ScriptEnc *sc_enc)
320 : {
321 : u32 i;
322 7928 : if (sc_enc->err) return GF_FALSE;
323 9788 : while (strchr(" \t\r\n", sc_enc->cur_buf[0])) {
324 1860 : if (sc_enc->cur_buf[0]=='\n') sc_enc->cur_line ++;
325 1860 : sc_enc->cur_buf++;
326 : }
327 7928 : if ((sc_enc->cur_buf[0] == '/') && (sc_enc->cur_buf[1] == '*')) {
328 0 : sc_enc->cur_buf += 2;
329 0 : while ((sc_enc->cur_buf[0] != '*') || (sc_enc->cur_buf[1] != '/')) {
330 0 : sc_enc->cur_buf++;
331 0 : if (!sc_enc->cur_buf[0] || !sc_enc->cur_buf[1]) {
332 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: cannot find closing comment */\n"));
333 0 : sc_enc->err = GF_BAD_PARAM;
334 0 : return GF_FALSE;
335 : }
336 : }
337 0 : sc_enc->cur_buf+=2;
338 0 : return SFE_NextToken(sc_enc);
339 : }
340 : i = 0;
341 : /*get a name*/
342 7928 : if (isalpha(sc_enc->cur_buf[i]) || (sc_enc->cur_buf[i]=='_')) {
343 15122 : while (isalnum(sc_enc->cur_buf[i]) || (sc_enc->cur_buf[i]=='_')) {
344 12435 : sc_enc->token[i] = sc_enc->cur_buf[i];
345 12435 : i++;
346 : }
347 2687 : sc_enc->token[i] = 0;
348 2687 : sc_enc->cur_buf += i;
349 2687 : sc_enc->token_code = TOK_IDENTIFIER;
350 : /*check keyword*/
351 30718 : for (i=0; i<NUMBER_OF_KEYWORD; i++) {
352 28771 : if (!strcmp(sc_enc->token, sc_keywords[i])) {
353 740 : sc_enc->token_code = i;
354 740 : return GF_TRUE;
355 : }
356 : }
357 1947 : if (!stricmp(sc_enc->token, "TRUE") || !stricmp(sc_enc->token, "FALSE") ) {
358 20 : sc_enc->token_code = TOK_BOOLEAN;
359 : }
360 : return GF_TRUE;
361 : }
362 : /*get a number*/
363 5241 : if (isdigit(sc_enc->cur_buf[i])) return SFE_GetNumber(sc_enc);
364 : /*get a string*/
365 4414 : if ((sc_enc->cur_buf[i]=='\'') || (sc_enc->cur_buf[i]=='\"')
366 4354 : || ((sc_enc->cur_buf[i]=='\\') && (sc_enc->cur_buf[i+1]=='\"'))
367 : ) {
368 : char end;
369 : Bool skip_last = GF_FALSE;
370 : end = sc_enc->cur_buf[i];
371 60 : if (sc_enc->cur_buf[i]=='\\') {
372 : skip_last = GF_TRUE;
373 0 : sc_enc->cur_buf++;
374 : }
375 340 : while (sc_enc->cur_buf[i+1] != end) {
376 280 : sc_enc->token[i] = sc_enc->cur_buf[i+1];
377 : i++;
378 : }
379 60 : sc_enc->token[i] = 0;
380 60 : sc_enc->cur_buf += i+2;
381 60 : if (skip_last) sc_enc->cur_buf++;
382 60 : sc_enc->token_code = TOK_STRING;
383 60 : return GF_TRUE;
384 : }
385 : /*all other codes*/
386 4354 : switch (sc_enc->cur_buf[i]) {
387 80 : case '.':
388 80 : if (isdigit(sc_enc->cur_buf[i+1])) {
389 0 : SFE_GetNumber(sc_enc);
390 0 : return GF_TRUE;
391 : } else {
392 80 : sc_enc->token_code = TOK_PERIOD;
393 : }
394 80 : break;
395 60 : case '!':
396 60 : if (sc_enc->cur_buf[i+1] == '=') {
397 20 : sc_enc->token_code = TOK_NE;
398 20 : sc_enc->cur_buf ++;
399 : } else {
400 40 : sc_enc->token_code = TOK_NOT;
401 : }
402 : break;
403 587 : case '=':
404 587 : if (sc_enc->cur_buf[i+1]=='=') {
405 40 : if (sc_enc->cur_buf[i+2]=='=') {
406 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[BIFSEnc] JavaScript token '===' not supported by standard\n"));
407 0 : sc_enc->err = GF_NOT_SUPPORTED;
408 0 : return GF_FALSE;
409 : }
410 40 : sc_enc->token_code = TOK_EQ;
411 40 : sc_enc->cur_buf ++;
412 : } else {
413 547 : sc_enc->token_code = TOK_ASSIGN;
414 : }
415 : break;
416 100 : case '+':
417 100 : if(sc_enc->cur_buf[i+1]=='=') {
418 20 : sc_enc->token_code = TOK_PLUSEQ;
419 20 : sc_enc->cur_buf ++;
420 80 : } else if(sc_enc->cur_buf[i+1]=='+') {
421 60 : sc_enc->token_code = TOK_INCREMENT;
422 60 : sc_enc->cur_buf++;
423 : } else {
424 20 : sc_enc->token_code = TOK_PLUS;
425 : }
426 : break;
427 100 : case '-':
428 100 : if(sc_enc->cur_buf[i+1]=='=') {
429 20 : sc_enc->token_code = TOK_MINUSEQ;
430 20 : sc_enc->cur_buf++;
431 80 : } else if(sc_enc->cur_buf[i+1] == '-') {
432 40 : sc_enc->token_code = TOK_DECREMENT;
433 40 : sc_enc->cur_buf++;
434 : } else {
435 40 : sc_enc->token_code = TOK_MINUS;
436 : }
437 : break;
438 40 : case '*':
439 40 : if(sc_enc->cur_buf[i+1]=='=') {
440 20 : sc_enc->token_code = TOK_MULTIPLYEQ;
441 20 : sc_enc->cur_buf++;
442 : } else {
443 20 : sc_enc->token_code = TOK_MULTIPLY;
444 : }
445 : break;
446 40 : case '/':
447 40 : if(sc_enc->cur_buf[i+1]=='=') {
448 20 : sc_enc->token_code = TOK_DIVIDEEQ;
449 20 : sc_enc->cur_buf++;
450 : } else {
451 20 : sc_enc->token_code = TOK_DIVIDE;
452 : }
453 : break;
454 60 : case '%':
455 60 : if(sc_enc->cur_buf[i+1]=='=') {
456 40 : sc_enc->token_code = TOK_MODEQ;
457 40 : sc_enc->cur_buf++;
458 : } else {
459 20 : sc_enc->token_code = TOK_MOD;
460 : }
461 : break;
462 60 : case '&':
463 60 : if(sc_enc->cur_buf[i+1]=='=') {
464 20 : sc_enc->token_code = TOK_ANDEQ;
465 20 : sc_enc->cur_buf++;
466 40 : } else if(sc_enc->cur_buf[i+1]=='&') {
467 20 : sc_enc->token_code = TOK_LAND;
468 20 : sc_enc->cur_buf++;
469 : } else {
470 20 : sc_enc->token_code = TOK_AND;
471 : }
472 : break;
473 60 : case '|':
474 60 : if(sc_enc->cur_buf[i+1]=='=') {
475 20 : sc_enc->token_code = TOK_OREQ;
476 20 : sc_enc->cur_buf++;
477 40 : } else if(sc_enc->cur_buf[i+1]=='|') {
478 20 : sc_enc->token_code = TOK_LOR;
479 20 : sc_enc->cur_buf++;
480 : } else {
481 20 : sc_enc->token_code = TOK_OR;
482 : }
483 : break;
484 40 : case '^':
485 40 : if(sc_enc->cur_buf[i+1]=='=') {
486 20 : sc_enc->token_code = TOK_XOREQ;
487 20 : sc_enc->cur_buf++;
488 : } else {
489 20 : sc_enc->token_code = TOK_XOR;
490 : }
491 : break;
492 100 : case '<':
493 100 : if (sc_enc->cur_buf[i+1]=='<') {
494 40 : if(sc_enc->cur_buf[i+2]=='=') {
495 20 : sc_enc->token_code = TOK_LSHIFTEQ;
496 20 : sc_enc->cur_buf += 1;
497 : } else {
498 20 : sc_enc->token_code = TOK_LSHIFT;
499 : }
500 40 : sc_enc->cur_buf += 1;
501 60 : } else if(sc_enc->cur_buf[i+1]=='=') {
502 20 : sc_enc->token_code = TOK_LE;
503 20 : sc_enc->cur_buf ++;
504 : } else {
505 40 : sc_enc->token_code = TOK_LT;
506 : }
507 : break;
508 120 : case '>':
509 120 : if (sc_enc->cur_buf[i+1]=='>') {
510 80 : if (sc_enc->cur_buf[i+2]=='=') {
511 20 : sc_enc->token_code = TOK_RSHIFTEQ;
512 20 : sc_enc->cur_buf ++;
513 60 : } else if(sc_enc->cur_buf[i+2]=='>') {
514 40 : if(sc_enc->cur_buf[i+3]=='=') {
515 20 : sc_enc->token_code = TOK_RSHIFTFILLEQ;
516 20 : sc_enc->cur_buf ++;
517 : } else {
518 20 : sc_enc->token_code = TOK_RSHIFTFILL;
519 : }
520 40 : sc_enc->cur_buf ++;
521 : } else {
522 20 : sc_enc->token_code = TOK_RSHIFT;
523 : }
524 80 : sc_enc->cur_buf ++;
525 40 : } else if (sc_enc->cur_buf[i+1]=='=') {
526 20 : sc_enc->token_code = TOK_GE;
527 20 : sc_enc->cur_buf ++;
528 : } else {
529 20 : sc_enc->token_code = TOK_GT;
530 : }
531 : break;
532 60 : case '?':
533 60 : sc_enc->token_code = TOK_CONDTEST;
534 60 : break;
535 120 : case ':':
536 120 : sc_enc->token_code = TOK_CONDSEP;
537 120 : break;
538 20 : case '~':
539 20 : sc_enc->token_code = TOK_ONESCOMP;
540 20 : break;
541 40 : case ',':
542 40 : sc_enc->token_code = TOK_COMMA;
543 40 : break;
544 1067 : case ';':
545 1067 : sc_enc->token_code = TOK_SEMICOLON;
546 1067 : break;
547 340 : case '{':
548 340 : sc_enc->token_code = TOK_LEFT_BRACE;
549 340 : break;
550 340 : case '}':
551 340 : sc_enc->token_code = TOK_RIGHT_BRACE;
552 340 : break;
553 420 : case '(':
554 420 : sc_enc->token_code = TOK_LEFT_CURVE;
555 420 : break;
556 420 : case ')':
557 420 : sc_enc->token_code = TOK_RIGHT_CURVE;
558 420 : break;
559 40 : case '[':
560 40 : sc_enc->token_code = TOK_LEFT_BRACKET;
561 40 : break;
562 40 : case ']':
563 40 : sc_enc->token_code = TOK_RIGHT_BRACKET;
564 40 : break;
565 0 : default:
566 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Unrecognized symbol %c\n", sc_enc->cur_buf[i]));
567 0 : sc_enc->err = GF_BAD_PARAM;
568 0 : return GF_FALSE;
569 : }
570 4354 : sc_enc->cur_buf ++;
571 4354 : return GF_TRUE;
572 : }
573 :
574 860 : Bool SFE_CheckToken(ScriptEnc *sc_enc, u32 token)
575 : {
576 860 : if (sc_enc->token_code != token) {
577 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Bad token (expecting \"%s\" got \"%s\")\n", tok_names[token] , tok_names[sc_enc->token_code]));
578 : return GF_FALSE;
579 : }
580 : return GF_TRUE;
581 : }
582 :
583 1927 : void SFE_PutIdentifier(ScriptEnc *sc_enc, char *id)
584 : {
585 : u32 i;
586 : u32 nbBits, length;
587 : char *str;
588 :
589 3634 : if (sc_enc->emul) return;
590 :
591 1927 : i=0;
592 15356 : while ((str = (char *)gf_list_enum(sc_enc->identifiers, &i))) {
593 13209 : if (strcmp(str, id)) continue;
594 :
595 : nbBits = 0;
596 1707 : length = gf_list_count(sc_enc->identifiers) - 1;
597 8635 : while (length > 0) {
598 5221 : length >>= 1;
599 5221 : nbBits ++;
600 : }
601 1707 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "received", str);
602 1707 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, i-1, nbBits, "identifierCode", str);
603 : return;
604 : }
605 220 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "received", id);
606 220 : gf_list_add(sc_enc->identifiers, gf_strdup(id));
607 220 : gf_bifs_enc_name(sc_enc->codec, sc_enc->bs, id);
608 : }
609 :
610 :
611 60 : void SFE_Arguments(ScriptEnc *sc_enc)
612 : {
613 : while (1) {
614 120 : if (!SFE_NextToken(sc_enc)) return;
615 120 : if (sc_enc->token_code == TOK_RIGHT_CURVE) break;
616 60 : else if (sc_enc->token_code == TOK_COMMA) continue;
617 40 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "hasArgument", NULL);
618 40 : SFE_PutIdentifier(sc_enc, sc_enc->token);
619 : }
620 60 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "hasArgument", NULL);
621 : }
622 :
623 : void SFE_StatementBlock(ScriptEnc *sc_enc);
624 : void SFE_Statement(ScriptEnc *sc_enc);
625 :
626 780 : void SFE_PutInteger(ScriptEnc *sc_enc, char *str)
627 : {
628 : u32 nbBits, val = 0;
629 780 : if (sc_enc->emul) return;
630 780 : if ((str[0]=='0') && (str[1]=='x' || str[1]=='X')) {
631 0 : val = (u32) strtoul(sc_enc->token, (char **) NULL, 16);
632 780 : } else if (str[0]=='0' && isdigit(str[1])) {
633 0 : val = (u32) strtoul(str, (char **) NULL, 8);
634 780 : } else if (isdigit(str[0])) {
635 780 : val = (u32) strtoul(str, (char **) NULL, 10);
636 : } else {
637 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: %s is not an integer\n", str));
638 0 : sc_enc->err = GF_BAD_PARAM;
639 0 : return;
640 : }
641 780 : nbBits = gf_get_bit_size(val);
642 780 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, nbBits, 5, "nbBitsInteger", NULL);
643 780 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, val, nbBits, "value", sc_enc->token);
644 : }
645 :
646 1227 : u32 SFE_LoadExpression(ScriptEnc *sc_enc, u32 *expr_sep)
647 : {
648 : Bool is_var = GF_FALSE;
649 : u32 close_code, open_code;
650 : u32 count = 0;
651 : u32 nbExpr = 1;
652 : u32 nbIndir = 0;
653 1227 : expr_sep[0] = 0;
654 :
655 1227 : sc_enc->expr_toks_len = 0;
656 :
657 6775 : while ( (sc_enc->token_code != TOK_SEMICOLON) && (sc_enc->token_code != TOK_RIGHT_CURVE) ) {
658 4341 : switch (sc_enc->token_code) {
659 60 : case TOK_CONDTEST:
660 60 : nbIndir ++;
661 60 : break;
662 60 : case TOK_CONDSEP:
663 120 : if (nbIndir > 0) nbIndir--;
664 : /*'case'*/
665 : else {
666 : goto break_loop;
667 : }
668 60 : break;
669 2574 : case TOK_IDENTIFIER:
670 : case TOK_NUMBER:
671 : case TOK_STRING:
672 : case TOK_BOOLEAN:
673 2574 : gf_list_add(sc_enc->id_buf, gf_strdup(sc_enc->token));
674 2574 : break;
675 : case TOK_FUNCTION:
676 : goto break_loop;
677 : }
678 :
679 4321 : if (sc_enc->token_code==TOK_VAR) is_var = GF_TRUE;
680 4301 : if (!is_var || (sc_enc->token_code!=TOK_COMMA)) {
681 4321 : sc_enc->expr_toks[sc_enc->expr_toks_len] = sc_enc->token_code;
682 4321 : sc_enc->expr_toks_len++;
683 : }
684 :
685 : open_code = sc_enc->token_code;
686 : close_code = 0;
687 4321 : if (sc_enc->token_code == TOK_LEFT_CURVE) close_code = TOK_RIGHT_CURVE;
688 4221 : else if (sc_enc->token_code == TOK_LEFT_BRACKET) close_code = TOK_RIGHT_BRACKET;
689 4181 : else if (sc_enc->token_code == TOK_LEFT_BRACE) close_code = TOK_RIGHT_BRACE;
690 :
691 : /*other expr*/
692 4321 : if ((sc_enc->token_code == TOK_COMMA) && (sc_enc->expr_toks[0] != TOK_VAR) ) {
693 0 : expr_sep[nbExpr++] = sc_enc->expr_toks_len - 1;
694 : }
695 : /*sub-expr*/
696 4321 : else if (close_code) {
697 140 : count++;
698 : do {
699 320 : SFE_NextToken(sc_enc);
700 320 : if ((sc_enc->token_code == TOK_IDENTIFIER) || (sc_enc->token_code == TOK_NUMBER)
701 200 : || (sc_enc->token_code == TOK_STRING) || (sc_enc->token_code == TOK_BOOLEAN) ) {
702 140 : gf_list_add(sc_enc->id_buf, gf_strdup(sc_enc->token));
703 : }
704 320 : sc_enc->expr_toks[sc_enc->expr_toks_len] = sc_enc->token_code;
705 320 : sc_enc->expr_toks_len++;
706 320 : if (sc_enc->token_code == open_code) count++;
707 320 : else if (sc_enc->token_code == close_code) count--;
708 320 : } while ( (sc_enc->token_code != close_code) || count);
709 : }
710 4321 : SFE_NextToken(sc_enc);
711 :
712 4321 : if (sc_enc->err) break;
713 : }
714 :
715 1207 : break_loop:
716 1227 : if (sc_enc->err) {
717 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: end of compoundExpression not found\n"));
718 : return 0;
719 : }
720 1227 : expr_sep[nbExpr] = sc_enc->expr_toks_len;
721 1227 : if ((sc_enc->token_code == TOK_IDENTIFIER) || (sc_enc->token_code == TOK_NUMBER)
722 1227 : || (sc_enc->token_code == TOK_STRING) || (sc_enc->token_code == TOK_BOOLEAN) ) {
723 0 : gf_list_add(sc_enc->id_buf, gf_strdup(sc_enc->token));
724 : }
725 :
726 1227 : if ((sc_enc->token_code != TOK_CONDSEP) && (sc_enc->token_code != TOK_RIGHT_BRACE) && (sc_enc->expr_toks[0] != TOK_VAR)) {
727 1207 : sc_enc->expr_toks[sc_enc->expr_toks_len] = sc_enc->token_code;
728 1207 : sc_enc->expr_toks_len++;
729 : }
730 : return nbExpr;
731 : }
732 :
733 : u32 MoveToToken(ScriptEnc *sc_enc, u32 endTok, u32 cur, u32 end);
734 :
735 100 : u32 SFE_ScanExpression(ScriptEnc *sc_enc, u32 start, u32 end, u32 *expr_sep)
736 : {
737 : u32 curTok;
738 : u32 n = start;
739 : u32 nbExpr = 1;
740 :
741 100 : expr_sep[0] = start;
742 380 : while (n<end) {
743 180 : curTok = sc_enc->expr_toks[n++];
744 180 : if (curTok == TOK_LEFT_CURVE) {
745 0 : n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n-1, end);
746 0 : n++;
747 180 : } else if (curTok == TOK_LEFT_BRACKET) {
748 0 : n = MoveToToken(sc_enc, TOK_RIGHT_BRACKET, n-1, end);
749 0 : n++;
750 180 : } else if (curTok == TOK_COMMA) {
751 20 : expr_sep[nbExpr++] = n-1;
752 : }
753 : }
754 100 : expr_sep[nbExpr] = end;
755 100 : return nbExpr;
756 : }
757 :
758 : u32 SFE_Expression(ScriptEnc *sc_enc, u32 start, u32 end, Bool memberAccess);
759 :
760 1327 : void SFE_CompoundExpression(ScriptEnc *sc_enc, u32 start, u32 end, u32 isPar)
761 : {
762 : u32 nbExp, i;
763 : /*filled by indexes of ',' expressions in the expr_tok buffer*/
764 : u32 expr_sep[MAX_NUM_EXPR];
765 :
766 1327 : if (sc_enc->err) return;
767 :
768 1327 : if (end==0) {
769 : /*load expressions , eg "a ? ((a>b) ? 1 : 0) : 0" */
770 1227 : nbExp = SFE_LoadExpression(sc_enc, expr_sep);
771 : } else {
772 : /*load sub-expression from loaded expression set*/
773 100 : nbExp = SFE_ScanExpression(sc_enc, start, end, expr_sep);
774 : }
775 :
776 1327 : SFE_Expression(sc_enc, expr_sep[0], expr_sep[1], GF_FALSE);
777 2674 : for (i=1; i<nbExp; i++) {
778 20 : SFE_WRITE_INT(sc_enc, 1, 1, isPar ? "hasParam" : "hasExpression", NULL);
779 20 : SFE_Expression(sc_enc, expr_sep[i]+1, expr_sep[i+1], GF_FALSE);
780 : }
781 1327 : SFE_WRITE_INT(sc_enc, 0, 1, isPar ? "hasParam" : "hasExpression", NULL);
782 : }
783 :
784 60 : void SFE_OptionalExpression(ScriptEnc *sc_enc)
785 : {
786 60 : if (sc_enc->token_code != TOK_SEMICOLON) {
787 60 : SFE_WRITE_INT(sc_enc, 1, 1, "hasCompoundExpression", NULL);
788 60 : SFE_CompoundExpression(sc_enc, 0, 0, 0);
789 : } else {
790 0 : SFE_WRITE_INT(sc_enc, 0, 1, "hasCompoundExpression", NULL);
791 : }
792 60 : }
793 :
794 200 : void SFE_IfStatement(ScriptEnc *sc_enc)
795 : {
796 : char *buf_bck;
797 : u32 tok_bck;
798 200 : SFE_NextToken(sc_enc);
799 200 : SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
800 200 : SFE_NextToken(sc_enc);
801 200 : SFE_CompoundExpression(sc_enc, 0, 0, 0);
802 200 : SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE);
803 200 : SFE_StatementBlock(sc_enc);
804 :
805 200 : buf_bck = sc_enc->cur_buf;
806 200 : tok_bck = sc_enc->token_code;
807 200 : SFE_NextToken(sc_enc);
808 200 : if (sc_enc->token_code == TOK_ELSE) {
809 20 : SFE_WRITE_INT(sc_enc, 1, 1, "hasELSEStatement", NULL);
810 20 : SFE_StatementBlock(sc_enc);
811 : } else {
812 180 : SFE_WRITE_INT(sc_enc, 0, 1, "hasELSEStatement", NULL);
813 180 : sc_enc->cur_buf = buf_bck;
814 180 : sc_enc->token_code = tok_bck;
815 : }
816 200 : }
817 :
818 20 : void SFE_ForStatement(ScriptEnc *sc_enc)
819 : {
820 20 : SFE_NextToken(sc_enc);
821 20 : SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
822 :
823 20 : SFE_NextToken(sc_enc);
824 20 : SFE_OptionalExpression(sc_enc);
825 20 : SFE_CheckToken(sc_enc, TOK_SEMICOLON);
826 :
827 20 : SFE_NextToken(sc_enc);
828 20 : SFE_OptionalExpression(sc_enc);
829 20 : SFE_CheckToken(sc_enc, TOK_SEMICOLON);
830 :
831 20 : SFE_NextToken(sc_enc);
832 20 : SFE_OptionalExpression(sc_enc);
833 20 : SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE);
834 :
835 20 : SFE_StatementBlock(sc_enc);
836 20 : }
837 :
838 20 : void SFE_WhileStatement(ScriptEnc *sc_enc)
839 : {
840 20 : SFE_NextToken(sc_enc);
841 20 : SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
842 20 : SFE_NextToken(sc_enc);
843 20 : SFE_CompoundExpression(sc_enc, 0, 0, 0);
844 20 : SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE);
845 :
846 20 : SFE_StatementBlock(sc_enc);
847 20 : }
848 :
849 40 : void SFE_ReturnStatement(ScriptEnc *sc_enc)
850 : {
851 40 : SFE_NextToken(sc_enc);
852 40 : if (sc_enc->token_code != TOK_SEMICOLON) {
853 0 : SFE_WRITE_INT(sc_enc, 1, 1, "returnValue", NULL);
854 0 : SFE_CompoundExpression(sc_enc, 0, 0, 0);
855 : } else {
856 40 : SFE_WRITE_INT(sc_enc, 0, 1, "returnValue", NULL);
857 : }
858 40 : }
859 :
860 60 : void SFE_CaseBlock(ScriptEnc *sc_enc)
861 : {
862 60 : SFE_WRITE_INT(sc_enc, 1, 1, "isCompoundStatement", NULL);
863 60 : SFE_NextToken(sc_enc);
864 60 : if (sc_enc->token_code == TOK_LEFT_BRACE) {
865 0 : SFE_NextToken(sc_enc);
866 0 : while (sc_enc->token_code != TOK_RIGHT_BRACE) {
867 0 : SFE_WRITE_INT(sc_enc, 1, 1, "hasStatement", NULL);
868 0 : SFE_Statement(sc_enc);
869 0 : SFE_NextToken(sc_enc);
870 : }
871 0 : SFE_NextToken(sc_enc);
872 : }
873 120 : while ((sc_enc->token_code != TOK_CASE) && (sc_enc->token_code != TOK_DEFAULT) && (sc_enc->token_code != TOK_RIGHT_BRACE)) {
874 60 : SFE_WRITE_INT(sc_enc, 1, 1, "hasStatement", NULL);
875 60 : SFE_Statement(sc_enc);
876 60 : SFE_NextToken(sc_enc);
877 : }
878 60 : SFE_WRITE_INT(sc_enc, 0, 1, "hasStatement", NULL);
879 60 : }
880 :
881 40 : u32 SFE_PutCaseInteger(ScriptEnc *sc_enc, char *str, u32 nbBits)
882 : {
883 : u32 val = 0;
884 40 : if ((str[0]=='0') && (str[1]=='x' || str[1]=='X')) {
885 0 : val = (u32) strtoul(sc_enc->token, (char **) NULL, 16);
886 40 : } else if (str[0]=='0' && isdigit(str[1])) {
887 0 : val = (u32) strtoul(str, (char **) NULL, 8);
888 40 : } else if (isdigit(str[0])) {
889 40 : val = (u32) strtoul(str, (char **) NULL, 10);
890 : } else {
891 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: %s is not an integer\n", str));
892 0 : sc_enc->err = GF_BAD_PARAM;
893 0 : return 0;
894 : }
895 40 : if (!sc_enc->emul) {
896 20 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, val, nbBits, "value", sc_enc->token);
897 : } else {
898 20 : nbBits = gf_get_bit_size(val);
899 : }
900 : return nbBits;
901 : }
902 :
903 20 : void SFE_SwitchStatement(ScriptEnc *sc_enc)
904 : {
905 : u32 nbBits, maxBits = 0;
906 : Bool prev_emu;
907 : char *buf_bck;
908 : u32 tok_bck;
909 :
910 20 : SFE_NextToken(sc_enc);
911 20 : SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
912 :
913 20 : SFE_NextToken(sc_enc);
914 20 : SFE_CompoundExpression(sc_enc, 0, 0, 0);
915 20 : SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE);
916 :
917 20 : SFE_NextToken(sc_enc);
918 20 : SFE_CheckToken(sc_enc, TOK_LEFT_BRACE);
919 :
920 : /*first pass in emul*/
921 20 : buf_bck = sc_enc->cur_buf;
922 20 : tok_bck = sc_enc->token_code;
923 20 : prev_emu = sc_enc->emul;
924 20 : sc_enc->emul = GF_TRUE;
925 :
926 20 : SFE_NextToken(sc_enc);
927 60 : while (sc_enc->token_code == TOK_CASE) {
928 20 : SFE_NextToken(sc_enc);
929 20 : SFE_CheckToken(sc_enc, TOK_NUMBER);
930 20 : nbBits = SFE_PutCaseInteger(sc_enc, sc_enc->token, 0);
931 20 : if (maxBits<nbBits) maxBits = nbBits;
932 :
933 20 : SFE_NextToken(sc_enc);
934 20 : SFE_CheckToken(sc_enc, TOK_CONDSEP);
935 :
936 20 : SFE_CaseBlock(sc_enc);
937 20 : SFE_WRITE_INT(sc_enc, (sc_enc->token_code == TOK_CASE) ? 1 : 0, 1, "hasMoreCases", NULL);
938 : }
939 :
940 : /*second pass in parent mode*/
941 20 : sc_enc->cur_buf = buf_bck;
942 20 : sc_enc->token_code = tok_bck;
943 20 : sc_enc->emul = prev_emu;
944 20 : maxBits ++;
945 20 : SFE_WRITE_INT(sc_enc, maxBits, 5, "caseNbBits", NULL);
946 :
947 20 : SFE_NextToken(sc_enc);
948 60 : while (sc_enc->token_code == TOK_CASE) {
949 20 : SFE_NextToken(sc_enc);
950 20 : SFE_CheckToken(sc_enc, TOK_NUMBER);
951 20 : SFE_PutCaseInteger(sc_enc, sc_enc->token, maxBits);
952 :
953 20 : SFE_NextToken(sc_enc);
954 20 : SFE_CheckToken(sc_enc, TOK_CONDSEP);
955 :
956 20 : SFE_CaseBlock(sc_enc);
957 20 : SFE_WRITE_INT(sc_enc, (sc_enc->token_code == TOK_CASE) ? 1 : 0, 1, "hasMoreCases", NULL);
958 : }
959 :
960 20 : if (sc_enc->token_code == TOK_DEFAULT) {
961 20 : SFE_WRITE_INT(sc_enc, 1, 1, "hasDefault", NULL);
962 20 : SFE_NextToken(sc_enc);
963 20 : SFE_CheckToken(sc_enc, TOK_CONDSEP);
964 20 : SFE_CaseBlock(sc_enc);
965 : } else {
966 0 : SFE_WRITE_INT(sc_enc, 0, 1, "hasDefault", NULL);
967 : }
968 20 : SFE_CheckToken(sc_enc, TOK_RIGHT_BRACE);
969 20 : }
970 :
971 1287 : void SFE_Statement(ScriptEnc *sc_enc)
972 : {
973 1287 : switch (sc_enc->token_code) {
974 200 : case TOK_IF:
975 200 : SFE_WRITE_INT(sc_enc, ST_IF, NUMBITS_STATEMENT, "statementType", "if");
976 200 : SFE_IfStatement(sc_enc);
977 200 : break;
978 20 : case TOK_FOR:
979 20 : SFE_WRITE_INT(sc_enc, ST_FOR, NUMBITS_STATEMENT, "statementType", "for");
980 20 : SFE_ForStatement(sc_enc);
981 20 : break;
982 20 : case TOK_WHILE:
983 20 : SFE_WRITE_INT(sc_enc, ST_WHILE, NUMBITS_STATEMENT, "statementType", "while");
984 20 : SFE_WhileStatement(sc_enc);
985 20 : break;
986 40 : case TOK_RETURN:
987 40 : SFE_WRITE_INT(sc_enc, ST_RETURN, NUMBITS_STATEMENT, "statementType", "return");
988 40 : SFE_ReturnStatement(sc_enc);
989 40 : break;
990 40 : case TOK_BREAK:
991 40 : SFE_WRITE_INT(sc_enc, ST_BREAK, NUMBITS_STATEMENT, "statementType", "break");
992 40 : SFE_NextToken(sc_enc);
993 40 : break;
994 20 : case TOK_CONTINUE:
995 20 : SFE_WRITE_INT(sc_enc, ST_CONTINUE, NUMBITS_STATEMENT, "statementType", "continue");
996 20 : SFE_NextToken(sc_enc);
997 20 : break;
998 20 : case TOK_SWITCH:
999 20 : SFE_WRITE_INT(sc_enc, ST_SWITCH, NUMBITS_STATEMENT, "statementType", "while");
1000 20 : SFE_SwitchStatement(sc_enc);
1001 20 : break;
1002 927 : default:
1003 927 : SFE_WRITE_INT(sc_enc, ST_COMPOUND_EXPR, NUMBITS_STATEMENT, "statementType", "compoundExpr");
1004 927 : SFE_CompoundExpression(sc_enc, 0, 0, 0);
1005 927 : break;
1006 : }
1007 1287 : }
1008 :
1009 320 : void SFE_Statements(ScriptEnc *sc_enc)
1010 : {
1011 : while (1) {
1012 2774 : if (!SFE_NextToken(sc_enc)) return;
1013 1547 : if (sc_enc->token_code == TOK_RIGHT_BRACE) break;
1014 1227 : SFE_WRITE_INT(sc_enc, 1, 1, "hasStatement", NULL);
1015 1227 : SFE_Statement(sc_enc);
1016 : }
1017 320 : SFE_WRITE_INT(sc_enc, 0, 1, "hasStatement", NULL);
1018 : }
1019 :
1020 320 : void SFE_StatementBlock(ScriptEnc *sc_enc)
1021 : {
1022 320 : if (!SFE_NextToken(sc_enc)) return;
1023 320 : if (sc_enc->token_code == TOK_LEFT_BRACE) {
1024 320 : SFE_WRITE_INT(sc_enc, 1, 1, "isCompoundStatement", NULL);
1025 320 : SFE_Statements(sc_enc);
1026 : } else {
1027 0 : SFE_WRITE_INT(sc_enc, 0, 1, "isCompoundStatement", NULL);
1028 0 : SFE_Statement(sc_enc);
1029 : }
1030 : }
1031 40 : void SFE_Function(ScriptEnc *sc_enc)
1032 : {
1033 : char szName[1000];
1034 :
1035 40 : SFE_NextToken(sc_enc);
1036 40 : SFE_CheckToken(sc_enc, TOK_FUNCTION);
1037 :
1038 40 : SFE_NextToken(sc_enc);
1039 40 : SFE_CheckToken(sc_enc, TOK_IDENTIFIER);
1040 40 : strcpy(szName, sc_enc->token);
1041 40 : SFE_PutIdentifier(sc_enc, sc_enc->token);
1042 :
1043 40 : SFE_NextToken(sc_enc);
1044 40 : SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
1045 :
1046 40 : SFE_Arguments(sc_enc);
1047 40 : SFE_StatementBlock(sc_enc);
1048 :
1049 40 : if (sc_enc->err) GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Error while parsing function %s\n", szName));
1050 40 : }
1051 :
1052 :
1053 20 : GF_Err SFScript_Encode(GF_BifsEncoder *codec, SFScript *script_field, GF_BitStream *bs, GF_Node *n)
1054 : {
1055 : char *ptr;
1056 : ScriptEnc sc_enc;
1057 20 : if (gf_node_get_tag(n) != TAG_MPEG4_Script) return GF_NON_COMPLIANT_BITSTREAM;
1058 :
1059 : memset(&sc_enc, 0, sizeof(ScriptEnc));
1060 20 : sc_enc.codec = codec;
1061 20 : sc_enc.script = n;
1062 20 : sc_enc.bs = bs;
1063 20 : sc_enc.identifiers = gf_list_new();
1064 20 : sc_enc.id_buf = gf_list_new();
1065 20 : sc_enc.err = GF_OK;
1066 :
1067 20 : if (codec->is_encoding_command) {
1068 0 : GF_BIFS_WRITE_INT(codec, bs, 1, 1, "Script::isList", NULL);
1069 0 : GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL);
1070 : } else {
1071 20 : EncScriptFields(&sc_enc);
1072 : }
1073 : /*reserevd*/
1074 20 : GF_BIFS_WRITE_INT(codec, bs, 1, 1, "reserved", NULL);
1075 :
1076 20 : if (script_field) {
1077 20 : sc_enc.cur_buf = (char *)script_field->script_text;
1078 0 : } else if (((M_Script*)n)->url.count) {
1079 0 : sc_enc.cur_buf = (char *)((M_Script*)n)->url.vals[0].script_text;
1080 : }
1081 20 : if (sc_enc.cur_buf) {
1082 20 : if (!strnicmp(sc_enc.cur_buf, "javascript:", 11)
1083 0 : || !strnicmp(sc_enc.cur_buf, "vrmlscript:", 11)
1084 0 : || !strnicmp(sc_enc.cur_buf, "ECMAScript:", 11)
1085 : ) {
1086 20 : sc_enc.cur_buf += 11;
1087 0 : } else if (!strnicmp(sc_enc.cur_buf, "mpeg4script:", 12) ) {
1088 0 : sc_enc.cur_buf += 12;
1089 : }
1090 : }
1091 :
1092 : /*encode functions*/
1093 102 : while (sc_enc.cur_buf && sc_enc.cur_buf[0] && (sc_enc.cur_buf[0]!='}')) {
1094 82 : if (strchr("\r\n\t ", sc_enc.cur_buf[0]) ) {
1095 42 : sc_enc.cur_buf++;
1096 42 : continue;
1097 : }
1098 40 : GF_BIFS_WRITE_INT(codec, bs, 1, 1, "hasFunction", NULL);
1099 40 : SFE_Function(&sc_enc);
1100 40 : if (sc_enc.err) break;
1101 : }
1102 20 : GF_BIFS_WRITE_INT(codec, bs, 0, 1, "hasFunction", NULL);
1103 :
1104 : //clean up
1105 280 : while (gf_list_count(sc_enc.identifiers)) {
1106 260 : ptr = (char *)gf_list_get(sc_enc.identifiers, 0);
1107 260 : gf_list_rem(sc_enc.identifiers, 0);
1108 260 : gf_free(ptr);
1109 : }
1110 20 : gf_list_del(sc_enc.identifiers);
1111 : /*in case of error this is needed*/
1112 40 : while (gf_list_count(sc_enc.id_buf)) {
1113 0 : ptr = (char *)gf_list_get(sc_enc.id_buf, 0);
1114 0 : gf_list_rem(sc_enc.id_buf, 0);
1115 0 : gf_free(ptr);
1116 : }
1117 20 : gf_list_del(sc_enc.id_buf);
1118 :
1119 20 : return sc_enc.err;
1120 : }
1121 :
1122 :
1123 7 : void SFE_PutReal(ScriptEnc *sc_enc, char *str)
1124 : {
1125 : u32 i;
1126 7 : size_t length = strlen(str);
1127 35 : for (i=0; i<length; i++) {
1128 28 : s32 c = str[i];
1129 28 : if (c >= '0' && c <= '9')
1130 : {
1131 21 : SFE_WRITE_INT(sc_enc, c-'0', 4, "floatChar", "Digital");
1132 : }
1133 7 : else if (c == '.')
1134 : {
1135 7 : SFE_WRITE_INT(sc_enc, 10, 4, "floatChar", "Decimal Point");
1136 : }
1137 0 : else if (c == 'e' || c == 'E')
1138 : {
1139 0 : SFE_WRITE_INT(sc_enc, 11, 4, "floatChar", "Exponential");
1140 : }
1141 0 : else if (c == '-')
1142 : {
1143 0 : SFE_WRITE_INT(sc_enc, 12, 4, "floatChar", "Sign");
1144 : }
1145 : else {
1146 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: %s is not a real number\n", str));
1147 0 : sc_enc->err = GF_BAD_PARAM;
1148 0 : return;
1149 : }
1150 : }
1151 7 : SFE_WRITE_INT(sc_enc, 15, 4, "floatChar", "End Symbol");
1152 : }
1153 :
1154 787 : void SFE_PutNumber(ScriptEnc *sc_enc, char *str)
1155 : {
1156 787 : if (strpbrk(str,".eE-") == 0) {
1157 780 : SFE_WRITE_INT(sc_enc, 1, 1, "isInteger", "integer");
1158 780 : SFE_PutInteger(sc_enc, str);
1159 : } else {
1160 7 : SFE_WRITE_INT(sc_enc, 0, 1, "isInteger", "real");
1161 7 : SFE_PutReal(sc_enc, str);
1162 : }
1163 787 : }
1164 :
1165 20 : void SFE_PutBoolean(ScriptEnc *sc_enc, char *str)
1166 : {
1167 : u32 v = 1;
1168 20 : if (!stricmp(str, "false") || !strcmp(str, "0")) v = 0;
1169 20 : SFE_WRITE_INT(sc_enc, v, 1, "value", "bolean");
1170 20 : }
1171 :
1172 :
1173 : #define CHECK_TOK(x) \
1174 : if (curTok != x) { \
1175 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Token %s read, %s expected\n", tok_names[curTok], tok_names[x])); \
1176 : sc_enc->err = GF_BAD_PARAM; \
1177 : } \
1178 :
1179 :
1180 0 : u32 TOK_To_ET(u32 tok)
1181 : {
1182 : switch(tok) {
1183 : case TOK_INCREMENT:
1184 : return ET_INCREMENT;
1185 : case TOK_DECREMENT:
1186 : return ET_DECREMENT;
1187 : case TOK_NOT:
1188 : return ET_NOT;
1189 : case TOK_ONESCOMP:
1190 : return ET_ONESCOMP;
1191 : case TOK_MULTIPLY :
1192 : return ET_MULTIPLY;
1193 : case TOK_DIVIDE :
1194 : return ET_DIVIDE;
1195 : case TOK_MOD :
1196 : return ET_MOD;
1197 : case TOK_PLUS :
1198 : return ET_PLUS;
1199 : case TOK_MINUS :
1200 : return ET_MINUS;
1201 : case TOK_LSHIFT :
1202 : return ET_LSHIFT;
1203 : case TOK_RSHIFT :
1204 : return ET_RSHIFT;
1205 : case TOK_RSHIFTFILL :
1206 : return ET_RSHIFTFILL;
1207 : case TOK_LT :
1208 : return ET_LT;
1209 : case TOK_LE :
1210 : return ET_LE;
1211 : case TOK_GT :
1212 : return ET_GT;
1213 : case TOK_GE :
1214 : return ET_GE;
1215 : case TOK_EQ :
1216 : return ET_EQ;
1217 : case TOK_NE :
1218 : return ET_NE;
1219 : case TOK_AND :
1220 : return ET_AND;
1221 : case TOK_XOR :
1222 : return ET_XOR;
1223 : case TOK_OR :
1224 : return ET_OR;
1225 : case TOK_LAND :
1226 : return ET_LAND;
1227 : case TOK_LOR :
1228 : return ET_LOR;
1229 : case TOK_CONDTEST :
1230 : return ET_CONDTEST;
1231 : case TOK_ASSIGN :
1232 : return ET_ASSIGN;
1233 : case TOK_PLUSEQ :
1234 : return ET_PLUSEQ;
1235 : case TOK_MINUSEQ :
1236 : return ET_MINUSEQ;
1237 : case TOK_MULTIPLYEQ :
1238 : return ET_MULTIPLYEQ;
1239 : case TOK_DIVIDEEQ :
1240 : return ET_DIVIDEEQ;
1241 : case TOK_MODEQ :
1242 : return ET_MODEQ;
1243 : case TOK_LSHIFTEQ :
1244 : return ET_LSHIFTEQ;
1245 : case TOK_RSHIFTEQ :
1246 : return ET_RSHIFTEQ;
1247 : case TOK_RSHIFTFILLEQ :
1248 : return ET_RSHIFTFILLEQ;
1249 : case TOK_ANDEQ :
1250 : return ET_ANDEQ;
1251 : case TOK_XOREQ :
1252 : return ET_XOREQ;
1253 : case TOK_OREQ :
1254 : return ET_OREQ;
1255 : case TOK_FUNCTION:
1256 : return ET_FUNCTION_CALL;
1257 : case TOK_VAR:
1258 : return ET_VAR;
1259 : default:
1260 : assert(0);
1261 : return (u32) -1;
1262 : }
1263 : }
1264 :
1265 : #ifndef GPAC_DISABLE_LOG
1266 : static const char *expr_name[] = {
1267 : "ET_CURVED_EXPR",
1268 : "ET_NEGATIVE",
1269 : "ET_NOT",
1270 : "ET_ONESCOMP",
1271 : "ET_INCREMENT",
1272 : "ET_DECREMENT",
1273 : "ET_POST_INCREMENT",
1274 : "ET_POST_DECREMENT",
1275 : "ET_CONDTEST",
1276 : "ET_STRING",
1277 : "ET_NUMBER",
1278 : "ET_IDENTIFIER",
1279 : "ET_FUNCTION_CALL",
1280 : "ET_NEW",
1281 : "ET_OBJECT_MEMBER_ACCESS",
1282 : "ET_OBJECT_METHOD_CALL",
1283 : "ET_ARRAY_DEREFERENCE",
1284 : "ET_ASSIGN",
1285 : "ET_PLUSEQ",
1286 : "ET_MINUSEQ",
1287 : "ET_MULTIPLYEQ",
1288 : "ET_DIVIDEEQ",
1289 : "ET_MODEQ",
1290 : "ET_ANDEQ",
1291 : "ET_OREQ",
1292 : "ET_XOREQ",
1293 : "ET_LSHIFTEQ",
1294 : "ET_RSHIFTEQ",
1295 : "ET_RSHIFTFILLEQ",
1296 : "ET_EQ",
1297 : "ET_NE",
1298 : "ET_LT",
1299 : "ET_LE",
1300 : "ET_GT",
1301 : "ET_GE",
1302 : "ET_PLUS",
1303 : "ET_MINUS",
1304 : "ET_MULTIPLY",
1305 : "ET_DIVIDE",
1306 : "ET_MOD",
1307 : "ET_LAND",
1308 : "ET_LOR",
1309 : "ET_AND",
1310 : "ET_OR",
1311 : "ET_XOR",
1312 : "ET_LSHIFT",
1313 : "ET_RSHIFT",
1314 : "ET_RSHIFTFILL",
1315 : "ET_BOOLEAN",
1316 : "ET_VAR",
1317 : "NUMBER_OF_EXPR_TYPE"
1318 : };
1319 : #endif
1320 :
1321 :
1322 : #define NUMBER_OF_RANK 15
1323 : static s32 ET_Rank[NUMBER_OF_EXPR_TYPE] =
1324 : {
1325 : 1,// ET_CURVED_EXPR
1326 : 2,// ET_NEGATIVE
1327 : 2,// ET_NOT
1328 : 2,// ET_ONESCOMP
1329 : 2,// ET_INCREMENT
1330 : 2,// ET_DECREMENT
1331 : 2,// ET_POST_INCREMENT
1332 : 2,// ET_POST_DECREMENT
1333 : 14,// ET_CONDTEST
1334 : 0,// ET_STRING
1335 : 0,// ET_NUMBER
1336 : 0,// ET_IDENTIFIER
1337 : 1,// ET_FUNCTION_CALL
1338 : 2,// ET_NEW
1339 : 1,// ET_OBJECT_MEMBER_ACCESS
1340 : 1,// ET_OBJECT_METHOD_CALL
1341 : 1,// ET_ARRAY_DEREFERENCE
1342 : 14,// ET_ASSIGN
1343 : 14,// ET_PLUSEQ
1344 : 14,// ET_MINUSEQ
1345 : 14,// ET_MULTIPLYEQ
1346 : 14,// ET_DIVIDEEQ
1347 : 14,// ET_MODEQ
1348 : 14,// ET_ANDEQ
1349 : 14,// ET_OREQ
1350 : 14,// ET_XOREQ
1351 : 14,// ET_LSHIFTEQ
1352 : 14,// ET_RSHIFTEQ
1353 : 14,// ET_RSHIFTFILLEQ
1354 : 8,// ET_EQ
1355 : 9,// ET_NE
1356 : 6,// ET_LT
1357 : 6,// ET_LE
1358 : 7,// ET_GT
1359 : 7,// ET_GE
1360 : 5,// ET_PLUS
1361 : 5,// ET_MINUS
1362 : 3,// ET_MULTIPLY
1363 : 3,// ET_DIVIDE
1364 : 3,// ET_MOD
1365 : 13,// ET_LAND
1366 : 14,// ET_LOR
1367 : 10,// ET_AND
1368 : 12,// ET_OR
1369 : 11,// ET_XOR
1370 : 5,// ET_LSHIFT
1371 : 6,// ET_RSHIFT
1372 : 6,// ET_RSHIFTFILL
1373 : 0, // ET_BOOLEAN
1374 : 14 // ET_VAR
1375 :
1376 : /*
1377 : 0, 0, 0, // variable, number, string
1378 : 1, 1, 1, 1, 1, // curved expr, call, member, array
1379 : 2, 2, 2, 2, 2, 2, 2, 2, // unary operator
1380 : 3, 3, 3, // multiply, divide, mod
1381 : 4, 4, // add, subtract
1382 : 5, 5, 5, // bitwise shift
1383 : 6, 6, 6, 6, // relational
1384 : 7, 7, // equality
1385 : 8, // bitwise and
1386 : 9, // bitwise xor
1387 : 10, // bitwise or
1388 : 11, // logical and
1389 : 12, // logical or
1390 : 13, // conditional
1391 : 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 // assignment
1392 : */
1393 : };
1394 : static s32 ET_leftAssoc[NUMBER_OF_RANK] = {1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
1395 :
1396 300 : u32 MoveToToken(ScriptEnc *sc_enc, u32 endTok, u32 cur, u32 end)
1397 : {
1398 : u32 cnt = 0;
1399 : u32 startTok = TOK_EOF, curTok;
1400 :
1401 300 : if (endTok == TOK_RIGHT_CURVE) startTok = TOK_LEFT_CURVE;
1402 140 : else if (endTok == TOK_RIGHT_BRACKET) startTok = TOK_LEFT_BRACKET;
1403 60 : else if (endTok == TOK_RIGHT_BRACE) startTok = TOK_LEFT_BRACE;
1404 60 : else if (endTok == TOK_CONDSEP) startTok = TOK_CONDTEST;
1405 : else {
1406 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal MoveToToken %s\n", tok_names[endTok]));
1407 0 : sc_enc->err = GF_BAD_PARAM;
1408 0 : return (u32) -1;
1409 : }
1410 : do {
1411 1000 : curTok = sc_enc->expr_toks[cur++];
1412 1000 : if (curTok == startTok) cnt++;
1413 700 : else if (curTok == endTok) cnt--;
1414 1000 : } while ( (curTok != endTok || cnt) && cur < end);
1415 300 : if (curTok==endTok && cnt==0) return cur-1;
1416 : return (u32) -1;
1417 : }
1418 :
1419 :
1420 : void SFE_FunctionCall(ScriptEnc *sc_enc, u32 start, u32 end);
1421 : void SFE_Params(ScriptEnc *sc_enc, u32 start, u32 end);
1422 : void SFE_ConditionTest(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
1423 : void SFE_ObjectConstruct(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
1424 : void SFE_ArrayDereference(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
1425 : void SFE_ObjectMethodCall(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
1426 : void SFE_ObjectMemberAccess(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
1427 :
1428 4241 : u32 SFE_Expression(ScriptEnc *sc_enc, u32 start, u32 end, Bool memberAccess)
1429 : {
1430 : char *str;
1431 : u32 n = start;
1432 : u32 curPos = 0, finalPos = 0;
1433 : u32 curTok, prevTok;
1434 : u32 curExpr = 0, expr = 0;
1435 : u32 curRank, maxRank=0;
1436 :
1437 4241 : if (sc_enc->err) return 0;
1438 :
1439 4241 : curTok = prevTok = sc_enc->expr_toks[n];
1440 : do {
1441 : curPos = n;
1442 8035 : switch (curTok) {
1443 3914 : case TOK_IDENTIFIER:
1444 : curExpr = ET_IDENTIFIER;
1445 3914 : break;
1446 1714 : case TOK_NUMBER:
1447 : curExpr = ET_NUMBER;
1448 1714 : break;
1449 40 : case TOK_BOOLEAN:
1450 : curExpr = ET_BOOLEAN;
1451 40 : break;
1452 100 : case TOK_STRING:
1453 : curExpr = ET_STRING;
1454 100 : break;
1455 80 : case TOK_LEFT_CURVE:
1456 80 : if (prevTok == TOK_IDENTIFIER) curExpr = ET_FUNCTION_CALL;
1457 : else curExpr = ET_CURVED_EXPR;
1458 80 : n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n, end);
1459 : curTok = TOK_RIGHT_CURVE;
1460 80 : break;
1461 80 : case TOK_LEFT_BRACKET:
1462 : curExpr = ET_ARRAY_DEREFERENCE;
1463 80 : n = MoveToToken(sc_enc, TOK_RIGHT_BRACKET, n, end);
1464 : curTok = TOK_RIGHT_BRACKET;
1465 80 : break;
1466 120 : case TOK_PERIOD:
1467 120 : curTok = sc_enc->expr_toks[++n];
1468 120 : CHECK_TOK(TOK_IDENTIFIER);
1469 120 : if (sc_enc->expr_toks[n+1] == TOK_LEFT_CURVE) {
1470 : curExpr = ET_OBJECT_METHOD_CALL;
1471 40 : n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n+1, end);
1472 : curTok = TOK_RIGHT_CURVE;
1473 : } else {
1474 : curExpr = ET_OBJECT_MEMBER_ACCESS;
1475 : }
1476 : break;
1477 40 : case TOK_NEW:
1478 : curExpr = ET_NEW;
1479 40 : curTok = sc_enc->expr_toks[++n];
1480 40 : CHECK_TOK(TOK_IDENTIFIER);
1481 40 : curTok = sc_enc->expr_toks[++n];
1482 40 : CHECK_TOK(TOK_LEFT_CURVE);
1483 40 : n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n, end);
1484 : curTok = TOK_RIGHT_CURVE;
1485 40 : break;
1486 20 : case TOK_FUNCTION:
1487 : curExpr = ET_FUNCTION_ASSIGN;
1488 20 : break;
1489 40 : case TOK_PLUS:
1490 40 : if (
1491 40 : prevTok==TOK_RIGHT_CURVE || prevTok==TOK_RIGHT_BRACKET ||
1492 40 : prevTok==TOK_IDENTIFIER || prevTok==TOK_NUMBER ||
1493 0 : prevTok==TOK_STRING || prevTok==TOK_INCREMENT ||
1494 : prevTok==TOK_DECREMENT
1495 : ) {
1496 : curExpr = ET_PLUS;
1497 : } else {
1498 : goto skip_token;
1499 : }
1500 : break;
1501 80 : case TOK_MINUS:
1502 80 : if (
1503 80 : prevTok==TOK_RIGHT_CURVE || prevTok==TOK_RIGHT_BRACKET ||
1504 80 : prevTok==TOK_IDENTIFIER || prevTok==TOK_NUMBER ||
1505 40 : prevTok==TOK_STRING || prevTok==TOK_INCREMENT ||
1506 : prevTok==TOK_DECREMENT
1507 : ) {
1508 : curExpr = ET_MINUS;
1509 : } else {
1510 : curExpr = ET_NEGATIVE;
1511 : curTok = TOK_NEGATIVE;
1512 : }
1513 : break;
1514 60 : case TOK_INCREMENT:
1515 : curExpr = ET_INCREMENT;
1516 60 : break;
1517 40 : case TOK_DECREMENT:
1518 : curExpr = ET_DECREMENT;
1519 40 : break;
1520 60 : case TOK_NOT:
1521 : curExpr = ET_NOT;
1522 60 : break;
1523 40 : case TOK_ONESCOMP:
1524 : curExpr = ET_ONESCOMP;
1525 40 : break;
1526 120 : case TOK_CONDTEST:
1527 : curExpr = ET_CONDTEST;
1528 120 : break;
1529 : case TOK_CONDSEP:
1530 : break;
1531 0 : case TOK_LEFT_BRACE:
1532 : curExpr = ET_CURVED_EXPR;
1533 0 : n = MoveToToken(sc_enc, TOK_RIGHT_BRACE, n, end);
1534 : curTok = TOK_RIGHT_BRACE;
1535 0 : break;
1536 : break;
1537 1367 : default:
1538 :
1539 1367 : if (curTok && (curTok != TOK_VAR)
1540 1347 : && (curTok < TOK_MULTIPLY || curTok > TOK_OREQ)) {
1541 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal token %s read\n", tok_names[curTok]));
1542 0 : sc_enc->err = GF_BAD_PARAM;
1543 0 : return 0;
1544 : }
1545 : curExpr = TOK_To_ET(curTok);
1546 : }
1547 :
1548 8035 : if (curTok == TOK_CONDSEP) {
1549 : prevTok = curTok;
1550 120 : curTok = sc_enc->expr_toks[++n];
1551 120 : continue;
1552 : }
1553 7915 : curRank = ET_Rank[curExpr];
1554 7915 : if (curRank > maxRank) {
1555 : maxRank = curRank;
1556 : expr = curExpr;
1557 : finalPos = curPos;
1558 6208 : } else if (curRank == maxRank && ET_leftAssoc[curRank]) {
1559 : expr = curExpr;
1560 : finalPos = curPos;
1561 : }
1562 : prevTok = curTok;
1563 7915 : skip_token:
1564 7915 : curTok = sc_enc->expr_toks[++n];
1565 8035 : } while (n<end);
1566 :
1567 4241 : if (expr == ET_INCREMENT) {
1568 60 : if (finalPos==start) {}
1569 40 : else if (finalPos==end-1) expr = ET_POST_INCREMENT;
1570 : else {
1571 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal Increment expression\n"));
1572 0 : sc_enc->err = GF_BAD_PARAM;
1573 0 : return expr;
1574 : }
1575 4181 : } else if (expr == ET_DECREMENT) {
1576 40 : if (finalPos==start) {}
1577 20 : else if (finalPos==end-1) expr = ET_POST_DECREMENT;
1578 : else {
1579 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal Decrement expression\n"));
1580 0 : sc_enc->err = GF_BAD_PARAM;
1581 0 : return expr;
1582 : }
1583 : }
1584 :
1585 4241 : SFE_WRITE_INT(sc_enc, expr, NUMBITS_EXPR_TYPE, "expressionType", (char *) expr_name[expr]);
1586 :
1587 4241 : switch (expr) {
1588 420 : case ET_MULTIPLY:
1589 : case ET_DIVIDE:
1590 : case ET_MOD:
1591 : case ET_PLUS:
1592 : case ET_MINUS:
1593 : case ET_LSHIFT:
1594 : case ET_RSHIFT:
1595 : case ET_RSHIFTFILL:
1596 : case ET_LT:
1597 : case ET_LE:
1598 : case ET_GT:
1599 : case ET_GE:
1600 : case ET_EQ:
1601 : case ET_NE:
1602 : case ET_AND:
1603 : case ET_XOR:
1604 : case ET_OR:
1605 : case ET_LAND:
1606 : case ET_LOR:
1607 420 : SFE_Expression(sc_enc, start, finalPos, GF_FALSE);
1608 420 : SFE_Expression(sc_enc, finalPos+1, end, GF_FALSE);
1609 420 : break;
1610 787 : case ET_ASSIGN:
1611 : case ET_PLUSEQ:
1612 : case ET_MINUSEQ:
1613 : case ET_MULTIPLYEQ:
1614 : case ET_DIVIDEEQ:
1615 : case ET_MODEQ:
1616 : case ET_LSHIFTEQ:
1617 : case ET_RSHIFTEQ:
1618 : case ET_RSHIFTFILLEQ:
1619 : case ET_ANDEQ:
1620 : case ET_XOREQ:
1621 : case ET_OREQ:
1622 : {
1623 787 : u32 ret = SFE_Expression(sc_enc, start, finalPos, GF_FALSE);
1624 787 : if ( ret != ET_IDENTIFIER && ret != ET_OBJECT_MEMBER_ACCESS && ret != ET_ARRAY_DEREFERENCE ) {
1625 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: LeftVariable expected, %s returned\n", expr_name[ret]));
1626 0 : sc_enc->err = GF_BAD_PARAM;
1627 0 : return expr;
1628 : }
1629 787 : SFE_Expression(sc_enc, finalPos+1, end, GF_FALSE);
1630 : }
1631 787 : break;
1632 :
1633 1707 : case ET_IDENTIFIER:
1634 1707 : str = (char *)gf_list_get(sc_enc->id_buf, 0);
1635 1707 : gf_list_rem(sc_enc->id_buf, 0);
1636 : /*TODO: when accessing member, we should try to translate proto fields into _fieldALL when not
1637 : using USENAMEs...*/
1638 : if (memberAccess) {
1639 : }
1640 1707 : SFE_PutIdentifier(sc_enc, str);
1641 1707 : gf_free(str);
1642 1707 : break;
1643 787 : case ET_NUMBER:
1644 787 : str = (char *)gf_list_get(sc_enc->id_buf, 0);
1645 787 : gf_list_rem(sc_enc->id_buf, 0);
1646 787 : SFE_PutNumber(sc_enc, str);
1647 787 : gf_free(str);
1648 787 : break;
1649 20 : case ET_BOOLEAN:
1650 20 : str = (char *)gf_list_get(sc_enc->id_buf, 0);
1651 20 : gf_list_rem(sc_enc->id_buf, 0);
1652 20 : SFE_PutBoolean(sc_enc, str);
1653 20 : gf_free(str);
1654 20 : break;
1655 40 : case ET_VAR:
1656 : while (1) {
1657 60 : str = (char *)gf_list_get(sc_enc->id_buf, 0);
1658 40 : if (!str) break;
1659 20 : gf_list_rem(sc_enc->id_buf, 0);
1660 20 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "hasArgument", NULL);
1661 20 : SFE_PutIdentifier(sc_enc, str);
1662 20 : gf_free(str);
1663 : }
1664 20 : GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "hasArgument", NULL);
1665 : break;
1666 60 : case ET_STRING:
1667 60 : str = (char *)gf_list_get(sc_enc->id_buf, 0);
1668 60 : gf_list_rem(sc_enc->id_buf, 0);
1669 60 : if (!sc_enc->emul) gf_bifs_enc_name(sc_enc->codec, sc_enc->bs, str);
1670 60 : gf_free(str);
1671 60 : break;
1672 120 : case ET_NEGATIVE:
1673 : case ET_INCREMENT:
1674 : case ET_DECREMENT:
1675 : case ET_NOT:
1676 : case ET_ONESCOMP:
1677 120 : SFE_Expression(sc_enc, finalPos+1, end, GF_FALSE);
1678 120 : break;
1679 20 : case ET_CURVED_EXPR:
1680 20 : SFE_CompoundExpression(sc_enc, finalPos+1, end-1, 0);
1681 20 : break;
1682 60 : case ET_POST_INCREMENT :
1683 : case ET_POST_DECREMENT :
1684 60 : SFE_Expression(sc_enc, start, finalPos, GF_FALSE);
1685 60 : break;
1686 20 : case ET_FUNCTION_CALL:
1687 20 : SFE_FunctionCall(sc_enc, start, end);
1688 20 : break;
1689 40 : case ET_OBJECT_MEMBER_ACCESS :
1690 40 : SFE_ObjectMemberAccess(sc_enc, start, finalPos, end);
1691 40 : break;
1692 40 : case ET_OBJECT_METHOD_CALL:
1693 40 : SFE_ObjectMethodCall(sc_enc, start, finalPos, end);
1694 40 : break;
1695 40 : case ET_ARRAY_DEREFERENCE:
1696 40 : SFE_ArrayDereference(sc_enc, start, finalPos, end);
1697 40 : break;
1698 20 : case ET_NEW:
1699 20 : SFE_ObjectConstruct(sc_enc, start, finalPos, end);
1700 20 : break;
1701 60 : case ET_CONDTEST:
1702 60 : SFE_ConditionTest(sc_enc, start, finalPos, end);
1703 60 : break;
1704 20 : case ET_FUNCTION_ASSIGN:
1705 20 : SFE_NextToken(sc_enc);
1706 20 : SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
1707 :
1708 20 : SFE_Arguments(sc_enc);
1709 20 : SFE_StatementBlock(sc_enc);
1710 20 : SFE_NextToken(sc_enc);
1711 20 : SFE_CheckToken(sc_enc, TOK_SEMICOLON);
1712 20 : break;
1713 0 : default:
1714 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal expression type %s\n", expr < GF_ARRAY_LENGTH(expr_name) ? expr_name[expr] : ""));
1715 0 : sc_enc->err = GF_BAD_PARAM;
1716 0 : break;
1717 : }
1718 : return expr;
1719 : }
1720 :
1721 :
1722 20 : void SFE_FunctionCall(ScriptEnc *sc_enc, u32 start, u32 end)
1723 : {
1724 : u32 curTok;
1725 : char *str;
1726 20 : curTok = sc_enc->expr_toks[start++];
1727 20 : CHECK_TOK(TOK_IDENTIFIER);
1728 20 : str = (char *)gf_list_get(sc_enc->id_buf, 0);
1729 20 : gf_list_rem(sc_enc->id_buf, 0);
1730 20 : SFE_PutIdentifier(sc_enc, str);
1731 20 : gf_free(str);
1732 20 : curTok = sc_enc->expr_toks[start++];
1733 20 : CHECK_TOK(TOK_LEFT_CURVE);
1734 20 : SFE_Params(sc_enc, start, end-1);
1735 20 : curTok = sc_enc->expr_toks[end-1];
1736 20 : CHECK_TOK(TOK_RIGHT_CURVE);
1737 20 : }
1738 :
1739 40 : void SFE_ObjectMemberAccess(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
1740 : {
1741 : u32 curTok;
1742 : char *str;
1743 :
1744 40 : SFE_Expression(sc_enc, start, op, GF_TRUE);
1745 40 : curTok = sc_enc->expr_toks[op];
1746 40 : CHECK_TOK(TOK_PERIOD);
1747 40 : curTok = sc_enc->expr_toks[end-1];
1748 40 : CHECK_TOK(TOK_IDENTIFIER);
1749 40 : str = (char *)gf_list_get(sc_enc->id_buf, 0);
1750 40 : gf_list_rem(sc_enc->id_buf, 0);
1751 40 : SFE_PutIdentifier(sc_enc, str);
1752 40 : gf_free(str);
1753 40 : }
1754 :
1755 40 : void SFE_ObjectMethodCall(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
1756 : {
1757 : u32 curTok;
1758 : char *str;
1759 :
1760 40 : SFE_Expression(sc_enc, start, op, GF_FALSE);
1761 40 : curTok = sc_enc->expr_toks[op];
1762 40 : CHECK_TOK(TOK_PERIOD);
1763 40 : curTok = sc_enc->expr_toks[op+1];
1764 40 : CHECK_TOK(TOK_IDENTIFIER);
1765 40 : str = (char *)gf_list_get(sc_enc->id_buf, 0);
1766 40 : gf_list_rem(sc_enc->id_buf, 0);
1767 40 : SFE_PutIdentifier(sc_enc, str);
1768 40 : gf_free(str);
1769 40 : curTok = sc_enc->expr_toks[op+2];
1770 40 : CHECK_TOK(TOK_LEFT_CURVE);
1771 40 : SFE_Params(sc_enc, op+3, end-1);
1772 40 : curTok = sc_enc->expr_toks[end-1];
1773 40 : CHECK_TOK(TOK_RIGHT_CURVE);
1774 40 : }
1775 :
1776 40 : void SFE_ArrayDereference(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
1777 : {
1778 : u32 curTok;
1779 :
1780 40 : SFE_Expression(sc_enc, start, op, GF_FALSE);
1781 40 : curTok = sc_enc->expr_toks[op];
1782 40 : CHECK_TOK(TOK_LEFT_BRACKET);
1783 40 : SFE_CompoundExpression(sc_enc, op+1, end-1, 0);
1784 40 : curTok = sc_enc->expr_toks[end-1];
1785 40 : CHECK_TOK(TOK_RIGHT_BRACKET);
1786 40 : }
1787 :
1788 20 : void SFE_ObjectConstruct(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
1789 : {
1790 : u32 curTok;
1791 : char *str;
1792 :
1793 20 : curTok = sc_enc->expr_toks[start++];
1794 20 : CHECK_TOK(TOK_NEW);
1795 20 : curTok = sc_enc->expr_toks[start++];
1796 20 : CHECK_TOK(TOK_IDENTIFIER);
1797 20 : str = (char *)gf_list_get(sc_enc->id_buf, 0);
1798 20 : gf_list_rem(sc_enc->id_buf, 0);
1799 20 : SFE_PutIdentifier(sc_enc, str);
1800 20 : gf_free(str);
1801 20 : curTok = sc_enc->expr_toks[start++];
1802 20 : CHECK_TOK(TOK_LEFT_CURVE);
1803 20 : SFE_Params(sc_enc, start, end-1);
1804 20 : curTok = sc_enc->expr_toks[end-1];
1805 20 : CHECK_TOK(TOK_RIGHT_CURVE);
1806 20 : }
1807 :
1808 60 : void SFE_ConditionTest(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
1809 : {
1810 : u32 curTok;
1811 :
1812 60 : SFE_Expression(sc_enc, start, op, GF_FALSE);
1813 60 : curTok = sc_enc->expr_toks[op];
1814 60 : CHECK_TOK(TOK_CONDTEST);
1815 60 : start = op+1;
1816 60 : op = MoveToToken(sc_enc, TOK_CONDSEP, op, end-1);
1817 60 : SFE_Expression(sc_enc, start, op, GF_FALSE);
1818 60 : curTok = sc_enc->expr_toks[op];
1819 60 : CHECK_TOK(TOK_CONDSEP);
1820 60 : SFE_Expression(sc_enc, op+1, end, GF_FALSE);
1821 60 : }
1822 :
1823 80 : void SFE_Params(ScriptEnc *sc_enc, u32 start, u32 end)
1824 : {
1825 : u32 curTok;
1826 :
1827 80 : curTok = sc_enc->expr_toks[start];
1828 80 : if (curTok != TOK_RIGHT_CURVE) {
1829 40 : SFE_WRITE_INT(sc_enc, 1, 1, "hasParam", NULL);
1830 40 : SFE_CompoundExpression(sc_enc, start, end, 1);
1831 : } else {
1832 40 : SFE_WRITE_INT(sc_enc, 0, 1, "hasParam", NULL);
1833 : }
1834 80 : }
1835 :
1836 : #endif /* !defined(GPAC_DISABLE_BIFS) && !defined(GPAC_DISABLE_BIFS_ENC) && defined(GPAC_HAS_QJS) */
|