Coverage Report

Created: 2025-10-10 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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) */