This source file includes following definitions.
- SFS_AddString
- SFS_AddInt
- SFS_AddChar
- ParseScriptField
- SFS_IncIndent
- SFS_DecIndent
- SFS_Space
- SFS_Indent
- SFS_Line
- SFScript_Parse
- SFS_Identifier
- SFS_Arguments
- SFS_StatementBlock
- SFS_Statement
- SFS_IfStatement
- SFS_SwitchStatement
- SFS_ForStatement
- SFS_WhileStatement
- SFS_ReturnStatement
- SFS_CompoundExpression
- SFS_OptionalExpression
- SFS_Expression
- SFS_NewObject
- SFS_ArrayDeref
- SFS_FunctionCall
- SFS_ObjectMemberAccess
- SFS_ObjectMethodCall
- SFS_Params
- SFS_GetNumber
- SFS_GetString
- SFS_GetBoolean
#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;
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;
}
}
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;
if (gf_bs_read_int(bs, 1)) {
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;
}
}
gf_bs_read_int(bs, 1);
SFS_AddString(&parser, "javascript:");
SFS_AddString(&parser, parser.new_line);
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:
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;
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));
}
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);
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));
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;
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;
}
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