root/src/bifs/script_dec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SFS_AddString
  2. SFS_AddInt
  3. SFS_AddChar
  4. ParseScriptField
  5. SFS_IncIndent
  6. SFS_DecIndent
  7. SFS_Space
  8. SFS_Indent
  9. SFS_Line
  10. SFScript_Parse
  11. SFS_Identifier
  12. SFS_Arguments
  13. SFS_StatementBlock
  14. SFS_Statement
  15. SFS_IfStatement
  16. SFS_SwitchStatement
  17. SFS_ForStatement
  18. SFS_WhileStatement
  19. SFS_ReturnStatement
  20. SFS_CompoundExpression
  21. SFS_OptionalExpression
  22. SFS_Expression
  23. SFS_NewObject
  24. SFS_ArrayDeref
  25. SFS_FunctionCall
  26. SFS_ObjectMemberAccess
  27. SFS_ObjectMethodCall
  28. SFS_Params
  29. SFS_GetNumber
  30. SFS_GetString
  31. SFS_GetBoolean

/*
 *                      GPAC - Multimedia Framework C SDK
 *
 *                      Authors: Jean Le Feuvre
 *                      Copyright (c) Telecom ParisTech 2000-2012
 *                                      All rights reserved
 *
 *  This file is part of GPAC / BIFS codec sub-project
 *
 *  GPAC is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  GPAC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#include "script.h"

#if !defined(GPAC_DISABLE_BIFS) && defined(GPAC_HAS_SPIDERMONKEY)

#define BINOP_MINVAL ET_EQ

typedef struct
{
        GF_Node *script;
        GF_BifsDecoder *codec;
        GF_BitStream *bs;
        char *string;
        u32 length;
        GF_List *identifiers;
        char *new_line;
        u32 indent;
} ScriptParser;


void SFS_Identifier(ScriptParser *parser);
void SFS_Arguments(ScriptParser *parser, Bool is_var);
void SFS_StatementBlock(ScriptParser *parser, Bool functBody);
void SFS_Statement(ScriptParser *parser);
void SFS_IfStatement(ScriptParser *parser);
void SFS_SwitchStatement(ScriptParser *parser);
void SFS_ForStatement(ScriptParser *parser);
void SFS_WhileStatement(ScriptParser *parser);
void SFS_ReturnStatement(ScriptParser *parser);
void SFS_CompoundExpression(ScriptParser *parser);
void SFS_OptionalExpression(ScriptParser *parser);
void SFS_Expression(ScriptParser *parser);
void SFS_NewObject(ScriptParser *parser);
void SFS_ArrayDeref(ScriptParser *parser);
void SFS_FunctionCall(ScriptParser *parser);
void SFS_ObjectMemberAccess(ScriptParser *parser);
void SFS_ObjectMethodCall(ScriptParser *parser);
void SFS_Params(ScriptParser *parser);
void SFS_GetNumber(ScriptParser *parser);
void SFS_GetString(ScriptParser *parser);
void SFS_GetBoolean(ScriptParser *parser);

#define PARSER_STEP_ALLOC       500

static void SFS_AddString(ScriptParser *parser, char *str)
{
        char *new_str;
        if (!str) return;
        if (strlen(parser->string) + strlen(str) >= parser->length) {
                parser->length += PARSER_STEP_ALLOC;
                new_str = (char *)gf_malloc(sizeof(char)*parser->length);
                strcpy(new_str, parser->string);
                gf_free(parser->string);
                parser->string = new_str;
        }
        strcat(parser->string, str);
}

static void SFS_AddInt(ScriptParser *parser, s32 val)
{
        char msg[500];
        sprintf(msg, "%d", val);
        SFS_AddString(parser, msg);
}
static void SFS_AddChar(ScriptParser *parser, char c)
{
        char msg[2];
        sprintf(msg, "%c", c);
        SFS_AddString(parser, msg);
}


GF_Err ParseScriptField(ScriptParser *parser)
{
        GF_ScriptField *field;
        GF_Err e;
        u32 eventType, fieldType;
        char name[1000];
        GF_FieldInfo info;

        eventType = gf_bs_read_int(parser->bs, 2);
        fieldType = gf_bs_read_int(parser->bs, 6);
        gf_bifs_dec_name(parser->bs, name);
        field = gf_sg_script_field_new(parser->script, eventType, fieldType, name);
        if (!field) return GF_NON_COMPLIANT_BITSTREAM;

        //save the name in the list of identifiers
        gf_list_add(parser->identifiers, gf_strdup(name));

        if (parser->codec->pCurrentProto) {
                Bool isISfield = (Bool)gf_bs_read_int(parser->bs, 1);
                if (isISfield) {
                        u32 numProtoField = gf_sg_proto_get_field_count(parser->codec->pCurrentProto);
                        u32 numBits = gf_get_bit_size(numProtoField - 1);
                        u32 field_all = gf_bs_read_int(parser->bs, numBits);
                        e = gf_sg_script_field_get_info(field, &info);
                        if (e) return e;
                        e = gf_sg_proto_field_set_ised(parser->codec->pCurrentProto, field_all, parser->script, info.fieldIndex);
                        return e;
                }
        }
        /*get default value*/
        if (eventType == GF_SG_SCRIPT_TYPE_FIELD) {
                if (gf_bs_read_int(parser->bs, 1)) {
                        e = gf_sg_script_field_get_info(field, &info);
                        if (e) return e;
                        gf_bifs_dec_field(parser->codec, parser->bs, parser->script, &info, GF_FALSE);
                }
        }

        return parser->codec->LastError;
}

static void SFS_IncIndent(ScriptParser *pars) {
        pars->indent++;
}
static void SFS_DecIndent(ScriptParser *pars) {
        pars->indent--;
}
static void SFS_Space(ScriptParser *pars) {
        if (pars->new_line) SFS_AddString(pars, " ");
}
static void SFS_Indent(ScriptParser *pars)
{
        u32 i;
        if (pars->new_line) {
                for (i=0; i<pars->indent; i++) SFS_AddString(pars, " ");
        }
}
static GFINLINE void SFS_Line(ScriptParser *parser)
{
        if (parser->new_line) {
                SFS_AddString(parser, parser->new_line);
        }
}


GF_Err SFScript_Parse(GF_BifsDecoder *codec, SFScript *script_field, GF_BitStream *bs, GF_Node *n)
{
        GF_Err e;
        u32 i, count, nbBits;
        char *ptr;
        ScriptParser parser;
        e = GF_OK;
        if (gf_node_get_tag(n) != TAG_MPEG4_Script) return GF_NON_COMPLIANT_BITSTREAM;

        parser.codec = codec;
        parser.script = n;
        parser.bs = bs;
        parser.length = 500;
        parser.string = (char *) gf_malloc(sizeof(char)* parser.length);
        parser.string[0] = 0;
        parser.identifiers = gf_list_new();
        parser.new_line = (char *) (codec->dec_memory_mode ? "\n" : NULL);
        parser.indent = 0;

        //first parse fields

        if (gf_bs_read_int(bs, 1)) {
                //endFlag
                while (!gf_bs_read_int(bs, 1)) {
                        e = ParseScriptField(&parser);
                        if (e) goto exit;
                }
        } else {
                nbBits = gf_bs_read_int(bs, 4);
                count = gf_bs_read_int(bs, nbBits);
                for (i=0; i<count; i++) {
                        e = ParseScriptField(&parser);
                        if (e) goto exit;
                }
        }
        //reserevd
        gf_bs_read_int(bs, 1);
        //then parse
        SFS_AddString(&parser, "javascript:");
        SFS_AddString(&parser, parser.new_line);

        //hasFunction
        while (gf_bs_read_int(bs, 1)) {
                SFS_AddString(&parser, "function ");
                SFS_Identifier(&parser);
                SFS_Arguments(&parser, GF_FALSE);
                SFS_Space(&parser);
                SFS_StatementBlock(&parser, GF_TRUE);
                SFS_Line(&parser);
        }

        SFS_Line(&parser);

        if (script_field->script_text) gf_free(script_field->script_text);
        script_field->script_text = (char *) gf_strdup(parser.string);

exit:
        //clean up
        while (gf_list_count(parser.identifiers)) {
                ptr = (char *)gf_list_get(parser.identifiers, 0);
                gf_free(ptr);
                gf_list_rem(parser.identifiers, 0);
        }
        gf_list_del(parser.identifiers);
        if (parser.string) gf_free(parser.string);
        return e;
}



void SFS_Identifier(ScriptParser *parser)
{
        u32 index;
        char name[500];

        if (parser->codec->LastError) return;

        //received
        if (gf_bs_read_int(parser->bs, 1)) {
                index = gf_bs_read_int(parser->bs, gf_get_bit_size(gf_list_count(parser->identifiers) - 1));
                SFS_AddString(parser, (char *)gf_list_get(parser->identifiers, index));
        }
        //parse
        else {
                gf_bifs_dec_name(parser->bs, name);
                gf_list_add(parser->identifiers, gf_strdup(name));
                SFS_AddString(parser, name);
        }
}

void SFS_Arguments(ScriptParser *parser, Bool is_var)
{
        u32 val;
        if (parser->codec->LastError) return;
        if (!is_var) SFS_AddString(parser, "(");

        val = gf_bs_read_int(parser->bs, 1);
        while (val) {
                SFS_Identifier(parser);
                val = gf_bs_read_int(parser->bs, 1);
                if (val) SFS_AddString(parser, ",");
        }
        if (!is_var) SFS_AddString(parser, ")");
}

void SFS_StatementBlock(ScriptParser *parser, Bool funcBody)
{
        if (parser->codec->LastError) return;

        if (gf_bs_read_int(parser->bs, 1)) {
                SFS_AddString(parser, "{");
                SFS_IncIndent(parser);

                while (gf_bs_read_int(parser->bs, 1)) {
                        SFS_Line(parser);
                        SFS_Indent(parser);
                        SFS_Statement(parser);
                }
                SFS_DecIndent(parser);
                SFS_Line(parser);
                SFS_Indent(parser);
                SFS_AddString(parser, "}");
        } else if (funcBody) {
                SFS_AddString(parser, "{");
                SFS_Statement(parser);
                SFS_AddString(parser, "}");
        } else {
                SFS_Statement(parser);
        }
}


void SFS_Statement(ScriptParser *parser)
{
        u32 val;
        if (parser->codec->LastError) return;

        val = gf_bs_read_int(parser->bs, NUMBITS_STATEMENT);
        switch (val) {
        case ST_IF:
                SFS_IfStatement(parser);
                break;
        case ST_FOR:
                SFS_ForStatement(parser);
                break;
        case ST_WHILE:
                SFS_WhileStatement(parser);
                break;
        case ST_RETURN:
                SFS_ReturnStatement(parser);
                break;
        case ST_BREAK:
                SFS_AddString(parser, "break;");
                break;
        case ST_CONTINUE:
                SFS_AddString(parser, "continue;");
                break;
        case ST_COMPOUND_EXPR:
                SFS_CompoundExpression(parser);
                SFS_AddString(parser, ";");
                break;
        case ST_SWITCH:
                SFS_SwitchStatement(parser);
                break;
        }
}

void SFS_IfStatement(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_AddString(parser, "if (");
        SFS_CompoundExpression(parser);
        SFS_AddString(parser, ") ");
        SFS_StatementBlock(parser, GF_FALSE);
        //has else
        if (gf_bs_read_int(parser->bs, 1)) {
                SFS_Line(parser);
                SFS_Indent(parser);
                SFS_AddString(parser, "else ");
                SFS_StatementBlock(parser, GF_FALSE);
        }
}

void SFS_SwitchStatement(ScriptParser *parser)
{
        u32 numBits, caseValue;

        if (parser->codec->LastError) return;
        SFS_AddString(parser, "switch (");
        SFS_CompoundExpression(parser);
        SFS_AddString(parser, ")");
        SFS_AddString(parser, "{");
        SFS_Line(parser);

        numBits = gf_bs_read_int(parser->bs, 5);
        do {
                SFS_Indent(parser);
                SFS_AddString(parser, "case ");
                caseValue = gf_bs_read_int(parser->bs, numBits);
                SFS_AddInt(parser, caseValue);
                SFS_AddString(parser, ":");
                SFS_Line(parser);
                SFS_Indent(parser);
                SFS_StatementBlock(parser, GF_FALSE);
                SFS_Line(parser);
        }
        while (gf_bs_read_int(parser->bs, 1));

        //default
        if (gf_bs_read_int(parser->bs, 1)) {
                SFS_AddString(parser, "default:");
                SFS_Line(parser);
                SFS_StatementBlock(parser, GF_FALSE);
        }
        SFS_AddString(parser, "}");
}

void SFS_ForStatement(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_AddString(parser, "for (");
        SFS_OptionalExpression(parser);
        SFS_AddString(parser, ";");
        SFS_OptionalExpression(parser);
        SFS_AddString(parser, ";");
        SFS_OptionalExpression(parser);
        SFS_AddString(parser, ")");

        SFS_StatementBlock(parser, GF_FALSE);
}

void SFS_WhileStatement(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_AddString(parser, "while (");
        SFS_CompoundExpression(parser);
        SFS_AddString(parser, ")");

        SFS_StatementBlock(parser, GF_FALSE);
}

void SFS_ReturnStatement(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_AddString(parser, "return");
        if (gf_bs_read_int(parser->bs, 1)) {
                SFS_AddString(parser, " ");
                SFS_CompoundExpression(parser);
        }
        SFS_AddString(parser, ";");
        SFS_Line(parser);
}

void SFS_CompoundExpression(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_Expression(parser);
        if (! gf_bs_read_int(parser->bs, 1)) return;
        SFS_AddString(parser, ",");
        SFS_CompoundExpression(parser);
}

void SFS_OptionalExpression(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        if (gf_bs_read_int(parser->bs, 1)) {
                SFS_CompoundExpression(parser);
        }
}


void SFS_Expression(ScriptParser *parser)
{
        u32 val = gf_bs_read_int(parser->bs, NUMBITS_EXPR_TYPE);
        if (parser->codec->LastError) return;

        switch(val) {
        case ET_CURVED_EXPR:
                SFS_AddString(parser, "(");
                SFS_CompoundExpression(parser);
                SFS_AddString(parser, ")");
                break;
        case ET_NEGATIVE:
                SFS_AddString(parser, "-");
                SFS_Expression(parser);
                break;
        case ET_NOT:
                SFS_AddString(parser, "!");
                SFS_Expression(parser);
                break;
        case ET_ONESCOMP:
                SFS_AddString(parser, "~");
                SFS_Expression(parser);
                break;
        case ET_INCREMENT:
                SFS_AddString(parser, "++");
                SFS_Expression(parser);
                break;
        case ET_DECREMENT:
                SFS_AddString(parser, "--");
                SFS_Expression(parser);
                break;
        case ET_POST_INCREMENT:
                SFS_Expression(parser);
                SFS_AddString(parser, "++");
                break;
        case ET_POST_DECREMENT:
                SFS_Expression(parser);
                SFS_AddString(parser, "--");
                break;
        case ET_CONDTEST:
                SFS_Expression(parser);
                SFS_AddString(parser, " ? ");
                SFS_Expression(parser);
                SFS_AddString(parser, " : ");
                SFS_Expression(parser);
                break;
        case ET_STRING:
                SFS_AddString(parser, "'");
                SFS_GetString(parser);
                SFS_AddString(parser, "'");
                break;
        case ET_NUMBER:
                SFS_GetNumber(parser);
                break;
        case ET_IDENTIFIER:
                SFS_Identifier(parser);
                break;
        case ET_FUNCTION_CALL:
                SFS_FunctionCall(parser);
                break;
        case ET_NEW:
                SFS_NewObject(parser);
                break;
        case ET_OBJECT_MEMBER_ACCESS:
                SFS_ObjectMemberAccess(parser);
                break;
        case ET_OBJECT_METHOD_CALL:
                SFS_ObjectMethodCall(parser);
                break;
        case ET_ARRAY_DEREFERENCE:
                SFS_ArrayDeref(parser);
                break;

        case ET_MULTIPLY:
                SFS_Expression(parser);
                SFS_AddString(parser, "*");
                SFS_Expression(parser);
                break;
        case ET_DIVIDE:
                SFS_Expression(parser);
                SFS_AddString(parser, "/");
                SFS_Expression(parser);
                break;
        case ET_MOD:
                SFS_Expression(parser);
                SFS_AddString(parser, "%");
                SFS_Expression(parser);
                break;
        case ET_PLUS:
                SFS_Expression(parser);
                SFS_AddString(parser, "+");
                SFS_Expression(parser);
                break;
        case ET_MINUS:
                SFS_Expression(parser);
                SFS_AddString(parser, "-");
                SFS_Expression(parser);
                break;
        case ET_LSHIFT:
                SFS_Expression(parser);
                SFS_AddString(parser, "<<");
                SFS_Expression(parser);
                break;
        case ET_RSHIFT:
                SFS_Expression(parser);
                SFS_AddString(parser, ">>");
                SFS_Expression(parser);
                break;
        case ET_RSHIFTFILL:
                SFS_Expression(parser);
                SFS_AddString(parser, ">>>");
                SFS_Expression(parser);
                break;
        case ET_AND:
                SFS_Expression(parser);
                SFS_AddString(parser, "&");
                SFS_Expression(parser);
                break;
        case ET_XOR:
                SFS_Expression(parser);
                SFS_AddString(parser, "^");
                SFS_Expression(parser);
                break;
        case ET_OR:
                SFS_Expression(parser);
                SFS_AddString(parser, "|");
                SFS_Expression(parser);
                break;
        case ET_LT:
                SFS_Expression(parser);
                SFS_AddString(parser, "<");
                SFS_Expression(parser);
                break;
        case ET_LE:
                SFS_Expression(parser);
                SFS_AddString(parser, "<=");
                SFS_Expression(parser);
                break;
        case ET_GT:
                SFS_Expression(parser);
                SFS_AddString(parser, ">");
                SFS_Expression(parser);
                break;
        case ET_GE:
                SFS_Expression(parser);
                SFS_AddString(parser, ">=");
                SFS_Expression(parser);
                break;
        case ET_EQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "==");
                SFS_Expression(parser);
                break;
        case ET_NE:
                SFS_Expression(parser);
                SFS_AddString(parser, "!=");
                SFS_Expression(parser);
                break;
        case ET_LAND:
                SFS_Expression(parser);
                SFS_AddString(parser, "&&");
                SFS_Expression(parser);
                break;
        case ET_LOR:
                SFS_Expression(parser);
                SFS_AddString(parser, "||");
                SFS_Expression(parser);
                break;
        case ET_ASSIGN:
                SFS_Expression(parser);
                SFS_AddString(parser, "=");
                SFS_Expression(parser);
                break;
        case ET_PLUSEQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "+=");
                SFS_Expression(parser);
                break;
        case ET_MINUSEQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "-=");
                SFS_Expression(parser);
                break;
        case ET_MULTIPLYEQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "*=");
                SFS_Expression(parser);
                break;
        case ET_DIVIDEEQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "/=");
                SFS_Expression(parser);
                break;
        case ET_MODEQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "%=");
                SFS_Expression(parser);
                break;
        case ET_LSHIFTEQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "<<=");
                SFS_Expression(parser);
                break;
        case ET_RSHIFTEQ:
                SFS_Expression(parser);
                SFS_AddString(parser, ">>=");
                SFS_Expression(parser);
                break;
        case ET_RSHIFTFILLEQ:
                SFS_Expression(parser);
                SFS_AddString(parser, ">>>=");
                SFS_Expression(parser);
                break;
        case ET_ANDEQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "&=");
                SFS_Expression(parser);
                break;
        case ET_XOREQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "^=");
                SFS_Expression(parser);
                break;
        case ET_OREQ:
                SFS_Expression(parser);
                SFS_AddString(parser, "|=");
                SFS_Expression(parser);
                break;
        case ET_BOOLEAN:
                SFS_GetBoolean(parser);
                break;
        case ET_VAR:
                SFS_AddString(parser, "var ");
                SFS_Arguments(parser, GF_TRUE);
                break;
        case ET_FUNCTION_ASSIGN:
                SFS_AddString(parser, "function ");
                SFS_Arguments(parser, GF_FALSE);
                SFS_StatementBlock(parser, GF_TRUE);
                break;
        default:
                assert(0);
                break;
        }
}

void SFS_NewObject(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_AddString(parser, "new ");
        SFS_Identifier(parser);
        SFS_AddString(parser, "(");
        SFS_Params(parser);
        SFS_AddString(parser, ") ");
}

void SFS_ArrayDeref(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_Expression(parser);
        SFS_AddString(parser, "[");
        SFS_CompoundExpression(parser);
        SFS_AddString(parser, "]");
}

void SFS_FunctionCall(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_Identifier(parser);
        SFS_AddString(parser, "(");
        SFS_Params(parser);
        SFS_AddString(parser, ")");
}

void SFS_ObjectMemberAccess(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_Expression(parser);
        SFS_AddString(parser, ".");
        SFS_Identifier(parser);
}


void SFS_ObjectMethodCall(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        SFS_Expression(parser);
        SFS_AddString(parser, ".");
        SFS_Identifier(parser);
        SFS_AddString(parser, "(");
        SFS_Params(parser);
        SFS_AddString(parser, ")");
}

void SFS_Params(ScriptParser *parser)
{
        u32 val;
        if (parser->codec->LastError) return;
        val = gf_bs_read_int(parser->bs, 1);
        while (val) {
                SFS_Expression(parser);
                val = gf_bs_read_int(parser->bs, 1);
                if(val) SFS_AddString(parser, ",");
        }
}

void SFS_GetNumber(ScriptParser *parser)
{
        u32 val, nbBits;

        if (parser->codec->LastError) return;
        // integer
        if (gf_bs_read_int(parser->bs, 1)) {
                nbBits = gf_bs_read_int(parser->bs, 5);
                val = gf_bs_read_int(parser->bs, nbBits);
                SFS_AddInt(parser, val);
                return;
        }
        // real number
        val = gf_bs_read_int(parser->bs, 4);
        while ( val != 15) {
                if (val<=9) {
                        SFS_AddChar(parser, (char) (val + '0') );
                } else if (val==10) {
                        SFS_AddChar(parser, '.');
                } else if (val==11) {
                        SFS_AddChar(parser, 'E');
                } else if (val==12) {
                        SFS_AddChar(parser, '-');
                }
                val = gf_bs_read_int(parser->bs, 4);
        }
}

void SFS_GetString(ScriptParser *parser)
{
        char name[1000];
        if (parser->codec->LastError) return;
        gf_bifs_dec_name(parser->bs, name);
        SFS_AddString(parser, name);
}

void SFS_GetBoolean(ScriptParser *parser)
{
        if (parser->codec->LastError) return;
        if (gf_bs_read_int(parser->bs, 1)) {
                SFS_AddString(parser, "true");
        } else {
                SFS_AddString(parser, "false");
        }
}

#endif /*!defined(GPAC_DISABLE_BIFS) && defined(GPAC_HAS_SPIDERMONKEY)*/

/* [<][>][^][v][top][bottom][index][help] */