/src/gpac/src/bifs/script_enc.c
Line | Count | Source |
1 | | /* |
2 | | * GPAC - Multimedia Framework C SDK |
3 | | * |
4 | | * Authors: Jean Le Feuvre |
5 | | * Copyright (c) Telecom ParisTech 2000-2023 |
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 | 0 | if (!sc_enc->emul) GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, val, nbBits, str1, str2); \ |
60 | | |
61 | | |
62 | | static GF_Err EncScriptFields(ScriptEnc *sc_enc) |
63 | 0 | { |
64 | 0 | u32 nbFields, nbBits, eType, nbBitsProto, i; |
65 | 0 | Bool use_list; |
66 | 0 | GF_Err e; |
67 | 0 | GF_FieldInfo info; |
68 | |
|
69 | 0 | nbFields = gf_node_get_num_fields_in_mode(sc_enc->script, GF_SG_FIELD_CODING_ALL) - 3; |
70 | 0 | use_list = GF_TRUE; |
71 | 0 | nbBits = gf_get_bit_size(nbFields); |
72 | 0 | if (nbFields+1 > 4 + gf_get_bit_size(nbFields)) use_list = GF_FALSE; |
73 | 0 | 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 | 0 | return GF_OK; |
77 | 0 | } |
78 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, use_list ? 1 : 0, 1, "Script::isList", NULL); |
79 | 0 | 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 | 0 | } |
83 | |
|
84 | 0 | nbBitsProto = 0; |
85 | 0 | 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 | 0 | for (i=0; i<nbFields; i++) { |
88 | 0 | if (use_list) GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "end", NULL); |
89 | |
|
90 | 0 | gf_node_get_field(sc_enc->script, i+3, &info); |
91 | 0 | switch (info.eventType) { |
92 | 0 | case GF_SG_EVENT_IN: |
93 | 0 | eType = GF_SG_SCRIPT_TYPE_EVENT_IN; |
94 | 0 | break; |
95 | 0 | case GF_SG_EVENT_OUT: |
96 | 0 | eType = GF_SG_SCRIPT_TYPE_EVENT_OUT; |
97 | 0 | break; |
98 | 0 | default: |
99 | 0 | eType = GF_SG_SCRIPT_TYPE_FIELD; |
100 | 0 | break; |
101 | 0 | } |
102 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, eType, 2, "eventType", NULL); |
103 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, info.fieldType, 6, "fieldType", NULL); |
104 | 0 | gf_bifs_enc_name(sc_enc->codec, sc_enc->bs, (char *) info.name); |
105 | | /*this is an identifier for script*/ |
106 | 0 | gf_list_add(sc_enc->identifiers, gf_strdup(info.name)); |
107 | |
|
108 | 0 | 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 | 0 | } else { |
116 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, isedField->ToField.fieldIndex, nbBitsProto, "protoField", NULL); |
117 | 0 | } |
118 | 0 | continue; |
119 | 0 | } |
120 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "isedField", NULL); |
121 | 0 | } |
122 | | /*default value*/ |
123 | 0 | if (eType == GF_SG_SCRIPT_TYPE_FIELD) { |
124 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, (info.far_ptr) ? 1 : 0, 1, "hasInitialValue", NULL); |
125 | 0 | if (info.far_ptr) { |
126 | 0 | e = gf_bifs_enc_field(sc_enc->codec, sc_enc->bs, sc_enc->script, &info); |
127 | 0 | if (e) return e; |
128 | 0 | } |
129 | 0 | } |
130 | 0 | } |
131 | 0 | if (use_list) GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "end", NULL); |
132 | 0 | return GF_OK; |
133 | 0 | } |
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 | | Bool SFE_GetNumber(ScriptEnc *sc_enc) |
294 | 0 | { |
295 | 0 | u32 i = 0; |
296 | 0 | Bool exp = GF_FALSE; |
297 | 0 | while ( isdigit(sc_enc->cur_buf[i]) |
298 | 0 | || (toupper(sc_enc->cur_buf[i])=='X') |
299 | 0 | || ((toupper(sc_enc->cur_buf[i]) >='A') && (toupper(sc_enc->cur_buf[i])<='F')) |
300 | 0 | || (sc_enc->cur_buf[i]=='.') |
301 | 0 | || (tolower(sc_enc->cur_buf[i])=='e') |
302 | 0 | || (exp && (sc_enc->cur_buf[i] == '-')) |
303 | 0 | ) { |
304 | 0 | sc_enc->token[i] = sc_enc->cur_buf[i]; |
305 | 0 | if (tolower(sc_enc->cur_buf[i])=='e') exp = GF_TRUE; |
306 | 0 | i++; |
307 | 0 | 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 | 0 | } |
312 | 0 | } |
313 | 0 | sc_enc->token[i] = 0; |
314 | 0 | sc_enc->cur_buf += i; |
315 | 0 | sc_enc->token_code = TOK_NUMBER; |
316 | 0 | return GF_TRUE; |
317 | 0 | } |
318 | | |
319 | | Bool SFE_NextToken(ScriptEnc *sc_enc) |
320 | 0 | { |
321 | 0 | u32 i; |
322 | 0 | if (sc_enc->err) return GF_FALSE; |
323 | 0 | while (strchr(" \t\r\n", sc_enc->cur_buf[0])) { |
324 | 0 | if (sc_enc->cur_buf[0]=='\n') sc_enc->cur_line ++; |
325 | 0 | sc_enc->cur_buf++; |
326 | 0 | } |
327 | 0 | 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 | 0 | } |
336 | 0 | } |
337 | 0 | sc_enc->cur_buf+=2; |
338 | 0 | return SFE_NextToken(sc_enc); |
339 | 0 | } |
340 | 0 | i = 0; |
341 | | /*get a name*/ |
342 | 0 | if (isalpha(sc_enc->cur_buf[i]) || (sc_enc->cur_buf[i]=='_')) { |
343 | 0 | while (isalnum(sc_enc->cur_buf[i]) || (sc_enc->cur_buf[i]=='_')) { |
344 | 0 | sc_enc->token[i] = sc_enc->cur_buf[i]; |
345 | 0 | i++; |
346 | 0 | } |
347 | 0 | sc_enc->token[i] = 0; |
348 | 0 | sc_enc->cur_buf += i; |
349 | 0 | sc_enc->token_code = TOK_IDENTIFIER; |
350 | | /*check keyword*/ |
351 | 0 | for (i=0; i<NUMBER_OF_KEYWORD; i++) { |
352 | 0 | if (!strcmp(sc_enc->token, sc_keywords[i])) { |
353 | 0 | sc_enc->token_code = i; |
354 | 0 | return GF_TRUE; |
355 | 0 | } |
356 | 0 | } |
357 | 0 | if (!stricmp(sc_enc->token, "TRUE") || !stricmp(sc_enc->token, "FALSE") ) { |
358 | 0 | sc_enc->token_code = TOK_BOOLEAN; |
359 | 0 | } |
360 | 0 | return GF_TRUE; |
361 | 0 | } |
362 | | /*get a number*/ |
363 | 0 | if (isdigit(sc_enc->cur_buf[i])) return SFE_GetNumber(sc_enc); |
364 | | /*get a string*/ |
365 | 0 | if ((sc_enc->cur_buf[i]=='\'') || (sc_enc->cur_buf[i]=='\"') |
366 | 0 | || ((sc_enc->cur_buf[i]=='\\') && (sc_enc->cur_buf[i+1]=='\"')) |
367 | 0 | ) { |
368 | 0 | char end; |
369 | 0 | Bool skip_last = GF_FALSE; |
370 | 0 | end = sc_enc->cur_buf[i]; |
371 | 0 | if (sc_enc->cur_buf[i]=='\\') { |
372 | 0 | skip_last = GF_TRUE; |
373 | 0 | sc_enc->cur_buf++; |
374 | 0 | } |
375 | 0 | while (sc_enc->cur_buf[i+1] != end) { |
376 | 0 | sc_enc->token[i] = sc_enc->cur_buf[i+1]; |
377 | 0 | i++; |
378 | 0 | } |
379 | 0 | sc_enc->token[i] = 0; |
380 | 0 | sc_enc->cur_buf += i+2; |
381 | 0 | if (skip_last) sc_enc->cur_buf++; |
382 | 0 | sc_enc->token_code = TOK_STRING; |
383 | 0 | return GF_TRUE; |
384 | 0 | } |
385 | | /*all other codes*/ |
386 | 0 | switch (sc_enc->cur_buf[i]) { |
387 | 0 | case '.': |
388 | 0 | if (isdigit(sc_enc->cur_buf[i+1])) { |
389 | 0 | SFE_GetNumber(sc_enc); |
390 | 0 | return GF_TRUE; |
391 | 0 | } else { |
392 | 0 | sc_enc->token_code = TOK_PERIOD; |
393 | 0 | } |
394 | 0 | break; |
395 | 0 | case '!': |
396 | 0 | if (sc_enc->cur_buf[i+1] == '=') { |
397 | 0 | sc_enc->token_code = TOK_NE; |
398 | 0 | sc_enc->cur_buf ++; |
399 | 0 | } else { |
400 | 0 | sc_enc->token_code = TOK_NOT; |
401 | 0 | } |
402 | 0 | break; |
403 | 0 | case '=': |
404 | 0 | if (sc_enc->cur_buf[i+1]=='=') { |
405 | 0 | 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 | 0 | } |
410 | 0 | sc_enc->token_code = TOK_EQ; |
411 | 0 | sc_enc->cur_buf ++; |
412 | 0 | } else { |
413 | 0 | sc_enc->token_code = TOK_ASSIGN; |
414 | 0 | } |
415 | 0 | break; |
416 | 0 | case '+': |
417 | 0 | if(sc_enc->cur_buf[i+1]=='=') { |
418 | 0 | sc_enc->token_code = TOK_PLUSEQ; |
419 | 0 | sc_enc->cur_buf ++; |
420 | 0 | } else if(sc_enc->cur_buf[i+1]=='+') { |
421 | 0 | sc_enc->token_code = TOK_INCREMENT; |
422 | 0 | sc_enc->cur_buf++; |
423 | 0 | } else { |
424 | 0 | sc_enc->token_code = TOK_PLUS; |
425 | 0 | } |
426 | 0 | break; |
427 | 0 | case '-': |
428 | 0 | if(sc_enc->cur_buf[i+1]=='=') { |
429 | 0 | sc_enc->token_code = TOK_MINUSEQ; |
430 | 0 | sc_enc->cur_buf++; |
431 | 0 | } else if(sc_enc->cur_buf[i+1] == '-') { |
432 | 0 | sc_enc->token_code = TOK_DECREMENT; |
433 | 0 | sc_enc->cur_buf++; |
434 | 0 | } else { |
435 | 0 | sc_enc->token_code = TOK_MINUS; |
436 | 0 | } |
437 | 0 | break; |
438 | 0 | case '*': |
439 | 0 | if(sc_enc->cur_buf[i+1]=='=') { |
440 | 0 | sc_enc->token_code = TOK_MULTIPLYEQ; |
441 | 0 | sc_enc->cur_buf++; |
442 | 0 | } else { |
443 | 0 | sc_enc->token_code = TOK_MULTIPLY; |
444 | 0 | } |
445 | 0 | break; |
446 | 0 | case '/': |
447 | 0 | if(sc_enc->cur_buf[i+1]=='=') { |
448 | 0 | sc_enc->token_code = TOK_DIVIDEEQ; |
449 | 0 | sc_enc->cur_buf++; |
450 | 0 | } else { |
451 | 0 | sc_enc->token_code = TOK_DIVIDE; |
452 | 0 | } |
453 | 0 | break; |
454 | 0 | case '%': |
455 | 0 | if(sc_enc->cur_buf[i+1]=='=') { |
456 | 0 | sc_enc->token_code = TOK_MODEQ; |
457 | 0 | sc_enc->cur_buf++; |
458 | 0 | } else { |
459 | 0 | sc_enc->token_code = TOK_MOD; |
460 | 0 | } |
461 | 0 | break; |
462 | 0 | case '&': |
463 | 0 | if(sc_enc->cur_buf[i+1]=='=') { |
464 | 0 | sc_enc->token_code = TOK_ANDEQ; |
465 | 0 | sc_enc->cur_buf++; |
466 | 0 | } else if(sc_enc->cur_buf[i+1]=='&') { |
467 | 0 | sc_enc->token_code = TOK_LAND; |
468 | 0 | sc_enc->cur_buf++; |
469 | 0 | } else { |
470 | 0 | sc_enc->token_code = TOK_AND; |
471 | 0 | } |
472 | 0 | break; |
473 | 0 | case '|': |
474 | 0 | if(sc_enc->cur_buf[i+1]=='=') { |
475 | 0 | sc_enc->token_code = TOK_OREQ; |
476 | 0 | sc_enc->cur_buf++; |
477 | 0 | } else if(sc_enc->cur_buf[i+1]=='|') { |
478 | 0 | sc_enc->token_code = TOK_LOR; |
479 | 0 | sc_enc->cur_buf++; |
480 | 0 | } else { |
481 | 0 | sc_enc->token_code = TOK_OR; |
482 | 0 | } |
483 | 0 | break; |
484 | 0 | case '^': |
485 | 0 | if(sc_enc->cur_buf[i+1]=='=') { |
486 | 0 | sc_enc->token_code = TOK_XOREQ; |
487 | 0 | sc_enc->cur_buf++; |
488 | 0 | } else { |
489 | 0 | sc_enc->token_code = TOK_XOR; |
490 | 0 | } |
491 | 0 | break; |
492 | 0 | case '<': |
493 | 0 | if (sc_enc->cur_buf[i+1]=='<') { |
494 | 0 | if(sc_enc->cur_buf[i+2]=='=') { |
495 | 0 | sc_enc->token_code = TOK_LSHIFTEQ; |
496 | 0 | sc_enc->cur_buf += 1; |
497 | 0 | } else { |
498 | 0 | sc_enc->token_code = TOK_LSHIFT; |
499 | 0 | } |
500 | 0 | sc_enc->cur_buf += 1; |
501 | 0 | } else if(sc_enc->cur_buf[i+1]=='=') { |
502 | 0 | sc_enc->token_code = TOK_LE; |
503 | 0 | sc_enc->cur_buf ++; |
504 | 0 | } else { |
505 | 0 | sc_enc->token_code = TOK_LT; |
506 | 0 | } |
507 | 0 | break; |
508 | 0 | case '>': |
509 | 0 | if (sc_enc->cur_buf[i+1]=='>') { |
510 | 0 | if (sc_enc->cur_buf[i+2]=='=') { |
511 | 0 | sc_enc->token_code = TOK_RSHIFTEQ; |
512 | 0 | sc_enc->cur_buf ++; |
513 | 0 | } else if(sc_enc->cur_buf[i+2]=='>') { |
514 | 0 | if(sc_enc->cur_buf[i+3]=='=') { |
515 | 0 | sc_enc->token_code = TOK_RSHIFTFILLEQ; |
516 | 0 | sc_enc->cur_buf ++; |
517 | 0 | } else { |
518 | 0 | sc_enc->token_code = TOK_RSHIFTFILL; |
519 | 0 | } |
520 | 0 | sc_enc->cur_buf ++; |
521 | 0 | } else { |
522 | 0 | sc_enc->token_code = TOK_RSHIFT; |
523 | 0 | } |
524 | 0 | sc_enc->cur_buf ++; |
525 | 0 | } else if (sc_enc->cur_buf[i+1]=='=') { |
526 | 0 | sc_enc->token_code = TOK_GE; |
527 | 0 | sc_enc->cur_buf ++; |
528 | 0 | } else { |
529 | 0 | sc_enc->token_code = TOK_GT; |
530 | 0 | } |
531 | 0 | break; |
532 | 0 | case '?': |
533 | 0 | sc_enc->token_code = TOK_CONDTEST; |
534 | 0 | break; |
535 | 0 | case ':': |
536 | 0 | sc_enc->token_code = TOK_CONDSEP; |
537 | 0 | break; |
538 | 0 | case '~': |
539 | 0 | sc_enc->token_code = TOK_ONESCOMP; |
540 | 0 | break; |
541 | 0 | case ',': |
542 | 0 | sc_enc->token_code = TOK_COMMA; |
543 | 0 | break; |
544 | 0 | case ';': |
545 | 0 | sc_enc->token_code = TOK_SEMICOLON; |
546 | 0 | break; |
547 | 0 | case '{': |
548 | 0 | sc_enc->token_code = TOK_LEFT_BRACE; |
549 | 0 | break; |
550 | 0 | case '}': |
551 | 0 | sc_enc->token_code = TOK_RIGHT_BRACE; |
552 | 0 | break; |
553 | 0 | case '(': |
554 | 0 | sc_enc->token_code = TOK_LEFT_CURVE; |
555 | 0 | break; |
556 | 0 | case ')': |
557 | 0 | sc_enc->token_code = TOK_RIGHT_CURVE; |
558 | 0 | break; |
559 | 0 | case '[': |
560 | 0 | sc_enc->token_code = TOK_LEFT_BRACKET; |
561 | 0 | break; |
562 | 0 | case ']': |
563 | 0 | sc_enc->token_code = TOK_RIGHT_BRACKET; |
564 | 0 | 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 | 0 | } |
570 | 0 | sc_enc->cur_buf ++; |
571 | 0 | return GF_TRUE; |
572 | 0 | } |
573 | | |
574 | | Bool SFE_CheckToken(ScriptEnc *sc_enc, u32 token) |
575 | 0 | { |
576 | 0 | 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 | 0 | return GF_FALSE; |
579 | 0 | } |
580 | 0 | return GF_TRUE; |
581 | 0 | } |
582 | | |
583 | | void SFE_PutIdentifier(ScriptEnc *sc_enc, char *id) |
584 | 0 | { |
585 | 0 | u32 i; |
586 | 0 | u32 nbBits, length; |
587 | 0 | char *str; |
588 | |
|
589 | 0 | if (sc_enc->emul) return; |
590 | | |
591 | 0 | i=0; |
592 | 0 | while ((str = (char *)gf_list_enum(sc_enc->identifiers, &i))) { |
593 | 0 | if (strcmp(str, id)) continue; |
594 | | |
595 | 0 | nbBits = 0; |
596 | 0 | length = gf_list_count(sc_enc->identifiers) - 1; |
597 | 0 | while (length > 0) { |
598 | 0 | length >>= 1; |
599 | 0 | nbBits ++; |
600 | 0 | } |
601 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "received", str); |
602 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, i-1, nbBits, "identifierCode", str); |
603 | 0 | return; |
604 | 0 | } |
605 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "received", id); |
606 | 0 | gf_list_add(sc_enc->identifiers, gf_strdup(id)); |
607 | 0 | gf_bifs_enc_name(sc_enc->codec, sc_enc->bs, id); |
608 | 0 | } |
609 | | |
610 | | |
611 | | void SFE_Arguments(ScriptEnc *sc_enc) |
612 | 0 | { |
613 | 0 | while (1) { |
614 | 0 | if (!SFE_NextToken(sc_enc)) return; |
615 | 0 | if (sc_enc->token_code == TOK_RIGHT_CURVE) break; |
616 | 0 | else if (sc_enc->token_code == TOK_COMMA) continue; |
617 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "hasArgument", NULL); |
618 | 0 | SFE_PutIdentifier(sc_enc, sc_enc->token); |
619 | 0 | } |
620 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "hasArgument", NULL); |
621 | 0 | } |
622 | | |
623 | | void SFE_StatementBlock(ScriptEnc *sc_enc); |
624 | | void SFE_Statement(ScriptEnc *sc_enc); |
625 | | |
626 | | void SFE_PutInteger(ScriptEnc *sc_enc, char *str) |
627 | 0 | { |
628 | 0 | u32 nbBits, val = 0; |
629 | 0 | if (sc_enc->emul) return; |
630 | 0 | if ((str[0]=='0') && (str[1]=='x' || str[1]=='X')) { |
631 | 0 | val = (u32) strtoul(sc_enc->token, (char **) NULL, 16); |
632 | 0 | } else if (str[0]=='0' && isdigit(str[1])) { |
633 | 0 | val = (u32) strtoul(str, (char **) NULL, 8); |
634 | 0 | } else if (isdigit(str[0])) { |
635 | 0 | val = (u32) strtoul(str, (char **) NULL, 10); |
636 | 0 | } 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 | 0 | } |
641 | 0 | nbBits = gf_get_bit_size(val); |
642 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, nbBits, 5, "nbBitsInteger", NULL); |
643 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, val, nbBits, "value", sc_enc->token); |
644 | 0 | } |
645 | | |
646 | | u32 SFE_LoadExpression(ScriptEnc *sc_enc, u32 *expr_sep) |
647 | 0 | { |
648 | 0 | Bool is_var = GF_FALSE; |
649 | 0 | u32 close_code, open_code; |
650 | 0 | u32 count = 0; |
651 | 0 | u32 nbExpr = 1; |
652 | 0 | u32 nbIndir = 0; |
653 | 0 | expr_sep[0] = 0; |
654 | |
|
655 | 0 | sc_enc->expr_toks_len = 0; |
656 | |
|
657 | 0 | while ( (sc_enc->token_code != TOK_SEMICOLON) && (sc_enc->token_code != TOK_RIGHT_CURVE) ) { |
658 | 0 | switch (sc_enc->token_code) { |
659 | 0 | case TOK_CONDTEST: |
660 | 0 | nbIndir ++; |
661 | 0 | break; |
662 | 0 | case TOK_CONDSEP: |
663 | 0 | if (nbIndir > 0) nbIndir--; |
664 | | /*'case'*/ |
665 | 0 | else { |
666 | 0 | goto break_loop; |
667 | 0 | } |
668 | 0 | break; |
669 | 0 | case TOK_IDENTIFIER: |
670 | 0 | case TOK_NUMBER: |
671 | 0 | case TOK_STRING: |
672 | 0 | case TOK_BOOLEAN: |
673 | 0 | gf_list_add(sc_enc->id_buf, gf_strdup(sc_enc->token)); |
674 | 0 | break; |
675 | 0 | case TOK_FUNCTION: |
676 | 0 | goto break_loop; |
677 | 0 | } |
678 | | |
679 | 0 | if (sc_enc->token_code==TOK_VAR) is_var = GF_TRUE; |
680 | 0 | if (!is_var || (sc_enc->token_code!=TOK_COMMA)) { |
681 | 0 | sc_enc->expr_toks[sc_enc->expr_toks_len] = sc_enc->token_code; |
682 | 0 | sc_enc->expr_toks_len++; |
683 | 0 | } |
684 | |
|
685 | 0 | open_code = sc_enc->token_code; |
686 | 0 | close_code = 0; |
687 | 0 | if (sc_enc->token_code == TOK_LEFT_CURVE) close_code = TOK_RIGHT_CURVE; |
688 | 0 | else if (sc_enc->token_code == TOK_LEFT_BRACKET) close_code = TOK_RIGHT_BRACKET; |
689 | 0 | else if (sc_enc->token_code == TOK_LEFT_BRACE) close_code = TOK_RIGHT_BRACE; |
690 | | |
691 | | /*other expr*/ |
692 | 0 | 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 | 0 | } |
695 | | /*sub-expr*/ |
696 | 0 | else if (close_code) { |
697 | 0 | count++; |
698 | 0 | do { |
699 | 0 | SFE_NextToken(sc_enc); |
700 | 0 | if ((sc_enc->token_code == TOK_IDENTIFIER) || (sc_enc->token_code == TOK_NUMBER) |
701 | 0 | || (sc_enc->token_code == TOK_STRING) || (sc_enc->token_code == TOK_BOOLEAN) ) { |
702 | 0 | gf_list_add(sc_enc->id_buf, gf_strdup(sc_enc->token)); |
703 | 0 | } |
704 | 0 | sc_enc->expr_toks[sc_enc->expr_toks_len] = sc_enc->token_code; |
705 | 0 | sc_enc->expr_toks_len++; |
706 | 0 | if (sc_enc->token_code == open_code) count++; |
707 | 0 | else if (sc_enc->token_code == close_code) count--; |
708 | 0 | } while ( (sc_enc->token_code != close_code) || count); |
709 | 0 | } |
710 | 0 | SFE_NextToken(sc_enc); |
711 | |
|
712 | 0 | if (sc_enc->err) break; |
713 | 0 | } |
714 | | |
715 | 0 | break_loop: |
716 | 0 | if (sc_enc->err) { |
717 | 0 | GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: end of compoundExpression not found\n")); |
718 | 0 | return 0; |
719 | 0 | } |
720 | 0 | expr_sep[nbExpr] = sc_enc->expr_toks_len; |
721 | 0 | if ((sc_enc->token_code == TOK_IDENTIFIER) || (sc_enc->token_code == TOK_NUMBER) |
722 | 0 | || (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 | 0 | } |
725 | |
|
726 | 0 | if ((sc_enc->token_code != TOK_CONDSEP) && (sc_enc->token_code != TOK_RIGHT_BRACE) && (sc_enc->expr_toks[0] != TOK_VAR)) { |
727 | 0 | sc_enc->expr_toks[sc_enc->expr_toks_len] = sc_enc->token_code; |
728 | 0 | sc_enc->expr_toks_len++; |
729 | 0 | } |
730 | 0 | return nbExpr; |
731 | 0 | } |
732 | | |
733 | | u32 MoveToToken(ScriptEnc *sc_enc, u32 endTok, u32 cur, u32 end); |
734 | | |
735 | | u32 SFE_ScanExpression(ScriptEnc *sc_enc, u32 start, u32 end, u32 *expr_sep) |
736 | 0 | { |
737 | 0 | u32 curTok; |
738 | 0 | u32 n = start; |
739 | 0 | u32 nbExpr = 1; |
740 | |
|
741 | 0 | expr_sep[0] = start; |
742 | 0 | while (n<end) { |
743 | 0 | curTok = sc_enc->expr_toks[n++]; |
744 | 0 | if (curTok == TOK_LEFT_CURVE) { |
745 | 0 | n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n-1, end); |
746 | 0 | n++; |
747 | 0 | } else if (curTok == TOK_LEFT_BRACKET) { |
748 | 0 | n = MoveToToken(sc_enc, TOK_RIGHT_BRACKET, n-1, end); |
749 | 0 | n++; |
750 | 0 | } else if (curTok == TOK_COMMA) { |
751 | 0 | expr_sep[nbExpr++] = n-1; |
752 | 0 | } |
753 | 0 | } |
754 | 0 | expr_sep[nbExpr] = end; |
755 | 0 | return nbExpr; |
756 | 0 | } |
757 | | |
758 | | u32 SFE_Expression(ScriptEnc *sc_enc, u32 start, u32 end, Bool memberAccess); |
759 | | |
760 | | void SFE_CompoundExpression(ScriptEnc *sc_enc, u32 start, u32 end, u32 isPar) |
761 | 0 | { |
762 | 0 | u32 nbExp, i; |
763 | | /*filled by indexes of ',' expressions in the expr_tok buffer*/ |
764 | 0 | u32 expr_sep[MAX_NUM_EXPR]; |
765 | |
|
766 | 0 | if (sc_enc->err) return; |
767 | | |
768 | 0 | if (end==0) { |
769 | | /*load expressions , eg "a ? ((a>b) ? 1 : 0) : 0" */ |
770 | 0 | nbExp = SFE_LoadExpression(sc_enc, expr_sep); |
771 | 0 | } else { |
772 | | /*load sub-expression from loaded expression set*/ |
773 | 0 | nbExp = SFE_ScanExpression(sc_enc, start, end, expr_sep); |
774 | 0 | } |
775 | |
|
776 | 0 | SFE_Expression(sc_enc, expr_sep[0], expr_sep[1], GF_FALSE); |
777 | 0 | for (i=1; i<nbExp; i++) { |
778 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, isPar ? "hasParam" : "hasExpression", NULL); |
779 | 0 | SFE_Expression(sc_enc, expr_sep[i]+1, expr_sep[i+1], GF_FALSE); |
780 | 0 | } |
781 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, isPar ? "hasParam" : "hasExpression", NULL); |
782 | 0 | } |
783 | | |
784 | | void SFE_OptionalExpression(ScriptEnc *sc_enc) |
785 | 0 | { |
786 | 0 | if (sc_enc->token_code != TOK_SEMICOLON) { |
787 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, "hasCompoundExpression", NULL); |
788 | 0 | SFE_CompoundExpression(sc_enc, 0, 0, 0); |
789 | 0 | } else { |
790 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, "hasCompoundExpression", NULL); |
791 | 0 | } |
792 | 0 | } |
793 | | |
794 | | void SFE_IfStatement(ScriptEnc *sc_enc) |
795 | 0 | { |
796 | 0 | char *buf_bck; |
797 | 0 | u32 tok_bck; |
798 | 0 | SFE_NextToken(sc_enc); |
799 | 0 | SFE_CheckToken(sc_enc, TOK_LEFT_CURVE); |
800 | 0 | SFE_NextToken(sc_enc); |
801 | 0 | SFE_CompoundExpression(sc_enc, 0, 0, 0); |
802 | 0 | SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE); |
803 | 0 | SFE_StatementBlock(sc_enc); |
804 | |
|
805 | 0 | buf_bck = sc_enc->cur_buf; |
806 | 0 | tok_bck = sc_enc->token_code; |
807 | 0 | SFE_NextToken(sc_enc); |
808 | 0 | if (sc_enc->token_code == TOK_ELSE) { |
809 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, "hasELSEStatement", NULL); |
810 | 0 | SFE_StatementBlock(sc_enc); |
811 | 0 | } else { |
812 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, "hasELSEStatement", NULL); |
813 | 0 | sc_enc->cur_buf = buf_bck; |
814 | 0 | sc_enc->token_code = tok_bck; |
815 | 0 | } |
816 | 0 | } |
817 | | |
818 | | void SFE_ForStatement(ScriptEnc *sc_enc) |
819 | 0 | { |
820 | 0 | SFE_NextToken(sc_enc); |
821 | 0 | SFE_CheckToken(sc_enc, TOK_LEFT_CURVE); |
822 | |
|
823 | 0 | SFE_NextToken(sc_enc); |
824 | 0 | SFE_OptionalExpression(sc_enc); |
825 | 0 | SFE_CheckToken(sc_enc, TOK_SEMICOLON); |
826 | |
|
827 | 0 | SFE_NextToken(sc_enc); |
828 | 0 | SFE_OptionalExpression(sc_enc); |
829 | 0 | SFE_CheckToken(sc_enc, TOK_SEMICOLON); |
830 | |
|
831 | 0 | SFE_NextToken(sc_enc); |
832 | 0 | SFE_OptionalExpression(sc_enc); |
833 | 0 | SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE); |
834 | |
|
835 | 0 | SFE_StatementBlock(sc_enc); |
836 | 0 | } |
837 | | |
838 | | void SFE_WhileStatement(ScriptEnc *sc_enc) |
839 | 0 | { |
840 | 0 | SFE_NextToken(sc_enc); |
841 | 0 | SFE_CheckToken(sc_enc, TOK_LEFT_CURVE); |
842 | 0 | SFE_NextToken(sc_enc); |
843 | 0 | SFE_CompoundExpression(sc_enc, 0, 0, 0); |
844 | 0 | SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE); |
845 | |
|
846 | 0 | SFE_StatementBlock(sc_enc); |
847 | 0 | } |
848 | | |
849 | | void SFE_ReturnStatement(ScriptEnc *sc_enc) |
850 | 0 | { |
851 | 0 | SFE_NextToken(sc_enc); |
852 | 0 | 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 | 0 | } else { |
856 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, "returnValue", NULL); |
857 | 0 | } |
858 | 0 | } |
859 | | |
860 | | void SFE_CaseBlock(ScriptEnc *sc_enc) |
861 | 0 | { |
862 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, "isCompoundStatement", NULL); |
863 | 0 | SFE_NextToken(sc_enc); |
864 | 0 | 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 | 0 | } |
871 | 0 | SFE_NextToken(sc_enc); |
872 | 0 | } |
873 | 0 | while ((sc_enc->token_code != TOK_CASE) && (sc_enc->token_code != TOK_DEFAULT) && (sc_enc->token_code != TOK_RIGHT_BRACE)) { |
874 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, "hasStatement", NULL); |
875 | 0 | SFE_Statement(sc_enc); |
876 | 0 | SFE_NextToken(sc_enc); |
877 | 0 | } |
878 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, "hasStatement", NULL); |
879 | 0 | } |
880 | | |
881 | | u32 SFE_PutCaseInteger(ScriptEnc *sc_enc, char *str, u32 nbBits) |
882 | 0 | { |
883 | 0 | u32 val = 0; |
884 | 0 | if ((str[0]=='0') && (str[1]=='x' || str[1]=='X')) { |
885 | 0 | val = (u32) strtoul(sc_enc->token, (char **) NULL, 16); |
886 | 0 | } else if (str[0]=='0' && isdigit(str[1])) { |
887 | 0 | val = (u32) strtoul(str, (char **) NULL, 8); |
888 | 0 | } else if (isdigit(str[0])) { |
889 | 0 | val = (u32) strtoul(str, (char **) NULL, 10); |
890 | 0 | } 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 | 0 | } |
895 | 0 | if (!sc_enc->emul) { |
896 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, val, nbBits, "value", sc_enc->token); |
897 | 0 | } else { |
898 | 0 | nbBits = gf_get_bit_size(val); |
899 | 0 | } |
900 | 0 | return nbBits; |
901 | 0 | } |
902 | | |
903 | | void SFE_SwitchStatement(ScriptEnc *sc_enc) |
904 | 0 | { |
905 | 0 | u32 nbBits, maxBits = 0; |
906 | 0 | Bool prev_emu; |
907 | 0 | char *buf_bck; |
908 | 0 | u32 tok_bck; |
909 | |
|
910 | 0 | SFE_NextToken(sc_enc); |
911 | 0 | SFE_CheckToken(sc_enc, TOK_LEFT_CURVE); |
912 | |
|
913 | 0 | SFE_NextToken(sc_enc); |
914 | 0 | SFE_CompoundExpression(sc_enc, 0, 0, 0); |
915 | 0 | SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE); |
916 | |
|
917 | 0 | SFE_NextToken(sc_enc); |
918 | 0 | SFE_CheckToken(sc_enc, TOK_LEFT_BRACE); |
919 | | |
920 | | /*first pass in emul*/ |
921 | 0 | buf_bck = sc_enc->cur_buf; |
922 | 0 | tok_bck = sc_enc->token_code; |
923 | 0 | prev_emu = sc_enc->emul; |
924 | 0 | sc_enc->emul = GF_TRUE; |
925 | |
|
926 | 0 | SFE_NextToken(sc_enc); |
927 | 0 | while (sc_enc->token_code == TOK_CASE) { |
928 | 0 | SFE_NextToken(sc_enc); |
929 | 0 | SFE_CheckToken(sc_enc, TOK_NUMBER); |
930 | 0 | nbBits = SFE_PutCaseInteger(sc_enc, sc_enc->token, 0); |
931 | 0 | if (maxBits<nbBits) maxBits = nbBits; |
932 | |
|
933 | 0 | SFE_NextToken(sc_enc); |
934 | 0 | SFE_CheckToken(sc_enc, TOK_CONDSEP); |
935 | |
|
936 | 0 | SFE_CaseBlock(sc_enc); |
937 | 0 | SFE_WRITE_INT(sc_enc, (sc_enc->token_code == TOK_CASE) ? 1 : 0, 1, "hasMoreCases", NULL); |
938 | 0 | } |
939 | | |
940 | | /*second pass in parent mode*/ |
941 | 0 | sc_enc->cur_buf = buf_bck; |
942 | 0 | sc_enc->token_code = tok_bck; |
943 | 0 | sc_enc->emul = prev_emu; |
944 | 0 | maxBits ++; |
945 | 0 | SFE_WRITE_INT(sc_enc, maxBits, 5, "caseNbBits", NULL); |
946 | |
|
947 | 0 | SFE_NextToken(sc_enc); |
948 | 0 | while (sc_enc->token_code == TOK_CASE) { |
949 | 0 | SFE_NextToken(sc_enc); |
950 | 0 | SFE_CheckToken(sc_enc, TOK_NUMBER); |
951 | 0 | SFE_PutCaseInteger(sc_enc, sc_enc->token, maxBits); |
952 | |
|
953 | 0 | SFE_NextToken(sc_enc); |
954 | 0 | SFE_CheckToken(sc_enc, TOK_CONDSEP); |
955 | |
|
956 | 0 | SFE_CaseBlock(sc_enc); |
957 | 0 | SFE_WRITE_INT(sc_enc, (sc_enc->token_code == TOK_CASE) ? 1 : 0, 1, "hasMoreCases", NULL); |
958 | 0 | } |
959 | |
|
960 | 0 | if (sc_enc->token_code == TOK_DEFAULT) { |
961 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, "hasDefault", NULL); |
962 | 0 | SFE_NextToken(sc_enc); |
963 | 0 | SFE_CheckToken(sc_enc, TOK_CONDSEP); |
964 | 0 | SFE_CaseBlock(sc_enc); |
965 | 0 | } else { |
966 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, "hasDefault", NULL); |
967 | 0 | } |
968 | 0 | SFE_CheckToken(sc_enc, TOK_RIGHT_BRACE); |
969 | 0 | } |
970 | | |
971 | | void SFE_Statement(ScriptEnc *sc_enc) |
972 | 0 | { |
973 | 0 | switch (sc_enc->token_code) { |
974 | 0 | case TOK_IF: |
975 | 0 | SFE_WRITE_INT(sc_enc, ST_IF, NUMBITS_STATEMENT, "statementType", "if"); |
976 | 0 | SFE_IfStatement(sc_enc); |
977 | 0 | break; |
978 | 0 | case TOK_FOR: |
979 | 0 | SFE_WRITE_INT(sc_enc, ST_FOR, NUMBITS_STATEMENT, "statementType", "for"); |
980 | 0 | SFE_ForStatement(sc_enc); |
981 | 0 | break; |
982 | 0 | case TOK_WHILE: |
983 | 0 | SFE_WRITE_INT(sc_enc, ST_WHILE, NUMBITS_STATEMENT, "statementType", "while"); |
984 | 0 | SFE_WhileStatement(sc_enc); |
985 | 0 | break; |
986 | 0 | case TOK_RETURN: |
987 | 0 | SFE_WRITE_INT(sc_enc, ST_RETURN, NUMBITS_STATEMENT, "statementType", "return"); |
988 | 0 | SFE_ReturnStatement(sc_enc); |
989 | 0 | break; |
990 | 0 | case TOK_BREAK: |
991 | 0 | SFE_WRITE_INT(sc_enc, ST_BREAK, NUMBITS_STATEMENT, "statementType", "break"); |
992 | 0 | SFE_NextToken(sc_enc); |
993 | 0 | break; |
994 | 0 | case TOK_CONTINUE: |
995 | 0 | SFE_WRITE_INT(sc_enc, ST_CONTINUE, NUMBITS_STATEMENT, "statementType", "continue"); |
996 | 0 | SFE_NextToken(sc_enc); |
997 | 0 | break; |
998 | 0 | case TOK_SWITCH: |
999 | 0 | SFE_WRITE_INT(sc_enc, ST_SWITCH, NUMBITS_STATEMENT, "statementType", "while"); |
1000 | 0 | SFE_SwitchStatement(sc_enc); |
1001 | 0 | break; |
1002 | 0 | default: |
1003 | 0 | SFE_WRITE_INT(sc_enc, ST_COMPOUND_EXPR, NUMBITS_STATEMENT, "statementType", "compoundExpr"); |
1004 | 0 | SFE_CompoundExpression(sc_enc, 0, 0, 0); |
1005 | 0 | break; |
1006 | 0 | } |
1007 | 0 | } |
1008 | | |
1009 | | void SFE_Statements(ScriptEnc *sc_enc) |
1010 | 0 | { |
1011 | 0 | while (1) { |
1012 | 0 | if (!SFE_NextToken(sc_enc)) return; |
1013 | 0 | if (sc_enc->token_code == TOK_RIGHT_BRACE) break; |
1014 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, "hasStatement", NULL); |
1015 | 0 | SFE_Statement(sc_enc); |
1016 | 0 | } |
1017 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, "hasStatement", NULL); |
1018 | 0 | } |
1019 | | |
1020 | | void SFE_StatementBlock(ScriptEnc *sc_enc) |
1021 | 0 | { |
1022 | 0 | if (!SFE_NextToken(sc_enc)) return; |
1023 | 0 | if (sc_enc->token_code == TOK_LEFT_BRACE) { |
1024 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, "isCompoundStatement", NULL); |
1025 | 0 | SFE_Statements(sc_enc); |
1026 | 0 | } else { |
1027 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, "isCompoundStatement", NULL); |
1028 | 0 | SFE_Statement(sc_enc); |
1029 | 0 | } |
1030 | 0 | } |
1031 | | void SFE_Function(ScriptEnc *sc_enc) |
1032 | 0 | { |
1033 | 0 | char szName[1000]; |
1034 | |
|
1035 | 0 | SFE_NextToken(sc_enc); |
1036 | 0 | SFE_CheckToken(sc_enc, TOK_FUNCTION); |
1037 | |
|
1038 | 0 | SFE_NextToken(sc_enc); |
1039 | 0 | SFE_CheckToken(sc_enc, TOK_IDENTIFIER); |
1040 | 0 | strcpy(szName, sc_enc->token); |
1041 | 0 | SFE_PutIdentifier(sc_enc, sc_enc->token); |
1042 | |
|
1043 | 0 | SFE_NextToken(sc_enc); |
1044 | 0 | SFE_CheckToken(sc_enc, TOK_LEFT_CURVE); |
1045 | |
|
1046 | 0 | SFE_Arguments(sc_enc); |
1047 | 0 | SFE_StatementBlock(sc_enc); |
1048 | |
|
1049 | 0 | if (sc_enc->err) GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Error while parsing function %s\n", szName)); |
1050 | 0 | } |
1051 | | |
1052 | | |
1053 | | GF_Err SFScript_Encode(GF_BifsEncoder *codec, SFScript *script_field, GF_BitStream *bs, GF_Node *n) |
1054 | 0 | { |
1055 | 0 | char *ptr; |
1056 | 0 | ScriptEnc sc_enc; |
1057 | 0 | if (gf_node_get_tag(n) != TAG_MPEG4_Script) return GF_NON_COMPLIANT_BITSTREAM; |
1058 | | |
1059 | 0 | memset(&sc_enc, 0, sizeof(ScriptEnc)); |
1060 | 0 | sc_enc.codec = codec; |
1061 | 0 | sc_enc.script = n; |
1062 | 0 | sc_enc.bs = bs; |
1063 | 0 | sc_enc.identifiers = gf_list_new(); |
1064 | 0 | sc_enc.id_buf = gf_list_new(); |
1065 | 0 | sc_enc.err = GF_OK; |
1066 | |
|
1067 | 0 | 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 | 0 | } else { |
1071 | 0 | EncScriptFields(&sc_enc); |
1072 | 0 | } |
1073 | | /*reserevd*/ |
1074 | 0 | GF_BIFS_WRITE_INT(codec, bs, 1, 1, "reserved", NULL); |
1075 | |
|
1076 | 0 | if (script_field) { |
1077 | 0 | 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 | 0 | } |
1081 | 0 | if (sc_enc.cur_buf) { |
1082 | 0 | 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 | 0 | ) { |
1086 | 0 | sc_enc.cur_buf += 11; |
1087 | 0 | } else if (!strnicmp(sc_enc.cur_buf, "mpeg4script:", 12) ) { |
1088 | 0 | sc_enc.cur_buf += 12; |
1089 | 0 | } |
1090 | 0 | } |
1091 | | |
1092 | | /*encode functions*/ |
1093 | 0 | while (sc_enc.cur_buf && sc_enc.cur_buf[0] && (sc_enc.cur_buf[0]!='}')) { |
1094 | 0 | if (strchr("\r\n\t ", sc_enc.cur_buf[0]) ) { |
1095 | 0 | sc_enc.cur_buf++; |
1096 | 0 | continue; |
1097 | 0 | } |
1098 | 0 | GF_BIFS_WRITE_INT(codec, bs, 1, 1, "hasFunction", NULL); |
1099 | 0 | SFE_Function(&sc_enc); |
1100 | 0 | if (sc_enc.err) break; |
1101 | 0 | } |
1102 | 0 | GF_BIFS_WRITE_INT(codec, bs, 0, 1, "hasFunction", NULL); |
1103 | | |
1104 | | //clean up |
1105 | 0 | while (gf_list_count(sc_enc.identifiers)) { |
1106 | 0 | ptr = (char *)gf_list_get(sc_enc.identifiers, 0); |
1107 | 0 | gf_list_rem(sc_enc.identifiers, 0); |
1108 | 0 | gf_free(ptr); |
1109 | 0 | } |
1110 | 0 | gf_list_del(sc_enc.identifiers); |
1111 | | /*in case of error this is needed*/ |
1112 | 0 | 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 | 0 | } |
1117 | 0 | gf_list_del(sc_enc.id_buf); |
1118 | |
|
1119 | 0 | return sc_enc.err; |
1120 | 0 | } |
1121 | | |
1122 | | |
1123 | | void SFE_PutReal(ScriptEnc *sc_enc, char *str) |
1124 | 0 | { |
1125 | 0 | u32 i; |
1126 | 0 | size_t length = strlen(str); |
1127 | 0 | for (i=0; i<length; i++) { |
1128 | 0 | s32 c = str[i]; |
1129 | 0 | if (c >= '0' && c <= '9') |
1130 | 0 | { |
1131 | 0 | SFE_WRITE_INT(sc_enc, c-'0', 4, "floatChar", "Digital"); |
1132 | 0 | } |
1133 | 0 | else if (c == '.') |
1134 | 0 | { |
1135 | 0 | SFE_WRITE_INT(sc_enc, 10, 4, "floatChar", "Decimal Point"); |
1136 | 0 | } |
1137 | 0 | else if (c == 'e' || c == 'E') |
1138 | 0 | { |
1139 | 0 | SFE_WRITE_INT(sc_enc, 11, 4, "floatChar", "Exponential"); |
1140 | 0 | } |
1141 | 0 | else if (c == '-') |
1142 | 0 | { |
1143 | 0 | SFE_WRITE_INT(sc_enc, 12, 4, "floatChar", "Sign"); |
1144 | 0 | } |
1145 | 0 | 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 | 0 | } |
1150 | 0 | } |
1151 | 0 | SFE_WRITE_INT(sc_enc, 15, 4, "floatChar", "End Symbol"); |
1152 | 0 | } |
1153 | | |
1154 | | void SFE_PutNumber(ScriptEnc *sc_enc, char *str) |
1155 | 0 | { |
1156 | 0 | if (strpbrk(str,".eE-") == 0) { |
1157 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, "isInteger", "integer"); |
1158 | 0 | SFE_PutInteger(sc_enc, str); |
1159 | 0 | } else { |
1160 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, "isInteger", "real"); |
1161 | 0 | SFE_PutReal(sc_enc, str); |
1162 | 0 | } |
1163 | 0 | } |
1164 | | |
1165 | | void SFE_PutBoolean(ScriptEnc *sc_enc, char *str) |
1166 | 0 | { |
1167 | 0 | u32 v = 1; |
1168 | 0 | if (!stricmp(str, "false") || !strcmp(str, "0")) v = 0; |
1169 | 0 | SFE_WRITE_INT(sc_enc, v, 1, "value", "bolean"); |
1170 | 0 | } |
1171 | | |
1172 | | |
1173 | | #define CHECK_TOK(x) \ |
1174 | 0 | if (curTok != x) { \ |
1175 | 0 | GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Token %s read, %s expected\n", tok_names[curTok], tok_names[x])); \ |
1176 | 0 | sc_enc->err = GF_BAD_PARAM; \ |
1177 | 0 | } \ |
1178 | | |
1179 | | |
1180 | | u32 TOK_To_ET(u32 tok) |
1181 | 0 | { |
1182 | 0 | switch(tok) { |
1183 | 0 | case TOK_INCREMENT: |
1184 | 0 | return ET_INCREMENT; |
1185 | 0 | case TOK_DECREMENT: |
1186 | 0 | return ET_DECREMENT; |
1187 | 0 | case TOK_NOT: |
1188 | 0 | return ET_NOT; |
1189 | 0 | case TOK_ONESCOMP: |
1190 | 0 | return ET_ONESCOMP; |
1191 | 0 | case TOK_MULTIPLY : |
1192 | 0 | return ET_MULTIPLY; |
1193 | 0 | case TOK_DIVIDE : |
1194 | 0 | return ET_DIVIDE; |
1195 | 0 | case TOK_MOD : |
1196 | 0 | return ET_MOD; |
1197 | 0 | case TOK_PLUS : |
1198 | 0 | return ET_PLUS; |
1199 | 0 | case TOK_MINUS : |
1200 | 0 | return ET_MINUS; |
1201 | 0 | case TOK_LSHIFT : |
1202 | 0 | return ET_LSHIFT; |
1203 | 0 | case TOK_RSHIFT : |
1204 | 0 | return ET_RSHIFT; |
1205 | 0 | case TOK_RSHIFTFILL : |
1206 | 0 | return ET_RSHIFTFILL; |
1207 | 0 | case TOK_LT : |
1208 | 0 | return ET_LT; |
1209 | 0 | case TOK_LE : |
1210 | 0 | return ET_LE; |
1211 | 0 | case TOK_GT : |
1212 | 0 | return ET_GT; |
1213 | 0 | case TOK_GE : |
1214 | 0 | return ET_GE; |
1215 | 0 | case TOK_EQ : |
1216 | 0 | return ET_EQ; |
1217 | 0 | case TOK_NE : |
1218 | 0 | return ET_NE; |
1219 | 0 | case TOK_AND : |
1220 | 0 | return ET_AND; |
1221 | 0 | case TOK_XOR : |
1222 | 0 | return ET_XOR; |
1223 | 0 | case TOK_OR : |
1224 | 0 | return ET_OR; |
1225 | 0 | case TOK_LAND : |
1226 | 0 | return ET_LAND; |
1227 | 0 | case TOK_LOR : |
1228 | 0 | return ET_LOR; |
1229 | 0 | case TOK_CONDTEST : |
1230 | 0 | return ET_CONDTEST; |
1231 | 0 | case TOK_ASSIGN : |
1232 | 0 | return ET_ASSIGN; |
1233 | 0 | case TOK_PLUSEQ : |
1234 | 0 | return ET_PLUSEQ; |
1235 | 0 | case TOK_MINUSEQ : |
1236 | 0 | return ET_MINUSEQ; |
1237 | 0 | case TOK_MULTIPLYEQ : |
1238 | 0 | return ET_MULTIPLYEQ; |
1239 | 0 | case TOK_DIVIDEEQ : |
1240 | 0 | return ET_DIVIDEEQ; |
1241 | 0 | case TOK_MODEQ : |
1242 | 0 | return ET_MODEQ; |
1243 | 0 | case TOK_LSHIFTEQ : |
1244 | 0 | return ET_LSHIFTEQ; |
1245 | 0 | case TOK_RSHIFTEQ : |
1246 | 0 | return ET_RSHIFTEQ; |
1247 | 0 | case TOK_RSHIFTFILLEQ : |
1248 | 0 | return ET_RSHIFTFILLEQ; |
1249 | 0 | case TOK_ANDEQ : |
1250 | 0 | return ET_ANDEQ; |
1251 | 0 | case TOK_XOREQ : |
1252 | 0 | return ET_XOREQ; |
1253 | 0 | case TOK_OREQ : |
1254 | 0 | return ET_OREQ; |
1255 | 0 | case TOK_FUNCTION: |
1256 | 0 | return ET_FUNCTION_CALL; |
1257 | 0 | case TOK_VAR: |
1258 | 0 | return ET_VAR; |
1259 | 0 | default: |
1260 | 0 | gf_assert(0); |
1261 | 0 | return (u32) -1; |
1262 | 0 | } |
1263 | 0 | } |
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 | | u32 MoveToToken(ScriptEnc *sc_enc, u32 endTok, u32 cur, u32 end) |
1397 | 0 | { |
1398 | 0 | u32 cnt = 0; |
1399 | 0 | u32 startTok = TOK_EOF, curTok; |
1400 | |
|
1401 | 0 | if (endTok == TOK_RIGHT_CURVE) startTok = TOK_LEFT_CURVE; |
1402 | 0 | else if (endTok == TOK_RIGHT_BRACKET) startTok = TOK_LEFT_BRACKET; |
1403 | 0 | else if (endTok == TOK_RIGHT_BRACE) startTok = TOK_LEFT_BRACE; |
1404 | 0 | else if (endTok == TOK_CONDSEP) startTok = TOK_CONDTEST; |
1405 | 0 | 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 | 0 | } |
1410 | 0 | do { |
1411 | 0 | curTok = sc_enc->expr_toks[cur++]; |
1412 | 0 | if (curTok == startTok) cnt++; |
1413 | 0 | else if (curTok == endTok) cnt--; |
1414 | 0 | } while ( (curTok != endTok || cnt) && cur < end); |
1415 | 0 | if (curTok==endTok && cnt==0) return cur-1; |
1416 | 0 | return (u32) -1; |
1417 | 0 | } |
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 | | u32 SFE_Expression(ScriptEnc *sc_enc, u32 start, u32 end, Bool memberAccess) |
1429 | 0 | { |
1430 | 0 | char *str; |
1431 | 0 | u32 n = start; |
1432 | 0 | u32 curPos = 0, finalPos = 0; |
1433 | 0 | u32 curTok, prevTok; |
1434 | 0 | u32 curExpr = 0, expr = 0; |
1435 | 0 | u32 curRank, maxRank=0; |
1436 | |
|
1437 | 0 | if (sc_enc->err) return 0; |
1438 | | |
1439 | 0 | curTok = prevTok = sc_enc->expr_toks[n]; |
1440 | 0 | do { |
1441 | 0 | curPos = n; |
1442 | 0 | switch (curTok) { |
1443 | 0 | case TOK_IDENTIFIER: |
1444 | 0 | curExpr = ET_IDENTIFIER; |
1445 | 0 | break; |
1446 | 0 | case TOK_NUMBER: |
1447 | 0 | curExpr = ET_NUMBER; |
1448 | 0 | break; |
1449 | 0 | case TOK_BOOLEAN: |
1450 | 0 | curExpr = ET_BOOLEAN; |
1451 | 0 | break; |
1452 | 0 | case TOK_STRING: |
1453 | 0 | curExpr = ET_STRING; |
1454 | 0 | break; |
1455 | 0 | case TOK_LEFT_CURVE: |
1456 | 0 | if (prevTok == TOK_IDENTIFIER) curExpr = ET_FUNCTION_CALL; |
1457 | 0 | else curExpr = ET_CURVED_EXPR; |
1458 | 0 | n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n, end); |
1459 | 0 | curTok = TOK_RIGHT_CURVE; |
1460 | 0 | break; |
1461 | 0 | case TOK_LEFT_BRACKET: |
1462 | 0 | curExpr = ET_ARRAY_DEREFERENCE; |
1463 | 0 | n = MoveToToken(sc_enc, TOK_RIGHT_BRACKET, n, end); |
1464 | 0 | curTok = TOK_RIGHT_BRACKET; |
1465 | 0 | break; |
1466 | 0 | case TOK_PERIOD: |
1467 | 0 | curTok = sc_enc->expr_toks[++n]; |
1468 | 0 | CHECK_TOK(TOK_IDENTIFIER); |
1469 | 0 | if (sc_enc->expr_toks[n+1] == TOK_LEFT_CURVE) { |
1470 | 0 | curExpr = ET_OBJECT_METHOD_CALL; |
1471 | 0 | n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n+1, end); |
1472 | 0 | curTok = TOK_RIGHT_CURVE; |
1473 | 0 | } else { |
1474 | 0 | curExpr = ET_OBJECT_MEMBER_ACCESS; |
1475 | 0 | } |
1476 | 0 | break; |
1477 | 0 | case TOK_NEW: |
1478 | 0 | curExpr = ET_NEW; |
1479 | 0 | curTok = sc_enc->expr_toks[++n]; |
1480 | 0 | CHECK_TOK(TOK_IDENTIFIER); |
1481 | 0 | curTok = sc_enc->expr_toks[++n]; |
1482 | 0 | CHECK_TOK(TOK_LEFT_CURVE); |
1483 | 0 | n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n, end); |
1484 | 0 | curTok = TOK_RIGHT_CURVE; |
1485 | 0 | break; |
1486 | 0 | case TOK_FUNCTION: |
1487 | 0 | curExpr = ET_FUNCTION_ASSIGN; |
1488 | 0 | break; |
1489 | 0 | case TOK_PLUS: |
1490 | 0 | if ( |
1491 | 0 | prevTok==TOK_RIGHT_CURVE || prevTok==TOK_RIGHT_BRACKET || |
1492 | 0 | prevTok==TOK_IDENTIFIER || prevTok==TOK_NUMBER || |
1493 | 0 | prevTok==TOK_STRING || prevTok==TOK_INCREMENT || |
1494 | 0 | prevTok==TOK_DECREMENT |
1495 | 0 | ) { |
1496 | 0 | curExpr = ET_PLUS; |
1497 | 0 | } else { |
1498 | 0 | goto skip_token; |
1499 | 0 | } |
1500 | 0 | break; |
1501 | 0 | case TOK_MINUS: |
1502 | 0 | if ( |
1503 | 0 | prevTok==TOK_RIGHT_CURVE || prevTok==TOK_RIGHT_BRACKET || |
1504 | 0 | prevTok==TOK_IDENTIFIER || prevTok==TOK_NUMBER || |
1505 | 0 | prevTok==TOK_STRING || prevTok==TOK_INCREMENT || |
1506 | 0 | prevTok==TOK_DECREMENT |
1507 | 0 | ) { |
1508 | 0 | curExpr = ET_MINUS; |
1509 | 0 | } else { |
1510 | 0 | curExpr = ET_NEGATIVE; |
1511 | 0 | curTok = TOK_NEGATIVE; |
1512 | 0 | } |
1513 | 0 | break; |
1514 | 0 | case TOK_INCREMENT: |
1515 | 0 | curExpr = ET_INCREMENT; |
1516 | 0 | break; |
1517 | 0 | case TOK_DECREMENT: |
1518 | 0 | curExpr = ET_DECREMENT; |
1519 | 0 | break; |
1520 | 0 | case TOK_NOT: |
1521 | 0 | curExpr = ET_NOT; |
1522 | 0 | break; |
1523 | 0 | case TOK_ONESCOMP: |
1524 | 0 | curExpr = ET_ONESCOMP; |
1525 | 0 | break; |
1526 | 0 | case TOK_CONDTEST: |
1527 | 0 | curExpr = ET_CONDTEST; |
1528 | 0 | break; |
1529 | 0 | case TOK_CONDSEP: |
1530 | 0 | break; |
1531 | 0 | case TOK_LEFT_BRACE: |
1532 | 0 | curExpr = ET_CURVED_EXPR; |
1533 | 0 | n = MoveToToken(sc_enc, TOK_RIGHT_BRACE, n, end); |
1534 | 0 | curTok = TOK_RIGHT_BRACE; |
1535 | 0 | break; |
1536 | 0 | break; |
1537 | 0 | default: |
1538 | |
|
1539 | 0 | if (curTok && (curTok != TOK_VAR) |
1540 | 0 | && (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 | 0 | } |
1545 | 0 | curExpr = TOK_To_ET(curTok); |
1546 | 0 | } |
1547 | | |
1548 | 0 | if (curTok == TOK_CONDSEP) { |
1549 | 0 | prevTok = curTok; |
1550 | 0 | curTok = sc_enc->expr_toks[++n]; |
1551 | 0 | continue; |
1552 | 0 | } |
1553 | 0 | curRank = ET_Rank[curExpr]; |
1554 | 0 | if (curRank > maxRank) { |
1555 | 0 | maxRank = curRank; |
1556 | 0 | expr = curExpr; |
1557 | 0 | finalPos = curPos; |
1558 | 0 | } else if (curRank == maxRank && ET_leftAssoc[curRank]) { |
1559 | 0 | expr = curExpr; |
1560 | 0 | finalPos = curPos; |
1561 | 0 | } |
1562 | 0 | prevTok = curTok; |
1563 | 0 | skip_token: |
1564 | 0 | curTok = sc_enc->expr_toks[++n]; |
1565 | 0 | } while (n<end); |
1566 | | |
1567 | 0 | if (expr == ET_INCREMENT) { |
1568 | 0 | if (finalPos==start) {} |
1569 | 0 | else if (finalPos==end-1) expr = ET_POST_INCREMENT; |
1570 | 0 | 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 | 0 | } |
1575 | 0 | } else if (expr == ET_DECREMENT) { |
1576 | 0 | if (finalPos==start) {} |
1577 | 0 | else if (finalPos==end-1) expr = ET_POST_DECREMENT; |
1578 | 0 | 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 | 0 | } |
1583 | 0 | } |
1584 | | |
1585 | 0 | SFE_WRITE_INT(sc_enc, expr, NUMBITS_EXPR_TYPE, "expressionType", (char *) expr_name[expr]); |
1586 | |
|
1587 | 0 | switch (expr) { |
1588 | 0 | case ET_MULTIPLY: |
1589 | 0 | case ET_DIVIDE: |
1590 | 0 | case ET_MOD: |
1591 | 0 | case ET_PLUS: |
1592 | 0 | case ET_MINUS: |
1593 | 0 | case ET_LSHIFT: |
1594 | 0 | case ET_RSHIFT: |
1595 | 0 | case ET_RSHIFTFILL: |
1596 | 0 | case ET_LT: |
1597 | 0 | case ET_LE: |
1598 | 0 | case ET_GT: |
1599 | 0 | case ET_GE: |
1600 | 0 | case ET_EQ: |
1601 | 0 | case ET_NE: |
1602 | 0 | case ET_AND: |
1603 | 0 | case ET_XOR: |
1604 | 0 | case ET_OR: |
1605 | 0 | case ET_LAND: |
1606 | 0 | case ET_LOR: |
1607 | 0 | SFE_Expression(sc_enc, start, finalPos, GF_FALSE); |
1608 | 0 | SFE_Expression(sc_enc, finalPos+1, end, GF_FALSE); |
1609 | 0 | break; |
1610 | 0 | case ET_ASSIGN: |
1611 | 0 | case ET_PLUSEQ: |
1612 | 0 | case ET_MINUSEQ: |
1613 | 0 | case ET_MULTIPLYEQ: |
1614 | 0 | case ET_DIVIDEEQ: |
1615 | 0 | case ET_MODEQ: |
1616 | 0 | case ET_LSHIFTEQ: |
1617 | 0 | case ET_RSHIFTEQ: |
1618 | 0 | case ET_RSHIFTFILLEQ: |
1619 | 0 | case ET_ANDEQ: |
1620 | 0 | case ET_XOREQ: |
1621 | 0 | case ET_OREQ: |
1622 | 0 | { |
1623 | 0 | u32 ret = SFE_Expression(sc_enc, start, finalPos, GF_FALSE); |
1624 | 0 | 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 | 0 | } |
1629 | 0 | SFE_Expression(sc_enc, finalPos+1, end, GF_FALSE); |
1630 | 0 | } |
1631 | 0 | break; |
1632 | | |
1633 | 0 | case ET_IDENTIFIER: |
1634 | 0 | str = (char *)gf_list_get(sc_enc->id_buf, 0); |
1635 | 0 | 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 | 0 | if (memberAccess) { |
1639 | 0 | } |
1640 | 0 | SFE_PutIdentifier(sc_enc, str); |
1641 | 0 | gf_free(str); |
1642 | 0 | break; |
1643 | 0 | case ET_NUMBER: |
1644 | 0 | str = (char *)gf_list_get(sc_enc->id_buf, 0); |
1645 | 0 | gf_list_rem(sc_enc->id_buf, 0); |
1646 | 0 | SFE_PutNumber(sc_enc, str); |
1647 | 0 | gf_free(str); |
1648 | 0 | break; |
1649 | 0 | case ET_BOOLEAN: |
1650 | 0 | str = (char *)gf_list_get(sc_enc->id_buf, 0); |
1651 | 0 | gf_list_rem(sc_enc->id_buf, 0); |
1652 | 0 | SFE_PutBoolean(sc_enc, str); |
1653 | 0 | gf_free(str); |
1654 | 0 | break; |
1655 | 0 | case ET_VAR: |
1656 | 0 | while (1) { |
1657 | 0 | str = (char *)gf_list_get(sc_enc->id_buf, 0); |
1658 | 0 | if (!str) break; |
1659 | 0 | gf_list_rem(sc_enc->id_buf, 0); |
1660 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "hasArgument", NULL); |
1661 | 0 | SFE_PutIdentifier(sc_enc, str); |
1662 | 0 | gf_free(str); |
1663 | 0 | } |
1664 | 0 | GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "hasArgument", NULL); |
1665 | 0 | break; |
1666 | 0 | case ET_STRING: |
1667 | 0 | str = (char *)gf_list_get(sc_enc->id_buf, 0); |
1668 | 0 | gf_list_rem(sc_enc->id_buf, 0); |
1669 | 0 | if (!sc_enc->emul) gf_bifs_enc_name(sc_enc->codec, sc_enc->bs, str); |
1670 | 0 | gf_free(str); |
1671 | 0 | break; |
1672 | 0 | case ET_NEGATIVE: |
1673 | 0 | case ET_INCREMENT: |
1674 | 0 | case ET_DECREMENT: |
1675 | 0 | case ET_NOT: |
1676 | 0 | case ET_ONESCOMP: |
1677 | 0 | SFE_Expression(sc_enc, finalPos+1, end, GF_FALSE); |
1678 | 0 | break; |
1679 | 0 | case ET_CURVED_EXPR: |
1680 | 0 | SFE_CompoundExpression(sc_enc, finalPos+1, end-1, 0); |
1681 | 0 | break; |
1682 | 0 | case ET_POST_INCREMENT : |
1683 | 0 | case ET_POST_DECREMENT : |
1684 | 0 | SFE_Expression(sc_enc, start, finalPos, GF_FALSE); |
1685 | 0 | break; |
1686 | 0 | case ET_FUNCTION_CALL: |
1687 | 0 | SFE_FunctionCall(sc_enc, start, end); |
1688 | 0 | break; |
1689 | 0 | case ET_OBJECT_MEMBER_ACCESS : |
1690 | 0 | SFE_ObjectMemberAccess(sc_enc, start, finalPos, end); |
1691 | 0 | break; |
1692 | 0 | case ET_OBJECT_METHOD_CALL: |
1693 | 0 | SFE_ObjectMethodCall(sc_enc, start, finalPos, end); |
1694 | 0 | break; |
1695 | 0 | case ET_ARRAY_DEREFERENCE: |
1696 | 0 | SFE_ArrayDereference(sc_enc, start, finalPos, end); |
1697 | 0 | break; |
1698 | 0 | case ET_NEW: |
1699 | 0 | SFE_ObjectConstruct(sc_enc, start, finalPos, end); |
1700 | 0 | break; |
1701 | 0 | case ET_CONDTEST: |
1702 | 0 | SFE_ConditionTest(sc_enc, start, finalPos, end); |
1703 | 0 | break; |
1704 | 0 | case ET_FUNCTION_ASSIGN: |
1705 | 0 | SFE_NextToken(sc_enc); |
1706 | 0 | SFE_CheckToken(sc_enc, TOK_LEFT_CURVE); |
1707 | |
|
1708 | 0 | SFE_Arguments(sc_enc); |
1709 | 0 | SFE_StatementBlock(sc_enc); |
1710 | 0 | SFE_NextToken(sc_enc); |
1711 | 0 | SFE_CheckToken(sc_enc, TOK_SEMICOLON); |
1712 | 0 | 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 | 0 | } |
1718 | 0 | return expr; |
1719 | 0 | } |
1720 | | |
1721 | | |
1722 | | void SFE_FunctionCall(ScriptEnc *sc_enc, u32 start, u32 end) |
1723 | 0 | { |
1724 | 0 | u32 curTok; |
1725 | 0 | char *str; |
1726 | 0 | curTok = sc_enc->expr_toks[start++]; |
1727 | 0 | CHECK_TOK(TOK_IDENTIFIER); |
1728 | 0 | str = (char *)gf_list_get(sc_enc->id_buf, 0); |
1729 | 0 | gf_list_rem(sc_enc->id_buf, 0); |
1730 | 0 | SFE_PutIdentifier(sc_enc, str); |
1731 | 0 | gf_free(str); |
1732 | 0 | curTok = sc_enc->expr_toks[start++]; |
1733 | 0 | CHECK_TOK(TOK_LEFT_CURVE); |
1734 | 0 | SFE_Params(sc_enc, start, end-1); |
1735 | 0 | curTok = sc_enc->expr_toks[end-1]; |
1736 | 0 | CHECK_TOK(TOK_RIGHT_CURVE); |
1737 | 0 | } |
1738 | | |
1739 | | void SFE_ObjectMemberAccess(ScriptEnc *sc_enc, u32 start, u32 op, u32 end) |
1740 | 0 | { |
1741 | 0 | u32 curTok; |
1742 | 0 | char *str; |
1743 | |
|
1744 | 0 | SFE_Expression(sc_enc, start, op, GF_TRUE); |
1745 | 0 | curTok = sc_enc->expr_toks[op]; |
1746 | 0 | CHECK_TOK(TOK_PERIOD); |
1747 | 0 | curTok = sc_enc->expr_toks[end-1]; |
1748 | 0 | CHECK_TOK(TOK_IDENTIFIER); |
1749 | 0 | str = (char *)gf_list_get(sc_enc->id_buf, 0); |
1750 | 0 | gf_list_rem(sc_enc->id_buf, 0); |
1751 | 0 | SFE_PutIdentifier(sc_enc, str); |
1752 | 0 | gf_free(str); |
1753 | 0 | } |
1754 | | |
1755 | | void SFE_ObjectMethodCall(ScriptEnc *sc_enc, u32 start, u32 op, u32 end) |
1756 | 0 | { |
1757 | 0 | u32 curTok; |
1758 | 0 | char *str; |
1759 | |
|
1760 | 0 | SFE_Expression(sc_enc, start, op, GF_FALSE); |
1761 | 0 | curTok = sc_enc->expr_toks[op]; |
1762 | 0 | CHECK_TOK(TOK_PERIOD); |
1763 | 0 | curTok = sc_enc->expr_toks[op+1]; |
1764 | 0 | CHECK_TOK(TOK_IDENTIFIER); |
1765 | 0 | str = (char *)gf_list_get(sc_enc->id_buf, 0); |
1766 | 0 | gf_list_rem(sc_enc->id_buf, 0); |
1767 | 0 | SFE_PutIdentifier(sc_enc, str); |
1768 | 0 | gf_free(str); |
1769 | 0 | curTok = sc_enc->expr_toks[op+2]; |
1770 | 0 | CHECK_TOK(TOK_LEFT_CURVE); |
1771 | 0 | SFE_Params(sc_enc, op+3, end-1); |
1772 | 0 | curTok = sc_enc->expr_toks[end-1]; |
1773 | 0 | CHECK_TOK(TOK_RIGHT_CURVE); |
1774 | 0 | } |
1775 | | |
1776 | | void SFE_ArrayDereference(ScriptEnc *sc_enc, u32 start, u32 op, u32 end) |
1777 | 0 | { |
1778 | 0 | u32 curTok; |
1779 | |
|
1780 | 0 | SFE_Expression(sc_enc, start, op, GF_FALSE); |
1781 | 0 | curTok = sc_enc->expr_toks[op]; |
1782 | 0 | CHECK_TOK(TOK_LEFT_BRACKET); |
1783 | 0 | SFE_CompoundExpression(sc_enc, op+1, end-1, 0); |
1784 | 0 | curTok = sc_enc->expr_toks[end-1]; |
1785 | 0 | CHECK_TOK(TOK_RIGHT_BRACKET); |
1786 | 0 | } |
1787 | | |
1788 | | void SFE_ObjectConstruct(ScriptEnc *sc_enc, u32 start, u32 op, u32 end) |
1789 | 0 | { |
1790 | 0 | u32 curTok; |
1791 | 0 | char *str; |
1792 | |
|
1793 | 0 | curTok = sc_enc->expr_toks[start++]; |
1794 | 0 | CHECK_TOK(TOK_NEW); |
1795 | 0 | curTok = sc_enc->expr_toks[start++]; |
1796 | 0 | CHECK_TOK(TOK_IDENTIFIER); |
1797 | 0 | str = (char *)gf_list_get(sc_enc->id_buf, 0); |
1798 | 0 | gf_list_rem(sc_enc->id_buf, 0); |
1799 | 0 | SFE_PutIdentifier(sc_enc, str); |
1800 | 0 | gf_free(str); |
1801 | 0 | curTok = sc_enc->expr_toks[start++]; |
1802 | 0 | CHECK_TOK(TOK_LEFT_CURVE); |
1803 | 0 | SFE_Params(sc_enc, start, end-1); |
1804 | 0 | curTok = sc_enc->expr_toks[end-1]; |
1805 | 0 | CHECK_TOK(TOK_RIGHT_CURVE); |
1806 | 0 | } |
1807 | | |
1808 | | void SFE_ConditionTest(ScriptEnc *sc_enc, u32 start, u32 op, u32 end) |
1809 | 0 | { |
1810 | 0 | u32 curTok; |
1811 | |
|
1812 | 0 | SFE_Expression(sc_enc, start, op, GF_FALSE); |
1813 | 0 | curTok = sc_enc->expr_toks[op]; |
1814 | 0 | CHECK_TOK(TOK_CONDTEST); |
1815 | 0 | start = op+1; |
1816 | 0 | op = MoveToToken(sc_enc, TOK_CONDSEP, op, end-1); |
1817 | 0 | SFE_Expression(sc_enc, start, op, GF_FALSE); |
1818 | 0 | curTok = sc_enc->expr_toks[op]; |
1819 | 0 | CHECK_TOK(TOK_CONDSEP); |
1820 | 0 | SFE_Expression(sc_enc, op+1, end, GF_FALSE); |
1821 | 0 | } |
1822 | | |
1823 | | void SFE_Params(ScriptEnc *sc_enc, u32 start, u32 end) |
1824 | 0 | { |
1825 | 0 | u32 curTok; |
1826 | |
|
1827 | 0 | curTok = sc_enc->expr_toks[start]; |
1828 | 0 | if (curTok != TOK_RIGHT_CURVE) { |
1829 | 0 | SFE_WRITE_INT(sc_enc, 1, 1, "hasParam", NULL); |
1830 | 0 | SFE_CompoundExpression(sc_enc, start, end, 1); |
1831 | 0 | } else { |
1832 | 0 | SFE_WRITE_INT(sc_enc, 0, 1, "hasParam", NULL); |
1833 | 0 | } |
1834 | 0 | } |
1835 | | |
1836 | | #endif /* !defined(GPAC_DISABLE_BIFS) && !defined(GPAC_DISABLE_BIFS_ENC) && defined(GPAC_HAS_QJS) */ |