This source file includes following definitions.
- EncScriptFields
- SFE_GetNumber
- SFE_NextToken
- SFE_CheckToken
- SFE_PutIdentifier
- SFE_Arguments
- SFE_PutInteger
- SFE_LoadExpression
- SFE_ScanExpression
- SFE_CompoundExpression
- SFE_OptionalExpression
- SFE_IfStatement
- SFE_ForStatement
- SFE_WhileStatement
- SFE_ReturnStatement
- SFE_CaseBlock
- SFE_PutCaseInteger
- SFE_SwitchStatement
- SFE_Statement
- SFE_Statements
- SFE_StatementBlock
- SFE_Function
- SFScript_Encode
- SFE_PutReal
- SFE_PutNumber
- SFE_PutBoolean
- TOK_To_ET
- MoveToToken
- SFE_Expression
- SFE_FunctionCall
- SFE_ObjectMemberAccess
- SFE_ObjectMethodCall
- SFE_ArrayDereference
- SFE_ObjectConstruct
- SFE_ConditionTest
- SFE_Params
#include "script.h"
#include <gpac/internal/scenegraph_dev.h>
#if !defined(GPAC_DISABLE_BIFS) && !defined(GPAC_DISABLE_BIFS_ENC) && defined(GPAC_HAS_SPIDERMONKEY)
typedef struct
{
GF_Node *script;
GF_BifsEncoder *codec;
GF_BitStream *bs;
GF_List *identifiers;
GF_Err err;
char *cur_buf;
char token[500];
u32 token_code;
u32 cur_line;
Bool emul;
char expr_toks[500];
u32 expr_toks_len;
GF_List *id_buf;
} ScriptEnc;
#define SFE_WRITE_INT(sc_enc, val, nbBits, str1, str2) \
if (!sc_enc->emul) GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, val, nbBits, str1, str2); \
static GF_Err EncScriptFields(ScriptEnc *sc_enc)
{
u32 nbFields, nbBits, eType, nbBitsProto, i;
Bool use_list;
GF_Err e;
GF_FieldInfo info;
nbFields = gf_node_get_num_fields_in_mode(sc_enc->script, GF_SG_FIELD_CODING_ALL) - 3;
use_list = GF_TRUE;
nbBits = gf_get_bit_size(nbFields);
if (nbFields+1 > 4 + gf_get_bit_size(nbFields)) use_list = GF_FALSE;
if (!nbFields) {
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "Script::isList", NULL);
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "end", NULL);
return GF_OK;
}
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, use_list ? 1 : 0, 1, "Script::isList", NULL);
if (!use_list) {
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, nbBits, 4, "nbBits", NULL);
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, nbFields, nbBits, "count", NULL);
}
nbBitsProto = 0;
if (sc_enc->codec->encoding_proto) nbBitsProto = gf_get_bit_size(gf_sg_proto_get_field_count(sc_enc->codec->encoding_proto) - 1);
for (i=0; i<nbFields; i++) {
if (use_list) GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "end", NULL);
gf_node_get_field(sc_enc->script, i+3, &info);
switch (info.eventType) {
case GF_SG_EVENT_IN:
eType = GF_SG_SCRIPT_TYPE_EVENT_IN;
break;
case GF_SG_EVENT_OUT:
eType = GF_SG_SCRIPT_TYPE_EVENT_OUT;
break;
default:
eType = GF_SG_SCRIPT_TYPE_FIELD;
break;
}
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, eType, 2, "eventType", NULL);
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, info.fieldType, 6, "fieldType", NULL);
gf_bifs_enc_name(sc_enc->codec, sc_enc->bs, (char *) info.name);
gf_list_add(sc_enc->identifiers, gf_strdup(info.name));
if (sc_enc->codec->encoding_proto) {
GF_Route *isedField = gf_bifs_enc_is_field_ised(sc_enc->codec, sc_enc->script, i+3);
if (isedField) {
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "isedField", NULL);
if (isedField->ToNode == sc_enc->script) {
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, isedField->FromField.fieldIndex, nbBitsProto, "protoField", NULL);
} else {
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, isedField->ToField.fieldIndex, nbBitsProto, "protoField", NULL);
}
continue;
}
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "isedField", NULL);
}
if (eType == GF_SG_SCRIPT_TYPE_FIELD) {
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, (info.far_ptr) ? 1 : 0, 1, "hasInitialValue", NULL);
if (info.far_ptr) {
e = gf_bifs_enc_field(sc_enc->codec, sc_enc->bs, sc_enc->script, &info);
if (e) return e;
}
}
}
if (use_list) GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "end", NULL);
return GF_OK;
}
enum
{
TOK_FUNCTION,
TOK_IF,
TOK_ELSE,
TOK_FOR,
TOK_WHILE,
TOK_RETURN,
TOK_BREAK,
TOK_CONTINUE,
TOK_NEW,
TOK_SWITCH,
TOK_CASE,
TOK_DEFAULT,
TOK_VAR,
NUMBER_OF_KEYWORD,
TOK_LEFT_BRACE = NUMBER_OF_KEYWORD,
TOK_RIGHT_BRACE,
TOK_LEFT_CURVE,
TOK_RIGHT_CURVE,
TOK_LEFT_BRACKET,
TOK_RIGHT_BRACKET,
TOK_PERIOD,
TOK_NOT,
TOK_ONESCOMP,
TOK_NEGATIVE,
TOK_INCREMENT,
TOK_DECREMENT,
TOK_MULTIPLY,
TOK_DIVIDE,
TOK_MOD,
TOK_PLUS,
TOK_MINUS,
TOK_LSHIFT,
TOK_RSHIFT,
TOK_RSHIFTFILL,
TOK_LT,
TOK_LE,
TOK_GT,
TOK_GE,
TOK_EQ,
TOK_NE,
TOK_AND,
TOK_XOR,
TOK_OR,
TOK_LAND,
TOK_LOR,
TOK_CONDTEST,
TOK_ASSIGN,
TOK_PLUSEQ,
TOK_MINUSEQ,
TOK_MULTIPLYEQ,
TOK_DIVIDEEQ,
TOK_MODEQ,
TOK_LSHIFTEQ,
TOK_RSHIFTEQ,
TOK_RSHIFTFILLEQ,
TOK_ANDEQ,
TOK_XOREQ,
TOK_OREQ,
TOK_COMMA,
TOK_SEMICOLON,
TOK_CONDSEP,
TOK_IDENTIFIER,
TOK_STRING,
TOK_NUMBER,
TOK_EOF,
TOK_BOOLEAN
};
const char *tok_names[] =
{
"function",
"if",
"else",
"for",
"while",
"return",
"break",
"continue",
"new",
"switch",
"case",
"default",
"var",
"{",
"}",
"(",
")",
"[",
"]",
".",
"!",
"~",
"-",
"++",
"--",
"*",
"/",
"%",
"+",
"-",
"<<",
">>",
">>>",
"<",
"<=",
">",
">=",
"==",
"!=",
"&",
"^",
"|",
"&&",
"||",
"?",
"=",
"+=",
"-=",
"*=",
"/=",
"%=",
"<<=",
">>=",
">>>=",
"&=",
"^=",
"|=",
",",
";",
":",
"identifier",
"string",
"number",
"boolean",
"end of script"
};
const char* sc_keywords [] =
{
"function",
"if",
"else",
"for",
"while",
"return",
"break",
"continue",
"new",
"switch",
"case",
"default",
"var"
};
Bool SFE_GetNumber(ScriptEnc *sc_enc)
{
u32 i = 0;
Bool exp = GF_FALSE;
while ( isdigit(sc_enc->cur_buf[i])
|| (toupper(sc_enc->cur_buf[i])=='X')
|| ((toupper(sc_enc->cur_buf[i]) >='A') && (toupper(sc_enc->cur_buf[i])<='F'))
|| (sc_enc->cur_buf[i]=='.')
|| (tolower(sc_enc->cur_buf[i])=='e')
|| (exp && (sc_enc->cur_buf[i] == '-'))
) {
sc_enc->token[i] = sc_enc->cur_buf[i];
if (tolower(sc_enc->cur_buf[i])=='e') exp = GF_TRUE;
i++;
if (!sc_enc->cur_buf[i]) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Invalid number syntax (%s)\n", sc_enc->cur_buf));
sc_enc->err = GF_BAD_PARAM;
return GF_FALSE;
}
}
sc_enc->token[i] = 0;
sc_enc->cur_buf += i;
sc_enc->token_code = TOK_NUMBER;
return GF_TRUE;
}
Bool SFE_NextToken(ScriptEnc *sc_enc)
{
u32 i;
if (sc_enc->err) return GF_FALSE;
while (strchr(" \t\r\n", sc_enc->cur_buf[0])) {
if (sc_enc->cur_buf[0]=='\n') sc_enc->cur_line ++;
sc_enc->cur_buf++;
}
if ((sc_enc->cur_buf[0] == '/') && (sc_enc->cur_buf[1] == '*')) {
sc_enc->cur_buf += 2;
while ((sc_enc->cur_buf[0] != '*') || (sc_enc->cur_buf[1] != '/')) {
sc_enc->cur_buf++;
if (!sc_enc->cur_buf[0] || !sc_enc->cur_buf[1]) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: cannot find closing comment */\n"));
sc_enc->err = GF_BAD_PARAM;
return GF_FALSE;
}
}
sc_enc->cur_buf+=2;
return SFE_NextToken(sc_enc);
}
i = 0;
if (isalpha(sc_enc->cur_buf[i]) || (sc_enc->cur_buf[i]=='_')) {
while (isalnum(sc_enc->cur_buf[i]) || (sc_enc->cur_buf[i]=='_')) {
sc_enc->token[i] = sc_enc->cur_buf[i];
i++;
}
sc_enc->token[i] = 0;
sc_enc->cur_buf += i;
sc_enc->token_code = TOK_IDENTIFIER;
for (i=0; i<NUMBER_OF_KEYWORD; i++) {
if (!strcmp(sc_enc->token, sc_keywords[i])) {
sc_enc->token_code = i;
return GF_TRUE;
}
}
if (!stricmp(sc_enc->token, "TRUE") || !stricmp(sc_enc->token, "FALSE") ) {
sc_enc->token_code = TOK_BOOLEAN;
}
return GF_TRUE;
}
if (isdigit(sc_enc->cur_buf[i])) return SFE_GetNumber(sc_enc);
if ((sc_enc->cur_buf[i]=='\'') || (sc_enc->cur_buf[i]=='\"')
|| ((sc_enc->cur_buf[i]=='\\') && (sc_enc->cur_buf[i+1]=='\"'))
) {
char end;
Bool skip_last = GF_FALSE;
end = sc_enc->cur_buf[i];
if (sc_enc->cur_buf[i]=='\\') {
skip_last = GF_TRUE;
sc_enc->cur_buf++;
}
while (sc_enc->cur_buf[i+1] != end) {
sc_enc->token[i] = sc_enc->cur_buf[i+1];
i++;
}
sc_enc->token[i] = 0;
sc_enc->cur_buf += i+2;
if (skip_last) sc_enc->cur_buf++;
sc_enc->token_code = TOK_STRING;
return GF_TRUE;
}
switch (sc_enc->cur_buf[i]) {
case '.':
if (isdigit(sc_enc->cur_buf[i+1])) {
SFE_GetNumber(sc_enc);
return GF_TRUE;
} else {
sc_enc->token_code = TOK_PERIOD;
}
break;
case '!':
if (sc_enc->cur_buf[i+1] == '=') {
sc_enc->token_code = TOK_NE;
sc_enc->cur_buf ++;
} else {
sc_enc->token_code = TOK_NOT;
}
break;
case '=':
if (sc_enc->cur_buf[i+1]=='=') {
if (sc_enc->cur_buf[i+2]=='=') {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[BIFSEnc] JavaScript token '===' not supported by standard\n"));
sc_enc->err = GF_NOT_SUPPORTED;
return GF_FALSE;
}
sc_enc->token_code = TOK_EQ;
sc_enc->cur_buf ++;
} else {
sc_enc->token_code = TOK_ASSIGN;
}
break;
case '+':
if(sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_PLUSEQ;
sc_enc->cur_buf ++;
} else if(sc_enc->cur_buf[i+1]=='+') {
sc_enc->token_code = TOK_INCREMENT;
sc_enc->cur_buf++;
} else {
sc_enc->token_code = TOK_PLUS;
}
break;
case '-':
if(sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_MINUSEQ;
sc_enc->cur_buf++;
} else if(sc_enc->cur_buf[i+1] == '-') {
sc_enc->token_code = TOK_DECREMENT;
sc_enc->cur_buf++;
} else {
sc_enc->token_code = TOK_MINUS;
}
break;
case '*':
if(sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_MULTIPLYEQ;
sc_enc->cur_buf++;
} else {
sc_enc->token_code = TOK_MULTIPLY;
}
break;
case '/':
if(sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_DIVIDEEQ;
sc_enc->cur_buf++;
} else {
sc_enc->token_code = TOK_DIVIDE;
}
break;
case '%':
if(sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_MODEQ;
sc_enc->cur_buf++;
} else {
sc_enc->token_code = TOK_MOD;
}
break;
case '&':
if(sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_ANDEQ;
sc_enc->cur_buf++;
} else if(sc_enc->cur_buf[i+1]=='&') {
sc_enc->token_code = TOK_LAND;
sc_enc->cur_buf++;
} else {
sc_enc->token_code = TOK_AND;
}
break;
case '|':
if(sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_OREQ;
sc_enc->cur_buf++;
} else if(sc_enc->cur_buf[i+1]=='|') {
sc_enc->token_code = TOK_LOR;
sc_enc->cur_buf++;
} else {
sc_enc->token_code = TOK_OR;
}
break;
case '^':
if(sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_XOREQ;
sc_enc->cur_buf++;
} else {
sc_enc->token_code = TOK_XOR;
}
break;
case '<':
if (sc_enc->cur_buf[i+1]=='<') {
if(sc_enc->cur_buf[i+2]=='=') {
sc_enc->token_code = TOK_LSHIFTEQ;
sc_enc->cur_buf += 1;
} else {
sc_enc->token_code = TOK_LSHIFT;
}
sc_enc->cur_buf += 1;
} else if(sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_LE;
sc_enc->cur_buf ++;
} else {
sc_enc->token_code = TOK_LT;
}
break;
case '>':
if (sc_enc->cur_buf[i+1]=='>') {
if (sc_enc->cur_buf[i+2]=='=') {
sc_enc->token_code = TOK_RSHIFTEQ;
sc_enc->cur_buf ++;
} else if(sc_enc->cur_buf[i+2]=='>') {
if(sc_enc->cur_buf[i+3]=='=') {
sc_enc->token_code = TOK_RSHIFTFILLEQ;
sc_enc->cur_buf ++;
} else {
sc_enc->token_code = TOK_RSHIFTFILL;
}
sc_enc->cur_buf ++;
} else {
sc_enc->token_code = TOK_RSHIFT;
}
sc_enc->cur_buf ++;
} else if (sc_enc->cur_buf[i+1]=='=') {
sc_enc->token_code = TOK_GE;
sc_enc->cur_buf ++;
} else {
sc_enc->token_code = TOK_GT;
}
break;
case '?':
sc_enc->token_code = TOK_CONDTEST;
break;
case ':':
sc_enc->token_code = TOK_CONDSEP;
break;
case '~':
sc_enc->token_code = TOK_ONESCOMP;
break;
case ',':
sc_enc->token_code = TOK_COMMA;
break;
case ';':
sc_enc->token_code = TOK_SEMICOLON;
break;
case '{':
sc_enc->token_code = TOK_LEFT_BRACE;
break;
case '}':
sc_enc->token_code = TOK_RIGHT_BRACE;
break;
case '(':
sc_enc->token_code = TOK_LEFT_CURVE;
break;
case ')':
sc_enc->token_code = TOK_RIGHT_CURVE;
break;
case '[':
sc_enc->token_code = TOK_LEFT_BRACKET;
break;
case ']':
sc_enc->token_code = TOK_RIGHT_BRACKET;
break;
default:
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Unrecognized symbol %c\n", sc_enc->cur_buf[i]));
sc_enc->err = GF_BAD_PARAM;
return GF_FALSE;
}
sc_enc->cur_buf ++;
return GF_TRUE;
}
Bool SFE_CheckToken(ScriptEnc *sc_enc, u32 token)
{
if (sc_enc->token_code != token) {
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]));
return GF_FALSE;
}
return GF_TRUE;
}
void SFE_PutIdentifier(ScriptEnc *sc_enc, char *id)
{
u32 i;
u32 nbBits, length;
char *str;
if (sc_enc->emul) return;
i=0;
while ((str = (char *)gf_list_enum(sc_enc->identifiers, &i))) {
if (strcmp(str, id)) continue;
nbBits = 0;
length = gf_list_count(sc_enc->identifiers) - 1;
while (length > 0) {
length >>= 1;
nbBits ++;
}
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "received", str);
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, i-1, nbBits, "identifierCode", str);
return;
}
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "received", id);
gf_list_add(sc_enc->identifiers, gf_strdup(id));
gf_bifs_enc_name(sc_enc->codec, sc_enc->bs, id);
}
void SFE_Arguments(ScriptEnc *sc_enc)
{
while (1) {
if (!SFE_NextToken(sc_enc)) return;
if (sc_enc->token_code == TOK_RIGHT_CURVE) break;
else if (sc_enc->token_code == TOK_COMMA) continue;
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "hasArgument", NULL);
SFE_PutIdentifier(sc_enc, sc_enc->token);
}
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "hasArgument", NULL);
}
void SFE_StatementBlock(ScriptEnc *sc_enc);
void SFE_Statement(ScriptEnc *sc_enc);
void SFE_PutInteger(ScriptEnc *sc_enc, char *str)
{
u32 nbBits, val = 0;
if (sc_enc->emul) return;
if ((str[0]=='0') && (str[1]=='x' || str[1]=='X')) {
val = (u32) strtoul(sc_enc->token, (char **) NULL, 16);
} else if (str[0]=='0' && isdigit(str[1])) {
val = (u32) strtoul(str, (char **) NULL, 8);
} else if (isdigit(str[0])) {
val = (u32) strtoul(str, (char **) NULL, 10);
} else {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: %s is not an integer\n", str));
sc_enc->err = GF_BAD_PARAM;
return;
}
nbBits = gf_get_bit_size(val);
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, nbBits, 5, "nbBitsInteger", NULL);
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, val, nbBits, "value", sc_enc->token);
}
u32 SFE_LoadExpression(ScriptEnc *sc_enc, u32 *expr_sep)
{
Bool is_var = GF_FALSE;
u32 close_code, open_code;
u32 count = 0;
u32 nbExpr = 1;
u32 nbIndir = 0;
expr_sep[0] = 0;
sc_enc->expr_toks_len = 0;
while ( (sc_enc->token_code != TOK_SEMICOLON) && (sc_enc->token_code != TOK_RIGHT_CURVE) ) {
switch (sc_enc->token_code) {
case TOK_CONDTEST:
nbIndir ++;
break;
case TOK_CONDSEP:
if (nbIndir > 0) nbIndir--;
else {
goto break_loop;
}
break;
case TOK_IDENTIFIER:
case TOK_NUMBER:
case TOK_STRING:
case TOK_BOOLEAN:
gf_list_add(sc_enc->id_buf, gf_strdup(sc_enc->token));
break;
case TOK_FUNCTION:
goto break_loop;
}
if (sc_enc->token_code==TOK_VAR) is_var = GF_TRUE;
if (!is_var || (sc_enc->token_code!=TOK_COMMA)) {
sc_enc->expr_toks[sc_enc->expr_toks_len] = sc_enc->token_code;
sc_enc->expr_toks_len++;
}
open_code = sc_enc->token_code;
close_code = 0;
if (sc_enc->token_code == TOK_LEFT_CURVE) close_code = TOK_RIGHT_CURVE;
else if (sc_enc->token_code == TOK_LEFT_BRACKET) close_code = TOK_RIGHT_BRACKET;
else if (sc_enc->token_code == TOK_LEFT_BRACE) close_code = TOK_RIGHT_BRACE;
if ((sc_enc->token_code == TOK_COMMA) && (sc_enc->expr_toks[0] != TOK_VAR) ) {
expr_sep[nbExpr++] = sc_enc->expr_toks_len - 1;
}
else if (close_code) {
count++;
do {
SFE_NextToken(sc_enc);
if ((sc_enc->token_code == TOK_IDENTIFIER) || (sc_enc->token_code == TOK_NUMBER)
|| (sc_enc->token_code == TOK_STRING) || (sc_enc->token_code == TOK_BOOLEAN) ) {
gf_list_add(sc_enc->id_buf, gf_strdup(sc_enc->token));
}
sc_enc->expr_toks[sc_enc->expr_toks_len] = sc_enc->token_code;
sc_enc->expr_toks_len++;
if (sc_enc->token_code == open_code) count++;
else if (sc_enc->token_code == close_code) count--;
} while ( (sc_enc->token_code != close_code) || count);
}
SFE_NextToken(sc_enc);
if (sc_enc->err) break;
}
break_loop:
if (sc_enc->err) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: end of compoundExpression not found\n"));
return 0;
}
expr_sep[nbExpr] = sc_enc->expr_toks_len;
if ((sc_enc->token_code == TOK_IDENTIFIER) || (sc_enc->token_code == TOK_NUMBER)
|| (sc_enc->token_code == TOK_STRING) || (sc_enc->token_code == TOK_BOOLEAN) ) {
gf_list_add(sc_enc->id_buf, gf_strdup(sc_enc->token));
}
if ((sc_enc->token_code != TOK_CONDSEP) && (sc_enc->token_code != TOK_RIGHT_BRACE) && (sc_enc->expr_toks[0] != TOK_VAR)) {
sc_enc->expr_toks[sc_enc->expr_toks_len] = sc_enc->token_code;
sc_enc->expr_toks_len++;
}
return nbExpr;
}
u32 MoveToToken(ScriptEnc *sc_enc, u32 endTok, u32 cur, u32 end);
u32 SFE_ScanExpression(ScriptEnc *sc_enc, u32 start, u32 end, u32 *expr_sep)
{
u32 curTok;
u32 n = start;
u32 nbExpr = 1;
expr_sep[0] = start;
while (n<end) {
curTok = sc_enc->expr_toks[n++];
if (curTok == TOK_LEFT_CURVE) {
n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n-1, end);
n++;
} else if (curTok == TOK_LEFT_BRACKET) {
n = MoveToToken(sc_enc, TOK_RIGHT_BRACKET, n-1, end);
n++;
} else if (curTok == TOK_COMMA) {
expr_sep[nbExpr++] = n-1;
}
}
expr_sep[nbExpr] = end;
return nbExpr;
}
u32 SFE_Expression(ScriptEnc *sc_enc, u32 start, u32 end, Bool memberAccess);
void SFE_CompoundExpression(ScriptEnc *sc_enc, u32 start, u32 end, u32 isPar)
{
u32 nbExp, i;
u32 expr_sep[MAX_NUM_EXPR];
if (sc_enc->err) return;
if (end==0) {
nbExp = SFE_LoadExpression(sc_enc, expr_sep);
} else {
nbExp = SFE_ScanExpression(sc_enc, start, end, expr_sep);
}
SFE_Expression(sc_enc, expr_sep[0], expr_sep[1], GF_FALSE);
for (i=1; i<nbExp; i++) {
SFE_WRITE_INT(sc_enc, 1, 1, isPar ? "hasParam" : "hasExpression", NULL);
SFE_Expression(sc_enc, expr_sep[i]+1, expr_sep[i+1], GF_FALSE);
}
SFE_WRITE_INT(sc_enc, 0, 1, isPar ? "hasParam" : "hasExpression", NULL);
}
void SFE_OptionalExpression(ScriptEnc *sc_enc)
{
if (sc_enc->token_code != TOK_SEMICOLON) {
SFE_WRITE_INT(sc_enc, 1, 1, "hasCompoundExpression", NULL);
SFE_CompoundExpression(sc_enc, 0, 0, 0);
} else {
SFE_WRITE_INT(sc_enc, 0, 1, "hasCompoundExpression", NULL);
}
}
void SFE_IfStatement(ScriptEnc *sc_enc)
{
char *buf_bck;
u32 tok_bck;
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
SFE_NextToken(sc_enc);
SFE_CompoundExpression(sc_enc, 0, 0, 0);
SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE);
SFE_StatementBlock(sc_enc);
buf_bck = sc_enc->cur_buf;
tok_bck = sc_enc->token_code;
SFE_NextToken(sc_enc);
if (sc_enc->token_code == TOK_ELSE) {
SFE_WRITE_INT(sc_enc, 1, 1, "hasELSEStatement", NULL);
SFE_StatementBlock(sc_enc);
} else {
SFE_WRITE_INT(sc_enc, 0, 1, "hasELSEStatement", NULL);
sc_enc->cur_buf = buf_bck;
sc_enc->token_code = tok_bck;
}
}
void SFE_ForStatement(ScriptEnc *sc_enc)
{
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
SFE_NextToken(sc_enc);
SFE_OptionalExpression(sc_enc);
SFE_CheckToken(sc_enc, TOK_SEMICOLON);
SFE_NextToken(sc_enc);
SFE_OptionalExpression(sc_enc);
SFE_CheckToken(sc_enc, TOK_SEMICOLON);
SFE_NextToken(sc_enc);
SFE_OptionalExpression(sc_enc);
SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE);
SFE_StatementBlock(sc_enc);
}
void SFE_WhileStatement(ScriptEnc *sc_enc)
{
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
SFE_NextToken(sc_enc);
SFE_CompoundExpression(sc_enc, 0, 0, 0);
SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE);
SFE_StatementBlock(sc_enc);
}
void SFE_ReturnStatement(ScriptEnc *sc_enc)
{
SFE_NextToken(sc_enc);
if (sc_enc->token_code != TOK_SEMICOLON) {
SFE_WRITE_INT(sc_enc, 1, 1, "returnValue", NULL);
SFE_CompoundExpression(sc_enc, 0, 0, 0);
} else {
SFE_WRITE_INT(sc_enc, 0, 1, "returnValue", NULL);
}
}
void SFE_CaseBlock(ScriptEnc *sc_enc)
{
SFE_WRITE_INT(sc_enc, 1, 1, "isCompoundStatement", NULL);
SFE_NextToken(sc_enc);
if (sc_enc->token_code == TOK_LEFT_BRACE) {
SFE_NextToken(sc_enc);
while (sc_enc->token_code != TOK_RIGHT_BRACE) {
SFE_WRITE_INT(sc_enc, 1, 1, "hasStatement", NULL);
SFE_Statement(sc_enc);
SFE_NextToken(sc_enc);
}
SFE_NextToken(sc_enc);
}
while ((sc_enc->token_code != TOK_CASE) && (sc_enc->token_code != TOK_DEFAULT) && (sc_enc->token_code != TOK_RIGHT_BRACE)) {
SFE_WRITE_INT(sc_enc, 1, 1, "hasStatement", NULL);
SFE_Statement(sc_enc);
SFE_NextToken(sc_enc);
}
SFE_WRITE_INT(sc_enc, 0, 1, "hasStatement", NULL);
}
u32 SFE_PutCaseInteger(ScriptEnc *sc_enc, char *str, u32 nbBits)
{
u32 val = 0;
if ((str[0]=='0') && (str[1]=='x' || str[1]=='X')) {
val = (u32) strtoul(sc_enc->token, (char **) NULL, 16);
} else if (str[0]=='0' && isdigit(str[1])) {
val = (u32) strtoul(str, (char **) NULL, 8);
} else if (isdigit(str[0])) {
val = (u32) strtoul(str, (char **) NULL, 10);
} else {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: %s is not an integer\n", str));
sc_enc->err = GF_BAD_PARAM;
return 0;
}
if (!sc_enc->emul) {
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, val, nbBits, "value", sc_enc->token);
} else {
nbBits = gf_get_bit_size(val);
}
return nbBits;
}
void SFE_SwitchStatement(ScriptEnc *sc_enc)
{
u32 nbBits, maxBits = 0;
Bool prev_emu;
char *buf_bck;
u32 tok_bck;
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
SFE_NextToken(sc_enc);
SFE_CompoundExpression(sc_enc, 0, 0, 0);
SFE_CheckToken(sc_enc, TOK_RIGHT_CURVE);
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_LEFT_BRACE);
buf_bck = sc_enc->cur_buf;
tok_bck = sc_enc->token_code;
prev_emu = sc_enc->emul;
sc_enc->emul = GF_TRUE;
SFE_NextToken(sc_enc);
while (sc_enc->token_code == TOK_CASE) {
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_NUMBER);
nbBits = SFE_PutCaseInteger(sc_enc, sc_enc->token, 0);
if (maxBits<nbBits) maxBits = nbBits;
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_CONDSEP);
SFE_CaseBlock(sc_enc);
SFE_WRITE_INT(sc_enc, (sc_enc->token_code == TOK_CASE) ? 1 : 0, 1, "hasMoreCases", NULL);
}
sc_enc->cur_buf = buf_bck;
sc_enc->token_code = tok_bck;
sc_enc->emul = prev_emu;
maxBits ++;
SFE_WRITE_INT(sc_enc, maxBits, 5, "caseNbBits", NULL);
SFE_NextToken(sc_enc);
while (sc_enc->token_code == TOK_CASE) {
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_NUMBER);
SFE_PutCaseInteger(sc_enc, sc_enc->token, maxBits);
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_CONDSEP);
SFE_CaseBlock(sc_enc);
SFE_WRITE_INT(sc_enc, (sc_enc->token_code == TOK_CASE) ? 1 : 0, 1, "hasMoreCases", NULL);
}
if (sc_enc->token_code == TOK_DEFAULT) {
SFE_WRITE_INT(sc_enc, 1, 1, "hasDefault", NULL);
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_CONDSEP);
SFE_CaseBlock(sc_enc);
} else {
SFE_WRITE_INT(sc_enc, 0, 1, "hasDefault", NULL);
}
SFE_CheckToken(sc_enc, TOK_RIGHT_BRACE);
}
void SFE_Statement(ScriptEnc *sc_enc)
{
switch (sc_enc->token_code) {
case TOK_IF:
SFE_WRITE_INT(sc_enc, ST_IF, NUMBITS_STATEMENT, "statementType", "if");
SFE_IfStatement(sc_enc);
break;
case TOK_FOR:
SFE_WRITE_INT(sc_enc, ST_FOR, NUMBITS_STATEMENT, "statementType", "for");
SFE_ForStatement(sc_enc);
break;
case TOK_WHILE:
SFE_WRITE_INT(sc_enc, ST_WHILE, NUMBITS_STATEMENT, "statementType", "while");
SFE_WhileStatement(sc_enc);
break;
case TOK_RETURN:
SFE_WRITE_INT(sc_enc, ST_RETURN, NUMBITS_STATEMENT, "statementType", "return");
SFE_ReturnStatement(sc_enc);
break;
case TOK_BREAK:
SFE_WRITE_INT(sc_enc, ST_BREAK, NUMBITS_STATEMENT, "statementType", "break");
SFE_NextToken(sc_enc);
break;
case TOK_CONTINUE:
SFE_WRITE_INT(sc_enc, ST_CONTINUE, NUMBITS_STATEMENT, "statementType", "continue");
SFE_NextToken(sc_enc);
break;
case TOK_SWITCH:
SFE_WRITE_INT(sc_enc, ST_SWITCH, NUMBITS_STATEMENT, "statementType", "while");
SFE_SwitchStatement(sc_enc);
break;
default:
SFE_WRITE_INT(sc_enc, ST_COMPOUND_EXPR, NUMBITS_STATEMENT, "statementType", "compoundExpr");
SFE_CompoundExpression(sc_enc, 0, 0, 0);
break;
}
}
void SFE_Statements(ScriptEnc *sc_enc)
{
while (1) {
if (!SFE_NextToken(sc_enc)) return;
if (sc_enc->token_code == TOK_RIGHT_BRACE) break;
SFE_WRITE_INT(sc_enc, 1, 1, "hasStatement", NULL);
SFE_Statement(sc_enc);
}
SFE_WRITE_INT(sc_enc, 0, 1, "hasStatement", NULL);
}
void SFE_StatementBlock(ScriptEnc *sc_enc)
{
if (!SFE_NextToken(sc_enc)) return;
if (sc_enc->token_code == TOK_LEFT_BRACE) {
SFE_WRITE_INT(sc_enc, 1, 1, "isCompoundStatement", NULL);
SFE_Statements(sc_enc);
} else {
SFE_WRITE_INT(sc_enc, 0, 1, "isCompoundStatement", NULL);
SFE_Statement(sc_enc);
}
}
void SFE_Function(ScriptEnc *sc_enc)
{
char szName[1000];
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_FUNCTION);
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_IDENTIFIER);
strcpy(szName, sc_enc->token);
SFE_PutIdentifier(sc_enc, sc_enc->token);
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
SFE_Arguments(sc_enc);
SFE_StatementBlock(sc_enc);
if (sc_enc->err) GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Error while parsing function %s\n", szName));
}
GF_Err SFScript_Encode(GF_BifsEncoder *codec, SFScript *script_field, GF_BitStream *bs, GF_Node *n)
{
char *ptr;
ScriptEnc sc_enc;
if (gf_node_get_tag(n) != TAG_MPEG4_Script) return GF_NON_COMPLIANT_BITSTREAM;
memset(&sc_enc, 0, sizeof(ScriptEnc));
sc_enc.codec = codec;
sc_enc.script = n;
sc_enc.bs = bs;
sc_enc.identifiers = gf_list_new();
sc_enc.id_buf = gf_list_new();
sc_enc.err = GF_OK;
if (codec->is_encoding_command) {
GF_BIFS_WRITE_INT(codec, bs, 1, 1, "Script::isList", NULL);
GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL);
} else {
EncScriptFields(&sc_enc);
}
GF_BIFS_WRITE_INT(codec, bs, 1, 1, "reserved", NULL);
if (script_field) {
sc_enc.cur_buf = (char *)script_field->script_text;
} else if (((M_Script*)n)->url.count) {
sc_enc.cur_buf = (char *)((M_Script*)n)->url.vals[0].script_text;
}
if (sc_enc.cur_buf) {
if (!strnicmp(sc_enc.cur_buf, "javascript:", 11)
|| !strnicmp(sc_enc.cur_buf, "vrmlscript:", 11)
|| !strnicmp(sc_enc.cur_buf, "ECMAScript:", 11)
) {
sc_enc.cur_buf += 11;
} else if (!strnicmp(sc_enc.cur_buf, "mpeg4script:", 12) ) {
sc_enc.cur_buf += 12;
}
}
while (sc_enc.cur_buf && sc_enc.cur_buf[0] && (sc_enc.cur_buf[0]!='}')) {
if (strchr("\r\n\t ", sc_enc.cur_buf[0]) ) {
sc_enc.cur_buf++;
continue;
}
GF_BIFS_WRITE_INT(codec, bs, 1, 1, "hasFunction", NULL);
SFE_Function(&sc_enc);
if (sc_enc.err) break;
}
GF_BIFS_WRITE_INT(codec, bs, 0, 1, "hasFunction", NULL);
while (gf_list_count(sc_enc.identifiers)) {
ptr = (char *)gf_list_get(sc_enc.identifiers, 0);
gf_list_rem(sc_enc.identifiers, 0);
gf_free(ptr);
}
gf_list_del(sc_enc.identifiers);
while (gf_list_count(sc_enc.id_buf)) {
ptr = (char *)gf_list_get(sc_enc.id_buf, 0);
gf_list_rem(sc_enc.id_buf, 0);
gf_free(ptr);
}
gf_list_del(sc_enc.id_buf);
return sc_enc.err;
}
void SFE_PutReal(ScriptEnc *sc_enc, char *str)
{
u32 i;
size_t length = strlen(str);
for (i=0; i<length; i++) {
s32 c = str[i];
if (c >= '0' && c <= '9')
{
SFE_WRITE_INT(sc_enc, c-'0', 4, "floatChar", "Digital");
}
else if (c == '.')
{
SFE_WRITE_INT(sc_enc, 10, 4, "floatChar", "Decimal Point");
}
else if (c == 'e' || c == 'E')
{
SFE_WRITE_INT(sc_enc, 11, 4, "floatChar", "Exponential");
}
else if (c == '-')
{
SFE_WRITE_INT(sc_enc, 12, 4, "floatChar", "Sign");
}
else {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: %s is not a real number\n", str));
sc_enc->err = GF_BAD_PARAM;
return;
}
}
SFE_WRITE_INT(sc_enc, 15, 4, "floatChar", "End Symbol");
}
void SFE_PutNumber(ScriptEnc *sc_enc, char *str)
{
if (strpbrk(str,".eE-") == 0) {
SFE_WRITE_INT(sc_enc, 1, 1, "isInteger", "integer");
SFE_PutInteger(sc_enc, str);
} else {
SFE_WRITE_INT(sc_enc, 0, 1, "isInteger", "real");
SFE_PutReal(sc_enc, str);
}
}
void SFE_PutBoolean(ScriptEnc *sc_enc, char *str)
{
u32 v = 1;
if (!stricmp(str, "false") || !strcmp(str, "0")) v = 0;
SFE_WRITE_INT(sc_enc, v, 1, "value", "bolean");
}
#define CHECK_TOK(x) \
if (curTok != x) { \
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: Token %s read, %s expected\n", tok_names[curTok], tok_names[x])); \
sc_enc->err = GF_BAD_PARAM; \
} \
u32 TOK_To_ET(u32 tok)
{
switch(tok) {
case TOK_INCREMENT:
return ET_INCREMENT;
case TOK_DECREMENT:
return ET_DECREMENT;
case TOK_NOT:
return ET_NOT;
case TOK_ONESCOMP:
return ET_ONESCOMP;
case TOK_MULTIPLY :
return ET_MULTIPLY;
case TOK_DIVIDE :
return ET_DIVIDE;
case TOK_MOD :
return ET_MOD;
case TOK_PLUS :
return ET_PLUS;
case TOK_MINUS :
return ET_MINUS;
case TOK_LSHIFT :
return ET_LSHIFT;
case TOK_RSHIFT :
return ET_RSHIFT;
case TOK_RSHIFTFILL :
return ET_RSHIFTFILL;
case TOK_LT :
return ET_LT;
case TOK_LE :
return ET_LE;
case TOK_GT :
return ET_GT;
case TOK_GE :
return ET_GE;
case TOK_EQ :
return ET_EQ;
case TOK_NE :
return ET_NE;
case TOK_AND :
return ET_AND;
case TOK_XOR :
return ET_XOR;
case TOK_OR :
return ET_OR;
case TOK_LAND :
return ET_LAND;
case TOK_LOR :
return ET_LOR;
case TOK_CONDTEST :
return ET_CONDTEST;
case TOK_ASSIGN :
return ET_ASSIGN;
case TOK_PLUSEQ :
return ET_PLUSEQ;
case TOK_MINUSEQ :
return ET_MINUSEQ;
case TOK_MULTIPLYEQ :
return ET_MULTIPLYEQ;
case TOK_DIVIDEEQ :
return ET_DIVIDEEQ;
case TOK_MODEQ :
return ET_MODEQ;
case TOK_LSHIFTEQ :
return ET_LSHIFTEQ;
case TOK_RSHIFTEQ :
return ET_RSHIFTEQ;
case TOK_RSHIFTFILLEQ :
return ET_RSHIFTFILLEQ;
case TOK_ANDEQ :
return ET_ANDEQ;
case TOK_XOREQ :
return ET_XOREQ;
case TOK_OREQ :
return ET_OREQ;
case TOK_FUNCTION:
return ET_FUNCTION_CALL;
case TOK_VAR:
return ET_VAR;
default:
assert(0);
return (u32) -1;
}
}
static const char *expr_name[] = {
"ET_CURVED_EXPR",
"ET_NEGATIVE",
"ET_NOT",
"ET_ONESCOMP",
"ET_INCREMENT",
"ET_DECREMENT",
"ET_POST_INCREMENT",
"ET_POST_DECREMENT",
"ET_CONDTEST",
"ET_STRING",
"ET_NUMBER",
"ET_IDENTIFIER",
"ET_FUNCTION_CALL",
"ET_NEW",
"ET_OBJECT_MEMBER_ACCESS",
"ET_OBJECT_METHOD_CALL",
"ET_ARRAY_DEREFERENCE",
"ET_ASSIGN",
"ET_PLUSEQ",
"ET_MINUSEQ",
"ET_MULTIPLYEQ",
"ET_DIVIDEEQ",
"ET_MODEQ",
"ET_ANDEQ",
"ET_OREQ",
"ET_XOREQ",
"ET_LSHIFTEQ",
"ET_RSHIFTEQ",
"ET_RSHIFTFILLEQ",
"ET_EQ",
"ET_NE",
"ET_LT",
"ET_LE",
"ET_GT",
"ET_GE",
"ET_PLUS",
"ET_MINUS",
"ET_MULTIPLY",
"ET_DIVIDE",
"ET_MOD",
"ET_LAND",
"ET_LOR",
"ET_AND",
"ET_OR",
"ET_XOR",
"ET_LSHIFT",
"ET_RSHIFT",
"ET_RSHIFTFILL",
"ET_BOOLEAN",
"ET_VAR",
"NUMBER_OF_EXPR_TYPE"
};
#define NUMBER_OF_RANK 15
static s32 ET_Rank[NUMBER_OF_EXPR_TYPE] =
{
1,
2,
2,
2,
2,
2,
2,
2,
14,
0,
0,
0,
1,
2,
1,
1,
1,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
14,
8,
9,
6,
6,
7,
7,
5,
5,
3,
3,
3,
13,
14,
10,
12,
11,
5,
6,
6,
0,
14
};
static s32 ET_leftAssoc[NUMBER_OF_RANK] = {1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
u32 MoveToToken(ScriptEnc *sc_enc, u32 endTok, u32 cur, u32 end)
{
u32 cnt = 0;
u32 startTok = TOK_EOF, curTok;
if (endTok == TOK_RIGHT_CURVE) startTok = TOK_LEFT_CURVE;
else if (endTok == TOK_RIGHT_BRACKET) startTok = TOK_LEFT_BRACKET;
else if (endTok == TOK_RIGHT_BRACE) startTok = TOK_LEFT_BRACE;
else if (endTok == TOK_CONDSEP) startTok = TOK_CONDTEST;
else {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal MoveToToken %s\n", tok_names[endTok]));
sc_enc->err = GF_BAD_PARAM;
return (u32) -1;
}
do {
curTok = sc_enc->expr_toks[cur++];
if (curTok == startTok) cnt++;
else if (curTok == endTok) cnt--;
} while ( (curTok != endTok || cnt) && cur < end);
if (curTok==endTok && cnt==0) return cur-1;
return (u32) -1;
}
void SFE_FunctionCall(ScriptEnc *sc_enc, u32 start, u32 end);
void SFE_Params(ScriptEnc *sc_enc, u32 start, u32 end);
void SFE_ConditionTest(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
void SFE_ObjectConstruct(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
void SFE_ArrayDereference(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
void SFE_ObjectMethodCall(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
void SFE_ObjectMemberAccess(ScriptEnc *sc_enc, u32 start, u32 op, u32 end);
u32 SFE_Expression(ScriptEnc *sc_enc, u32 start, u32 end, Bool memberAccess)
{
char *str;
u32 n = start;
u32 curPos = 0, finalPos = 0;
u32 curTok, prevTok;
u32 curExpr = 0, expr = 0;
u32 curRank, maxRank=0;
if (sc_enc->err) return 0;
curTok = prevTok = sc_enc->expr_toks[n];
do {
curPos = n;
switch (curTok) {
case TOK_IDENTIFIER:
curExpr = ET_IDENTIFIER;
break;
case TOK_NUMBER:
curExpr = ET_NUMBER;
break;
case TOK_BOOLEAN:
curExpr = ET_BOOLEAN;
break;
case TOK_STRING:
curExpr = ET_STRING;
break;
case TOK_LEFT_CURVE:
if (prevTok == TOK_IDENTIFIER) curExpr = ET_FUNCTION_CALL;
else curExpr = ET_CURVED_EXPR;
n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n, end);
curTok = TOK_RIGHT_CURVE;
break;
case TOK_LEFT_BRACKET:
curExpr = ET_ARRAY_DEREFERENCE;
n = MoveToToken(sc_enc, TOK_RIGHT_BRACKET, n, end);
curTok = TOK_RIGHT_BRACKET;
break;
case TOK_PERIOD:
curTok = sc_enc->expr_toks[++n];
CHECK_TOK(TOK_IDENTIFIER);
if (sc_enc->expr_toks[n+1] == TOK_LEFT_CURVE) {
curExpr = ET_OBJECT_METHOD_CALL;
n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n+1, end);
curTok = TOK_RIGHT_CURVE;
} else {
curExpr = ET_OBJECT_MEMBER_ACCESS;
}
break;
case TOK_NEW:
curExpr = ET_NEW;
curTok = sc_enc->expr_toks[++n];
CHECK_TOK(TOK_IDENTIFIER);
curTok = sc_enc->expr_toks[++n];
CHECK_TOK(TOK_LEFT_CURVE);
n = MoveToToken(sc_enc, TOK_RIGHT_CURVE, n, end);
curTok = TOK_RIGHT_CURVE;
break;
case TOK_FUNCTION:
curExpr = ET_FUNCTION_ASSIGN;
break;
case TOK_PLUS:
if (
prevTok==TOK_RIGHT_CURVE || prevTok==TOK_RIGHT_BRACKET ||
prevTok==TOK_IDENTIFIER || prevTok==TOK_NUMBER ||
prevTok==TOK_STRING || prevTok==TOK_INCREMENT ||
prevTok==TOK_DECREMENT
) {
curExpr = ET_PLUS;
} else {
goto skip_token;
}
break;
case TOK_MINUS:
if (
prevTok==TOK_RIGHT_CURVE || prevTok==TOK_RIGHT_BRACKET ||
prevTok==TOK_IDENTIFIER || prevTok==TOK_NUMBER ||
prevTok==TOK_STRING || prevTok==TOK_INCREMENT ||
prevTok==TOK_DECREMENT
) {
curExpr = ET_MINUS;
} else {
curExpr = ET_NEGATIVE;
curTok = TOK_NEGATIVE;
}
break;
case TOK_INCREMENT:
curExpr = ET_INCREMENT;
break;
case TOK_DECREMENT:
curExpr = ET_DECREMENT;
break;
case TOK_NOT:
curExpr = ET_NOT;
break;
case TOK_ONESCOMP:
curExpr = ET_ONESCOMP;
break;
case TOK_CONDTEST:
curExpr = ET_CONDTEST;
break;
case TOK_CONDSEP:
break;
case TOK_LEFT_BRACE:
curExpr = ET_CURVED_EXPR;
n = MoveToToken(sc_enc, TOK_RIGHT_BRACE, n, end);
curTok = TOK_RIGHT_BRACE;
break;
break;
default:
if (curTok && (curTok != TOK_VAR)
&& (curTok < TOK_MULTIPLY || curTok > TOK_OREQ)) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal token %s read\n", tok_names[curTok]));
sc_enc->err = GF_BAD_PARAM;
return 0;
}
curExpr = TOK_To_ET(curTok);
}
if (curTok == TOK_CONDSEP) {
prevTok = curTok;
curTok = sc_enc->expr_toks[++n];
continue;
}
curRank = ET_Rank[curExpr];
if (curRank > maxRank) {
maxRank = curRank;
expr = curExpr;
finalPos = curPos;
} else if (curRank == maxRank && ET_leftAssoc[curRank]) {
expr = curExpr;
finalPos = curPos;
}
prevTok = curTok;
skip_token:
curTok = sc_enc->expr_toks[++n];
} while (n<end);
if (expr == ET_INCREMENT) {
if (finalPos==start) {}
else if (finalPos==end-1) expr = ET_POST_INCREMENT;
else {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal Increment expression\n"));
sc_enc->err = GF_BAD_PARAM;
return expr;
}
} else if (expr == ET_DECREMENT) {
if (finalPos==start) {}
else if (finalPos==end-1) expr = ET_POST_DECREMENT;
else {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal Decrement expression\n"));
sc_enc->err = GF_BAD_PARAM;
return expr;
}
}
SFE_WRITE_INT(sc_enc, expr, NUMBITS_EXPR_TYPE, "expressionType", (char *) expr_name[expr]);
switch (expr) {
case ET_MULTIPLY:
case ET_DIVIDE:
case ET_MOD:
case ET_PLUS:
case ET_MINUS:
case ET_LSHIFT:
case ET_RSHIFT:
case ET_RSHIFTFILL:
case ET_LT:
case ET_LE:
case ET_GT:
case ET_GE:
case ET_EQ:
case ET_NE:
case ET_AND:
case ET_XOR:
case ET_OR:
case ET_LAND:
case ET_LOR:
SFE_Expression(sc_enc, start, finalPos, GF_FALSE);
SFE_Expression(sc_enc, finalPos+1, end, GF_FALSE);
break;
case ET_ASSIGN:
case ET_PLUSEQ:
case ET_MINUSEQ:
case ET_MULTIPLYEQ:
case ET_DIVIDEEQ:
case ET_MODEQ:
case ET_LSHIFTEQ:
case ET_RSHIFTEQ:
case ET_RSHIFTFILLEQ:
case ET_ANDEQ:
case ET_XOREQ:
case ET_OREQ:
{
u32 ret = SFE_Expression(sc_enc, start, finalPos, GF_FALSE);
if ( ret != ET_IDENTIFIER && ret != ET_OBJECT_MEMBER_ACCESS && ret != ET_ARRAY_DEREFERENCE ) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: LeftVariable expected, %s returned\n", expr_name[ret]));
sc_enc->err = GF_BAD_PARAM;
return expr;
}
SFE_Expression(sc_enc, finalPos+1, end, GF_FALSE);
}
break;
case ET_IDENTIFIER:
str = (char *)gf_list_get(sc_enc->id_buf, 0);
gf_list_rem(sc_enc->id_buf, 0);
if (memberAccess) {
}
SFE_PutIdentifier(sc_enc, str);
gf_free(str);
break;
case ET_NUMBER:
str = (char *)gf_list_get(sc_enc->id_buf, 0);
gf_list_rem(sc_enc->id_buf, 0);
SFE_PutNumber(sc_enc, str);
gf_free(str);
break;
case ET_BOOLEAN:
str = (char *)gf_list_get(sc_enc->id_buf, 0);
gf_list_rem(sc_enc->id_buf, 0);
SFE_PutBoolean(sc_enc, str);
gf_free(str);
break;
case ET_VAR:
while (1) {
str = (char *)gf_list_get(sc_enc->id_buf, 0);
if (!str) break;
gf_list_rem(sc_enc->id_buf, 0);
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 1, 1, "hasArgument", NULL);
SFE_PutIdentifier(sc_enc, str);
gf_free(str);
}
GF_BIFS_WRITE_INT(sc_enc->codec, sc_enc->bs, 0, 1, "hasArgument", NULL);
break;
case ET_STRING:
str = (char *)gf_list_get(sc_enc->id_buf, 0);
gf_list_rem(sc_enc->id_buf, 0);
if (!sc_enc->emul) gf_bifs_enc_name(sc_enc->codec, sc_enc->bs, str);
gf_free(str);
break;
case ET_NEGATIVE:
case ET_INCREMENT:
case ET_DECREMENT:
case ET_NOT:
case ET_ONESCOMP:
SFE_Expression(sc_enc, finalPos+1, end, GF_FALSE);
break;
case ET_CURVED_EXPR:
SFE_CompoundExpression(sc_enc, finalPos+1, end-1, 0);
break;
case ET_POST_INCREMENT :
case ET_POST_DECREMENT :
SFE_Expression(sc_enc, start, finalPos, GF_FALSE);
break;
case ET_FUNCTION_CALL:
SFE_FunctionCall(sc_enc, start, end);
break;
case ET_OBJECT_MEMBER_ACCESS :
SFE_ObjectMemberAccess(sc_enc, start, finalPos, end);
break;
case ET_OBJECT_METHOD_CALL:
SFE_ObjectMethodCall(sc_enc, start, finalPos, end);
break;
case ET_ARRAY_DEREFERENCE:
SFE_ArrayDereference(sc_enc, start, finalPos, end);
break;
case ET_NEW:
SFE_ObjectConstruct(sc_enc, start, finalPos, end);
break;
case ET_CONDTEST:
SFE_ConditionTest(sc_enc, start, finalPos, end);
break;
case ET_FUNCTION_ASSIGN:
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_LEFT_CURVE);
SFE_Arguments(sc_enc);
SFE_StatementBlock(sc_enc);
SFE_NextToken(sc_enc);
SFE_CheckToken(sc_enc, TOK_SEMICOLON);
break;
default:
GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[bifs] Script encoding: illegal expression type %s\n", expr_name[expr]));
sc_enc->err = GF_BAD_PARAM;
break;
}
return expr;
}
void SFE_FunctionCall(ScriptEnc *sc_enc, u32 start, u32 end)
{
u32 curTok;
char *str;
curTok = sc_enc->expr_toks[start++];
CHECK_TOK(TOK_IDENTIFIER);
str = (char *)gf_list_get(sc_enc->id_buf, 0);
gf_list_rem(sc_enc->id_buf, 0);
SFE_PutIdentifier(sc_enc, str);
gf_free(str);
curTok = sc_enc->expr_toks[start++];
CHECK_TOK(TOK_LEFT_CURVE);
SFE_Params(sc_enc, start, end-1);
curTok = sc_enc->expr_toks[end-1];
CHECK_TOK(TOK_RIGHT_CURVE);
}
void SFE_ObjectMemberAccess(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
{
u32 curTok;
char *str;
SFE_Expression(sc_enc, start, op, GF_TRUE);
curTok = sc_enc->expr_toks[op];
CHECK_TOK(TOK_PERIOD);
curTok = sc_enc->expr_toks[end-1];
CHECK_TOK(TOK_IDENTIFIER);
str = (char *)gf_list_get(sc_enc->id_buf, 0);
gf_list_rem(sc_enc->id_buf, 0);
SFE_PutIdentifier(sc_enc, str);
gf_free(str);
}
void SFE_ObjectMethodCall(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
{
u32 curTok;
char *str;
SFE_Expression(sc_enc, start, op, GF_FALSE);
curTok = sc_enc->expr_toks[op];
CHECK_TOK(TOK_PERIOD);
curTok = sc_enc->expr_toks[op+1];
CHECK_TOK(TOK_IDENTIFIER);
str = (char *)gf_list_get(sc_enc->id_buf, 0);
gf_list_rem(sc_enc->id_buf, 0);
SFE_PutIdentifier(sc_enc, str);
gf_free(str);
curTok = sc_enc->expr_toks[op+2];
CHECK_TOK(TOK_LEFT_CURVE);
SFE_Params(sc_enc, op+3, end-1);
curTok = sc_enc->expr_toks[end-1];
CHECK_TOK(TOK_RIGHT_CURVE);
}
void SFE_ArrayDereference(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
{
u32 curTok;
SFE_Expression(sc_enc, start, op, GF_FALSE);
curTok = sc_enc->expr_toks[op];
CHECK_TOK(TOK_LEFT_BRACKET);
SFE_CompoundExpression(sc_enc, op+1, end-1, 0);
curTok = sc_enc->expr_toks[end-1];
CHECK_TOK(TOK_RIGHT_BRACKET);
}
void SFE_ObjectConstruct(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
{
u32 curTok;
char *str;
curTok = sc_enc->expr_toks[start++];
CHECK_TOK(TOK_NEW);
curTok = sc_enc->expr_toks[start++];
CHECK_TOK(TOK_IDENTIFIER);
str = (char *)gf_list_get(sc_enc->id_buf, 0);
gf_list_rem(sc_enc->id_buf, 0);
SFE_PutIdentifier(sc_enc, str);
gf_free(str);
curTok = sc_enc->expr_toks[start++];
CHECK_TOK(TOK_LEFT_CURVE);
SFE_Params(sc_enc, start, end-1);
curTok = sc_enc->expr_toks[end-1];
CHECK_TOK(TOK_RIGHT_CURVE);
}
void SFE_ConditionTest(ScriptEnc *sc_enc, u32 start, u32 op, u32 end)
{
u32 curTok;
SFE_Expression(sc_enc, start, op, GF_FALSE);
curTok = sc_enc->expr_toks[op];
CHECK_TOK(TOK_CONDTEST);
start = op+1;
op = MoveToToken(sc_enc, TOK_CONDSEP, op, end-1);
SFE_Expression(sc_enc, start, op, GF_FALSE);
curTok = sc_enc->expr_toks[op];
CHECK_TOK(TOK_CONDSEP);
SFE_Expression(sc_enc, op+1, end, GF_FALSE);
}
void SFE_Params(ScriptEnc *sc_enc, u32 start, u32 end)
{
u32 curTok;
curTok = sc_enc->expr_toks[start];
if (curTok != TOK_RIGHT_CURVE) {
SFE_WRITE_INT(sc_enc, 1, 1, "hasParam", NULL);
SFE_CompoundExpression(sc_enc, start, end, 1);
} else {
SFE_WRITE_INT(sc_enc, 0, 1, "hasParam", NULL);
}
}
#endif