LCOV - code coverage report
Current view: top level - bifs - script_enc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 756 864 87.5 %
Date: 2021-04-29 23:48:07 Functions: 35 36 97.2 %

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

Generated by: LCOV version 1.13