/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * 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" #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 *)malloc(sizeof(char)*parser->length); strcpy(new_str, parser->string); 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, strdup(name)); if (parser->codec->pCurrentProto) { Bool isISfield = 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); } } 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; iindent; 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; Bool has_fields = 0; 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 *) 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 has_fields = 1; } } else { nbBits = gf_bs_read_int(bs, 4); count = gf_bs_read_int(bs, nbBits); for (i=0; iscript_text) free(script_field->script_text); script_field->script_text = (unsigned char *) strdup(parser.string); exit: //clean up while (gf_list_count(parser.identifiers)) { ptr = (char *)gf_list_get(parser.identifiers, 0); free(ptr); gf_list_rem(parser.identifiers, 0); } gf_list_del(parser.identifiers); if (parser.string) free(parser.string); return e; } void SFS_Identifier(ScriptParser *parser) { u32 index; char name[500]; if (parser->codec->LastError) return; //recieved 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, 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, 0); //has else if (gf_bs_read_int(parser->bs, 1)) { SFS_Line(parser); SFS_Indent(parser); SFS_AddString(parser, "else "); SFS_StatementBlock(parser, 0); } } 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, 0); 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, 0); } 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, 0); } void SFS_WhileStatement(ScriptParser *parser) { if (parser->codec->LastError) return; SFS_AddString(parser, "while ("); SFS_CompoundExpression(parser); SFS_AddString(parser, ")"); SFS_StatementBlock(parser, 0); } 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, 1); break; case ET_FUNCTION_ASSIGN: SFS_AddString(parser, "function "); SFS_Arguments(parser, 0); SFS_StatementBlock(parser, 1); 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>=0 && 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"); } }