180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScript.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMath.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkParse.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkString.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypedArray.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* things to do
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ? re-enable support for struct literals (e.g., for initializing points or rects)
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {x:1, y:2}
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ? use standard XML / script notation like document.getElementById("canvas");
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    finish support for typed arrays
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ? allow indexing arrays by string
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this could map to the 'name' attribute of a given child of an array
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ? allow multiple types in the array
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    remove SkDisplayType.h  // from SkOperand.h
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    merge type and operand arrays into scriptvalue array
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const char* errorStrings[] = {
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "array index of out bounds", // kArrayIndexOutOfBounds
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "could not find reference id", // kCouldNotFindReferencedID
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "dot operator expects object", // kDotOperatorExpectsObject
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "error in array index", // kErrorInArrrayIndex
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "error in function parameters", // kErrorInFunctionParameters
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected array", // kExpectedArray
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected boolean expression", // kExpectedBooleanExpression
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected field name", // kExpectedFieldName
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected hex", // kExpectedHex
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected int for condition operator", // kExpectedIntForConditionOperator
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected number", // kExpectedNumber
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected number for array index", // kExpectedNumberForArrayIndex
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected operator", // kExpectedOperator
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected token", // kExpectedToken
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected token before dot operator", // kExpectedTokenBeforeDotOperator
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "expected value", // kExpectedValue
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "handle member failed", // kHandleMemberFailed
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "handle member function failed", // kHandleMemberFunctionFailed
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "handle unbox failed", // kHandleUnboxFailed
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "index out of range", // kIndexOutOfRange
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "mismatched array brace", // kMismatchedArrayBrace
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "mismatched brackets", // kMismatchedBrackets
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "no function handler found", // kNoFunctionHandlerFound
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "premature end", // kPrematureEnd
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "too many parameters", // kTooManyParameters
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "type conversion failed", // kTypeConversionFailed
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        "unterminated string" // kUnterminatedString
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkScriptEngine::SkOperatorAttributes SkScriptEngine::gOpAttributes[] = {
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias }, //   kUnassigned,
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { SkOpType(kInt | kScalar | kString), SkOpType(kInt | kScalar | kString), kTowardsString }, // kAdd
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // kAddInt = kAdd,
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kAddScalar,
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kAddString,
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kArrayOp,
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kInt, kInt, kNoBias }, // kBitAnd
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kInt, kNoBias }, // kBitNot
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kInt, kInt, kNoBias }, // kBitOr
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { SkOpType(kInt | kScalar), SkOpType(kInt | kScalar), kNoBias }, // kDivide
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // kDivideInt = kDivide
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kDivideScalar
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kElse
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { SkOpType(kInt | kScalar | kString), SkOpType(kInt | kScalar | kString), kTowardsNumber }, // kEqual
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // kEqualInt = kEqual
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kEqualScalar
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kEqualString
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kInt, kNoType, kNoBias },     // kFlipOps
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { SkOpType(kInt | kScalar | kString), SkOpType(kInt | kScalar | kString), kTowardsNumber }, // kGreaterEqual
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // kGreaterEqualInt = kGreaterEqual
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kGreaterEqualScalar
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kGreaterEqualString
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kIf
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kInt, kNoBias }, // kLogicalAnd  (really, ToBool)
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kInt, kNoBias }, // kLogicalNot
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kInt, kInt, kNoBias }, // kLogicalOr
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, SkOpType(kInt | kScalar), kNoBias }, // kMinus
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // kMinusInt = kMinus
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kMinusScalar
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { SkOpType(kInt | kScalar), SkOpType(kInt | kScalar), kNoBias }, // kModulo
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // kModuloInt = kModulo
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kModuloScalar
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { SkOpType(kInt | kScalar), SkOpType(kInt | kScalar), kNoBias }, // kMultiply
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // kMultiplyInt = kMultiply
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kMultiplyScalar
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kParen
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kInt, kInt, kNoBias }, // kShiftLeft
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kInt, kInt, kNoBias }, // kShiftRight
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { SkOpType(kInt | kScalar), SkOpType(kInt | kScalar), kNoBias }, // kSubtract
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // kSubtractInt = kSubtract
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kNoType, kNoType, kNoBias },  // kSubtractScalar
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { kInt, kInt, kNoBias } // kXor
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Note that the real precedence for () [] is '2'
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// but here, precedence means 'while an equal or smaller precedence than the current operator
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// is on the stack, process it. This allows 3+5*2 to defer the add until after the multiply
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// is preformed, since the add precedence is not smaller than multiply.
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// But, (3*4 does not process the '(', since brackets are greater than all other precedences
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define kBracketPrecedence 16
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define kIfElsePrecedence 15
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst signed char SkScriptEngine::gPrecedence[] = {
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        -1, //  kUnassigned,
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        6, // kAdd,
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // kAddInt = kAdd,
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        6, // kAddScalar,
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        6, // kAddString,   // string concat
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kBracketPrecedence, // kArrayOp,
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        10, // kBitAnd,
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        4, // kBitNot,
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        12, // kBitOr,
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        5, // kDivide,
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // kDivideInt = kDivide,
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        5, // kDivideScalar,
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kIfElsePrecedence, // kElse,
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        9, // kEqual,
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // kEqualInt = kEqual,
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        9, // kEqualScalar,
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        9, // kEqualString,
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        -1, // kFlipOps,
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        8, // kGreaterEqual,
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // kGreaterEqualInt = kGreaterEqual,
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        8, // kGreaterEqualScalar,
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        8, // kGreaterEqualString,
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kIfElsePrecedence, // kIf,
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        13, // kLogicalAnd,
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        4, // kLogicalNot,
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        14, // kLogicalOr,
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        4, // kMinus,
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // kMinusInt = kMinus,
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        4, // kMinusScalar,
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        5, // kModulo,
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // kModuloInt = kModulo,
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        5, // kModuloScalar,
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        5, // kMultiply,
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // kMultiplyInt = kMultiply,
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        5, // kMultiplyScalar,
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kBracketPrecedence, // kParen,
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        7, // kShiftLeft,
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        7, // kShiftRight,  // signed
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        6, // kSubtract,
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // kSubtractInt = kSubtract,
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        6, // kSubtractScalar,
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        11, // kXor
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_between(int c, int min, int max)
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (unsigned)(c - min) <= (unsigned)(max - min);
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool is_ws(int c)
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return is_between(c, 1, 32);
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int token_length(const char* start) {
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char ch = start[0];
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (! is_between(ch, 'a' , 'z') &&  ! is_between(ch, 'A', 'Z') && ch != '_' && ch != '$')
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return -1;
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int length = 0;
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ch = start[++length];
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (is_between(ch, 'a' , 'z') || is_between(ch, 'A', 'Z') || is_between(ch, '0', '9') ||
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ch == '_' || ch == '$');
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return length;
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScriptEngine::SkScriptEngine(SkOpType returnType) :
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTokenLength(0), fReturnType(returnType), fError(kNoError)
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSuppress noInitialSuppress;
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    noInitialSuppress.fOperator = kUnassigned;
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    noInitialSuppress.fOpStackDepth = 0;
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    noInitialSuppress.fSuppress = false;
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    noInitialSuppress.fElse = 0;
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSuppressStack.push(noInitialSuppress);
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *fOpStack.push() = kParen;
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTrackArray.appendClear();
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTrackString.appendClear();
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScriptEngine::~SkScriptEngine() {
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (SkString** stringPtr = fTrackString.begin(); stringPtr < fTrackString.end(); stringPtr++)
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete *stringPtr;
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (SkTypedArray** arrayPtr = fTrackArray.begin(); arrayPtr < fTrackArray.end(); arrayPtr++)
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete *arrayPtr;
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkScriptEngine::arithmeticOp(char ch, char nextChar, bool lastPush) {
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOp op = kUnassigned;
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool reverseOperands = false;
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool negateResult = false;
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int advance = 1;
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (ch) {
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '+':
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // !!! ignoring unary plus as implemented here has the side effect of
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // suppressing errors like +"hi"
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (lastPush == false)  // unary plus, don't push an operator
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto returnAdv;
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kAdd;
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '-':
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = lastPush ? kSubtract : kMinus;
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '*':
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kMultiply;
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '/':
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kDivide;
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '>':
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (nextChar == '>') {
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                op = kShiftRight;
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto twoChar;
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kGreaterEqual;
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (nextChar == '=')
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto twoChar;
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            reverseOperands = negateResult = true;
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '<':
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (nextChar == '<') {
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                op = kShiftLeft;
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto twoChar;
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kGreaterEqual;
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            reverseOperands = nextChar == '=';
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            negateResult = ! reverseOperands;
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            advance += reverseOperands;
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '=':
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (nextChar == '=') {
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                op = kEqual;
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto twoChar;
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '!':
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (nextChar == '=') {
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                op = kEqual;
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                negateResult = true;
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QuerutwoChar:
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                advance++;
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kLogicalNot;
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '?':
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kIf;
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case ':':
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kElse;
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '^':
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kXor;
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '(':
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *fOpStack.push() = kParen;  // push even if eval is suppressed
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto returnAdv;
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '&':
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(nextChar != '&');
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kBitAnd;
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '|':
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(nextChar != '|');
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kBitOr;
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '%':
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kModulo;
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '~':
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = kBitNot;
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (op == kUnassigned)
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fSuppressStack.top().fSuppress == false) {
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        signed char precedence = gPrecedence[op];
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int idx = 0;
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkOp compare;
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            do {
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                compare = fOpStack.index(idx);
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if ((compare & kArtificialOp) == 0)
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    break;
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                idx++;
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } while (true);
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            signed char topPrecedence = gPrecedence[compare];
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(topPrecedence != -1);
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (topPrecedence > precedence || (topPrecedence == precedence &&
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    gOpAttributes[op].fLeftType == kNoType)) {
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (processOp() == false)
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return 0;   // error
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (true);
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (negateResult)
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *fOpStack.push() = (SkOp) (kLogicalNot | kArtificialOp);
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fOpStack.push(op);
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (reverseOperands)
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *fOpStack.push() = (SkOp) (kFlipOps | kArtificialOp);
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QuerureturnAdv:
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return advance;
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::boxCallBack(_boxCallBack func, void* userStorage) {
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UserCallBack callBack;
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    callBack.fBoxCallBack = func;
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    commonCallBack(kBox, callBack, userStorage);
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::commonCallBack(CallBackType type, UserCallBack& callBack, void* userStorage) {
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    callBack.fCallBackType = type;
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    callBack.fUserStorage = userStorage;
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *fUserCallBacks.prepend() = callBack;
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::convertParams(SkTDArray<SkScriptValue>& params,
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkFunctionParamType* paramTypes, int paramCount) {
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (params.count() > paramCount) {
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fError = kTooManyParameters;
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;   // too many parameters passed
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int index = 0; index < params.count(); index++) {
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (convertTo((SkDisplayTypes) paramTypes[index], &params[index]) == false)
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::convertTo(SkDisplayTypes toType, SkScriptValue* value ) {
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDisplayTypes type = value->fType;
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (type == toType)
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (ToOpType(type) == kObject) {
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0   // !!! I want object->string to get string from displaystringtype, not id
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ToOpType(toType) == kString) {
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            bool success = handleObjectToString(value->fOperand.fObject);
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (success == false)
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkOpType type;
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fTypeStack.pop(&type);
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            value->fType = ToDisplayType(type);
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fOperandStack.pop(&value->fOperand);
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (handleUnbox(value) == false) {
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fError = kHandleUnboxFailed;
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return convertTo(toType, value);
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return ConvertTo(this, toType, value);
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::evaluateDot(const char*& script, bool suppressed) {
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t fieldLength = token_length(++script);        // skip dot
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fieldLength == 0) {
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fError = kExpectedFieldName;
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* field = script;
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    script += fieldLength;
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = handleProperty(suppressed);
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (success == false) {
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fError = kCouldNotFindReferencedID; // note: never generated by standard animator plugins
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return evaluateDotParam(script, suppressed, field, fieldLength);
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::evaluateDotParam(const char*& script, bool suppressed,
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const char* field, size_t fieldLength) {
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void* object;
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (suppressed)
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        object = NULL;
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else {
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fTypeStack.top() != kObject) {
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fError = kDotOperatorExpectsObject;
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        object = fOperandStack.top().fObject;
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTypeStack.pop();
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fOperandStack.pop();
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char ch; // see if it is a simple member or a function
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (is_ws(ch = script[0]))
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        script++;
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = true;
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (ch != '(') {
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (suppressed == false) {
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if ((success = handleMember(field, fieldLength, object)) == false)
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fError = kHandleMemberFailed;
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkTDArray<SkScriptValue> params;
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fBraceStack.push() = kFunctionBrace;
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        success = functionParams(&script, params);
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success && suppressed == false &&
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                (success = handleMemberFunction(field, fieldLength, object, params)) == false)
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fError = kHandleMemberFunctionFailed;
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::evaluateScript(const char** scriptPtr, SkScriptValue* value) {
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char** original = scriptPtr;
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success;
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* inner;
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (strncmp(*scriptPtr, "#script:", sizeof("#script:") - 1) == 0) {
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *scriptPtr += sizeof("#script:") - 1;
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fReturnType == kNoType || fReturnType == kString) {
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            success = innerScript(scriptPtr, value);
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (success == false)
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto end;
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            inner = value->fOperand.fString->c_str();
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            scriptPtr = &inner;
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        success = innerScript(scriptPtr, value);
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success == false)
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto end;
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const char* script = *scriptPtr;
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char ch;
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        while (is_ws(ch = script[0]))
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            script++;
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ch != '\0') {
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // error may trigger on scripts like "50,0" that were intended to be written as "[50, 0]"
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fError = kPrematureEnd;
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            success = false;
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruend:
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (success == false) {
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf("script failed: %s", *original);
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fError)
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf(" %s", errorStrings[fError - 1]);
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf("\n");
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::forget(SkTypedArray* array) {
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (array->getType() == SkType_String) {
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int index = 0; index < array->count(); index++) {
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkString* string = (*array)[index].fString;
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int found = fTrackString.find(string);
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (found >= 0)
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fTrackString.remove(found);
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (array->getType() == SkType_Array) {
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int index = 0; index < array->count(); index++) {
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkTypedArray* child = (*array)[index].fArray;
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            forget(child);  // forgets children of child
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int found = fTrackArray.find(child);
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (found >= 0)
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fTrackArray.remove(found);
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::functionCallBack(_functionCallBack func, void* userStorage) {
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UserCallBack callBack;
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    callBack.fFunctionCallBack = func;
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    commonCallBack(kFunction, callBack, userStorage);
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::functionParams(const char** scriptPtr, SkTDArray<SkScriptValue>& params) {
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    (*scriptPtr)++; // skip open paren
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *fOpStack.push() = kParen;
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *fBraceStack.push() = kFunctionBrace;
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkBool suppressed = fSuppressStack.top().fSuppress;
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScriptValue value;
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool success = innerScript(scriptPtr, suppressed ? NULL : &value);
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success == false) {
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fError = kErrorInFunctionParameters;
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (suppressed)
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *params.append() = value;
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while ((*scriptPtr)[-1] == ',');
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fBraceStack.pop();
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fOpStack.pop(); // pop paren
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    (*scriptPtr)++; // advance beyond close paren
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::getErrorString(SkString* str) const {
51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fError)
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str->set(errorStrings[fError - 1]);
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fError != 0;
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::innerScript(const char** scriptPtr, SkScriptValue* value) {
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* script = *scriptPtr;
52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char ch;
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool lastPush = false;
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = true;
52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int opBalance = fOpStack.count();
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int baseBrace = fBraceStack.count();
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int suppressBalance = fSuppressStack.count();
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while ((ch = script[0]) != '\0') {
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (is_ws(ch)) {
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            script++;
52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkBool suppressed = fSuppressStack.top().fSuppress;
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkOperand operand;
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const char* dotCheck;
53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fBraceStack.count() > baseBrace) {
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0   // disable support for struct brace
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (ch == ':') {
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(fTokenLength > 0);
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(fBraceStack.top() == kStructBrace);
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                ++script;
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(fDisplayable);
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkString token(fToken, fTokenLength);
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fTokenLength = 0;
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                const char* tokenName = token.c_str();
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                const SkMemberInfo* tokenInfo SK_INIT_TO_AVOID_WARNING;
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (suppressed == false) {
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDisplayTypes type = fInfo->getType();
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    tokenInfo = SkDisplayType::GetMember(type, &tokenName);
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkASSERT(tokenInfo);
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
55080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkScriptValue tokenValue;
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                success = innerScript(&script, &tokenValue);    // terminate and return on comma, close brace
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(success);
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (suppressed == false) {
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (tokenValue.fType == SkType_Displayable) {
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkASSERT(SkDisplayType::IsDisplayable(tokenInfo->getType()));
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        fDisplayable->setReference(tokenInfo, tokenValue.fOperand.fDisplayable);
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    } else {
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        if (tokenValue.fType != tokenInfo->getType()) {
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            if (convertTo(tokenInfo->getType(), &tokenValue) == false)
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                return false;
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        }
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        tokenInfo->writeValue(fDisplayable, NULL, 0, 0,
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            (void*) ((char*) fInfo->memberData(fDisplayable) + tokenInfo->fOffset + fArrayOffset),
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            tokenInfo->getType(), tokenValue);
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                lastPush = false;
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fBraceStack.top() == kArrayBrace) {
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkScriptValue tokenValue;
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                success = innerScript(&script, &tokenValue);    // terminate and return on comma, close brace
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (success == false) {
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fError = kErrorInArrrayIndex;
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (suppressed == false) {
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0 // no support for structures for now
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (tokenValue.fType == SkType_Structure) {
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        fArrayOffset += (int) fInfo->getSize(fDisplayable);
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    } else
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    {
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkDisplayTypes type = ToDisplayType(fReturnType);
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        if (fReturnType == kNoType) {
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            // !!! short sighted; in the future, allow each returned array component to carry
58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            // its own type, and let caller do any needed conversions
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            if (value->fOperand.fArray->count() == 0)
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                value->fOperand.fArray->setType(type = tokenValue.fType);
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            else
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                type = value->fOperand.fArray->getType();
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        }
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        if (tokenValue.fType != type) {
59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            if (convertTo(type, &tokenValue) == false)
59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                return false;
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        }
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        *value->fOperand.fArray->append() = tokenValue.fOperand;
59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                lastPush = false;
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (token_length(script) == 0) {
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fError = kExpectedToken;
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (lastPush != false && fTokenLength > 0) {
61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (ch == '(') {
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *fBraceStack.push() = kFunctionBrace;
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (handleFunction(&script, SkToBool(suppressed)) == false)
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;
61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                lastPush = true;
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (ch == '[') {
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (handleProperty(SkToBool(suppressed)) == false)
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;   // note: never triggered by standard animator plugins
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (handleArrayIndexer(&script, SkToBool(suppressed)) == false)
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                lastPush = true;
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (ch != '.') {
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (handleProperty(SkToBool(suppressed)) == false)
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;   // note: never triggered by standard animator plugins
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                lastPush = true;
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ch == '0' && (script[1] & ~0x20) == 'X') {
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (lastPush != false) {
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kExpectedOperator;
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            script += 2;
63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            script = SkParse::FindHex(script, (uint32_t*)&operand.fS32);
63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (script == NULL) {
63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kExpectedHex;
64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto intCommon;
64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (lastPush == false && ch == '.')
64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto scalarCommon;
64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ch >= '0' && ch <= '9') {
64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (lastPush != false) {
64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kExpectedOperator;
64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dotCheck = SkParse::FindS32(script, &operand.fS32);
65280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (dotCheck[0] != '.') {
65380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                script = dotCheck;
65480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruintCommon:
65580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (suppressed == false)
65680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    *fTypeStack.push() = kInt;
65780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruscalarCommon:
65980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                script = SkParse::FindScalar(script, &operand.fScalar);
66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (suppressed == false)
66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    *fTypeStack.push() = kScalar;
66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (suppressed == false)
66480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.push(operand);
66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            lastPush = true;
66680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
66780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
66880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int length = token_length(script);
66980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (length > 0) {
67080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (lastPush != false) {
67180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kExpectedOperator;
67280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
67380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
67480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fToken = script;
67580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fTokenLength = length;
67680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            script += length;
67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            lastPush = true;
67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
68080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char startQuote = ch;
68180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (startQuote == '\'' || startQuote == '\"') {
68280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (lastPush != false) {
68380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kExpectedOperator;
68480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
68680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand.fString = new SkString();
68780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            track(operand.fString);
68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ++script;
68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // <mrr> this is a lot of calls to append() one char at at time
69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // how hard to preflight script so we know how much to grow fString by?
69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            do {
69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (script[0] == '\\')
69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    ++script;
69580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand.fString->append(script, 1);
69680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                ++script;
69780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (script[0] == '\0') {
69880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fError = kUnterminatedString;
69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;
70080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
70180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } while (script[0] != startQuote);
70280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ++script;
70380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (suppressed == false) {
70480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *fTypeStack.push() = kString;
70580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.push(operand);
70680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            lastPush = true;
70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ;
71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ch ==  '.') {
71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fTokenLength == 0) {
71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkScriptValue scriptValue;
71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDEBUGCODE(scriptValue.fOperand.fObject = NULL);
71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                int tokenLength = token_length(++script);
71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                const char* token = script;
71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                script += tokenLength;
71880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (suppressed == false) {
71980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (fTypeStack.count() == 0) {
72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        fError = kExpectedTokenBeforeDotOperator;
72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        return false;
72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkOpType topType;
72480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fTypeStack.pop(&topType);
72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fOperandStack.pop(&scriptValue.fOperand);
72680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    scriptValue.fType = ToDisplayType(topType);
72780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    handleBox(&scriptValue);
72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
72980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                success = evaluateDotParam(script, SkToBool(suppressed), token, tokenLength);
73080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (success == false)
73180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;
73280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                lastPush = true;
73380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
73480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
73580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // get next token, and evaluate immediately
73680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            success = evaluateDot(script, SkToBool(suppressed));
73780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (success == false)
73880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
73980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            lastPush = true;
74080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
74180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
74280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ch == '[') {
74380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (lastPush == false) {
74480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                script++;
74580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *fBraceStack.push() = kArrayBrace;
74680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (suppressed)
74780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    continue;
74880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand.fArray = value->fOperand.fArray = new SkTypedArray(ToDisplayType(fReturnType));
74980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                track(value->fOperand.fArray);
75080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *fTypeStack.push() = (SkOpType) kArray;
75180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.push(operand);
75280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
75380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
75480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (handleArrayIndexer(&script, SkToBool(suppressed)) == false)
75580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
75680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            lastPush = true;
75780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
75880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
75980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0 // structs not supported for now
76080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ch == '{') {
76180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (lastPush == false) {
76280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                script++;
76380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *fBraceStack.push() = kStructBrace;
76480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (suppressed)
76580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    continue;
76680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand.fS32 = 0;
76780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *fTypeStack.push() = (SkOpType) kStruct;
76880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.push(operand);
76980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
77080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
77180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0); // braces in other contexts aren't supported yet
77280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
77380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
77480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ch == ')' && fBraceStack.count() > 0) {
77580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkBraceStyle braceStyle = fBraceStack.top();
77680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (braceStyle == kFunctionBrace) {
77780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fBraceStack.pop();
77880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
77980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
78080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
78180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (ch == ',' || ch == ']') {
78280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (ch != ',') {
78380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkBraceStyle match;
78480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fBraceStack.pop(&match);
78580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (match != kArrayBrace) {
78680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fError = kMismatchedArrayBrace;
78780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;
78880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
78980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
79080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            script++;
79180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // !!! see if brace or bracket is correct closer
79280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
79380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
79480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char nextChar = script[1];
79580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int advance = logicalOp(ch, nextChar);
79680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (advance < 0)     // error
79780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
79880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (advance == 0)
79980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            advance = arithmeticOp(ch, nextChar, lastPush);
80080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (advance == 0) // unknown token
80180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
80280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (advance > 0)
80380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            script += advance;
80480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        lastPush = ch == ']' || ch == ')';
80580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
80680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool suppressed = SkToBool(fSuppressStack.top().fSuppress);
80780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fTokenLength > 0) {
80880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        success = handleProperty(suppressed);
80980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success == false)
81080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;   // note: never triggered by standard animator plugins
81180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
81280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (fOpStack.count() > opBalance) {   // leave open paren
81380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if ((fError = opError()) != kNoError)
81480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
81580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (processOp() == false)
81680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
81780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
81880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOpType topType = fTypeStack.count() > 0 ? fTypeStack.top() : kNoType;
81980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (suppressed == false && topType != fReturnType &&
82080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            topType == kString && fReturnType != kNoType) { // if result is a string, give handle property a chance to convert it to the property value
82180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString* string = fOperandStack.top().fString;
82280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fToken = string->c_str();
82380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTokenLength = string->size();
82480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fOperandStack.pop();
82580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTypeStack.pop();
82680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        success = handleProperty(SkToBool(fSuppressStack.top().fSuppress));
82780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success == false) { // if it couldn't convert, return string (error?)
82880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkOperand operand;
82980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand.fS32 = 0;
83080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *fTypeStack.push() = kString;
83180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand.fString = string;
83280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fOperandStack.push(operand);
83380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
83480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
83580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value) {
83680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fOperandStack.count() == 0)
83780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
83880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fOperandStack.count() >= 1);
83980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fTypeStack.count() >= 1);
84080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fOperandStack.pop(&value->fOperand);
84180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkOpType type;
84280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTypeStack.pop(&type);
84380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        value->fType = ToDisplayType(type);
84480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//      SkASSERT(value->fType != SkType_Unknown);
84580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (topType != fReturnType && topType == kObject && fReturnType != kNoType) {
84680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (convertTo(ToDisplayType(fReturnType), value) == false)
84780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
84880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
84980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
85080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (fSuppressStack.count() > suppressBalance)
85180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fSuppressStack.pop();
85280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *scriptPtr = script;
85380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true; // no error
85480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
85580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
85680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::memberCallBack(_memberCallBack member , void* userStorage) {
85780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UserCallBack callBack;
85880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    callBack.fMemberCallBack = member;
85980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    commonCallBack(kMember, callBack, userStorage);
86080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
86180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::memberFunctionCallBack(_memberFunctionCallBack func, void* userStorage) {
86380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UserCallBack callBack;
86480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    callBack.fMemberFunctionCallBack = func;
86580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    commonCallBack(kMemberFunction, callBack, userStorage);
86680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
86780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
86980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::objectToStringCallBack(_objectToStringCallBack func, void* userStorage) {
87080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UserCallBack callBack;
87180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    callBack.fObjectToStringCallBack = func;
87280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    commonCallBack(kObjectToString, callBack, userStorage);
87380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
87480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
87580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::handleArrayIndexer(const char** scriptPtr, bool suppressed) {
87780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScriptValue scriptValue;
87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    (*scriptPtr)++;
87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *fOpStack.push() = kParen;
88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *fBraceStack.push() = kArrayBrace;
88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOpType saveType = fReturnType;
88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fReturnType = kInt;
88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = innerScript(scriptPtr, suppressed == false ? &scriptValue : NULL);
88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (success == false)
88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fReturnType = saveType;
88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (suppressed == false) {
88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (convertTo(SkType_Int, &scriptValue) == false)
88980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int index = scriptValue.fOperand.fS32;
89180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScriptValue scriptValue;
89280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkOpType type;
89380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTypeStack.pop(&type);
89480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fOperandStack.pop(&scriptValue.fOperand);
89580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scriptValue.fType = ToDisplayType(type);
89680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (type == kObject) {
89780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            success = handleUnbox(&scriptValue);
89880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (success == false)
89980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (ToOpType(scriptValue.fType) != kArray) {
90180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kExpectedArray;
90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
90380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
90480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *fTypeStack.push() = scriptValue.fOperand.fArray->getOpType();
90680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//      SkASSERT(index >= 0);
90780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if ((unsigned) index >= (unsigned) scriptValue.fOperand.fArray->count()) {
90880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fError = kArrayIndexOutOfBounds;
90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
91180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scriptValue.fOperand = scriptValue.fOperand.fArray->begin()[index];
91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fOperandStack.push(scriptValue.fOperand);
91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fOpStack.pop(); // pop paren
91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::handleBox(SkScriptValue* scriptValue) {
91980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = true;
92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (UserCallBack* callBack = fUserCallBacks.begin(); callBack < fUserCallBacks.end(); callBack++) {
92180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (callBack->fCallBackType != kBox)
92280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
92380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        success = (*callBack->fBoxCallBack)(callBack->fUserStorage, scriptValue);
92480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success) {
92580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fOperandStack.push(scriptValue->fOperand);
92680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *fTypeStack.push() = ToOpType(scriptValue->fType);
92780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto done;
92880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
92980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
93080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudone:
93180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
93280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
93380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
93480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::handleFunction(const char** scriptPtr, bool suppressed) {
93580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScriptValue callbackResult;
93680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTDArray<SkScriptValue> params;
93780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkString functionName(fToken, fTokenLength);
93880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTokenLength = 0;
93980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = functionParams(scriptPtr, params);
94080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (success == false)
94180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        goto done;
94280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (suppressed == true)
94380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
94480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
94580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (UserCallBack* callBack = fUserCallBacks.begin(); callBack < fUserCallBacks.end(); callBack++) {
94680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (callBack->fCallBackType != kFunction)
94780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
94880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            success = (*callBack->fFunctionCallBack)(functionName.c_str(), functionName.size(), params,
94980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                callBack->fUserStorage, &callbackResult);
95080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (success) {
95180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.push(callbackResult.fOperand);
95280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *fTypeStack.push() = ToOpType(callbackResult.fType);
95380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto done;
95480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
95580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
95680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
95780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fError = kNoFunctionHandlerFound;
95880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
95980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudone:
96080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
96180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
96280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
96380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::handleMember(const char* field, size_t len, void* object) {
96480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScriptValue callbackResult;
96580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = true;
96680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (UserCallBack* callBack = fUserCallBacks.begin(); callBack < fUserCallBacks.end(); callBack++) {
96780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (callBack->fCallBackType != kMember)
96880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
96980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        success = (*callBack->fMemberCallBack)(field, len, object, callBack->fUserStorage, &callbackResult);
97080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success) {
97180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (callbackResult.fType == SkType_String)
97280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                track(callbackResult.fOperand.fString);
97380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fOperandStack.push(callbackResult.fOperand);
97480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *fTypeStack.push() = ToOpType(callbackResult.fType);
97580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto done;
97680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
97780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
97880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
97980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudone:
98080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
98180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
98280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
98380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::handleMemberFunction(const char* field, size_t len, void* object, SkTDArray<SkScriptValue>& params) {
98480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScriptValue callbackResult;
98580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = true;
98680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (UserCallBack* callBack = fUserCallBacks.begin(); callBack < fUserCallBacks.end(); callBack++) {
98780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (callBack->fCallBackType != kMemberFunction)
98880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
98980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        success = (*callBack->fMemberFunctionCallBack)(field, len, object, params,
99080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            callBack->fUserStorage, &callbackResult);
99180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success) {
99280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (callbackResult.fType == SkType_String)
99380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                track(callbackResult.fOperand.fString);
99480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fOperandStack.push(callbackResult.fOperand);
99580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *fTypeStack.push() = ToOpType(callbackResult.fType);
99680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto done;
99780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
99880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
99980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
100080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudone:
100180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
100280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
100380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
100480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
100580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::handleObjectToString(void* object) {
100680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScriptValue callbackResult;
100780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = true;
100880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (UserCallBack* callBack = fUserCallBacks.begin(); callBack < fUserCallBacks.end(); callBack++) {
100980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (callBack->fCallBackType != kObjectToString)
101080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
101180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        success = (*callBack->fObjectToStringCallBack)(object,
101280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            callBack->fUserStorage, &callbackResult);
101380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success) {
101480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (callbackResult.fType == SkType_String)
101580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                track(callbackResult.fOperand.fString);
101680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fOperandStack.push(callbackResult.fOperand);
101780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *fTypeStack.push() = ToOpType(callbackResult.fType);
101880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto done;
101980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
102080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
102180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
102280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudone:
102380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
102480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
102580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
102680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
102780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::handleProperty(bool suppressed) {
102880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScriptValue callbackResult;
102980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = true;
103080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (suppressed)
103180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        goto done;
103280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    success = false; // note that with standard animator-script plugins, callback never returns false
103380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
103480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (UserCallBack* callBack = fUserCallBacks.begin(); callBack < fUserCallBacks.end(); callBack++) {
103580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (callBack->fCallBackType != kProperty)
103680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                continue;
103780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            success = (*callBack->fPropertyCallBack)(fToken, fTokenLength,
103880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                callBack->fUserStorage, &callbackResult);
103980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (success) {
104080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (callbackResult.fType == SkType_String && callbackResult.fOperand.fString == NULL) {
104180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    callbackResult.fOperand.fString = new SkString(fToken, fTokenLength);
104280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    track(callbackResult.fOperand.fString);
104380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
104480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.push(callbackResult.fOperand);
104580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *fTypeStack.push() = ToOpType(callbackResult.fType);
104680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto done;
104780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
104880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
104980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
105080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudone:
105180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTokenLength = 0;
105280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
105380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
105480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
105580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::handleUnbox(SkScriptValue* scriptValue) {
105680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = true;
105780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (UserCallBack* callBack = fUserCallBacks.begin(); callBack < fUserCallBacks.end(); callBack++) {
105880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (callBack->fCallBackType != kUnbox)
105980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue;
106080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        success = (*callBack->fUnboxCallBack)(callBack->fUserStorage, scriptValue);
106180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success) {
106280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (scriptValue->fType == SkType_String)
106380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                track(scriptValue->fOperand.fString);
106480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto done;
106580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
106680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
106780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
106880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudone:
106980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
107080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
107180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
107280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// note that entire expression is treated as if it were enclosed in parens
107380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// an open paren is always the first thing in the op stack
107480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
107580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkScriptEngine::logicalOp(char ch, char nextChar) {
107680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int advance = 1;
107780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOp match;
107880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    signed char precedence;
107980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (ch) {
108080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case ')':
108180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            match = kParen;
108280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
108380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case ']':
108480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            match = kArrayOp;
108580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
108680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '?':
108780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            match = kIf;
108880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
108980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case ':':
109080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            match = kElse;
109180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
109280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '&':
109380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (nextChar != '&')
109480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto noMatch;
109580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            match = kLogicalAnd;
109680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            advance = 2;
109780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
109880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case '|':
109980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (nextChar != '|')
110080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                goto noMatch;
110180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            match = kLogicalOr;
110280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            advance = 2;
110380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
110480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
110580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QuerunoMatch:
110680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return 0;
110780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
110880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSuppress suppress;
110980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    precedence = gPrecedence[match];
111080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fSuppressStack.top().fSuppress) {
111180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fSuppressStack.top().fOpStackDepth < fOpStack.count()) {
111280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkOp topOp = fOpStack.top();
111380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (gPrecedence[topOp] <= precedence)
111480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOpStack.pop();
111580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto goHome;
111680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
111780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool changedPrecedence = gPrecedence[fSuppressStack.top().fOperator] < precedence;
111880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (changedPrecedence)
111980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fSuppressStack.pop();
112080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (precedence == kIfElsePrecedence) {
112180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (match == kIf) {
112280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (changedPrecedence)
112380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fOpStack.pop();
112480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                else
112580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    *fOpStack.push() = kIf;
112680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
112780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (fSuppressStack.top().fOpStackDepth == fOpStack.count()) {
112880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    goto flipSuppress;
112980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
113080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOpStack.pop();
113180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
113280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
113380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (changedPrecedence == false)
113480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            goto goHome;
113580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
113680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (gPrecedence[fOpStack.top() & ~kArtificialOp] < precedence) {
113780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (processOp() == false)
113880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
113980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
114080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fSuppressStack.top().fOpStackDepth > fOpStack.count())
114180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fSuppressStack.pop();
114280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (match) {
114380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kParen:
114480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kArrayOp:
114580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fOpStack.count() <= 1 || fOpStack.top() != match) {
114680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kMismatchedBrackets;
114780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return -1;
114880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
114980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (match == kParen)
115080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOpStack.pop();
115180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            else {
115280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkOpType indexType;
115380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fTypeStack.pop(&indexType);
115480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (indexType != kInt && indexType != kScalar) {
115580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fError = kExpectedNumberForArrayIndex; // (although, could permit strings eventually)
115680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return -1;
115780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
115880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkOperand indexOperand;
115980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.pop(&indexOperand);
116080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                int index = indexType == kScalar ? SkScalarFloor(indexOperand.fScalar) :
116180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    indexOperand.fS32;
116280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkOpType arrayType;
116380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fTypeStack.pop(&arrayType);
116480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if ((unsigned)arrayType != (unsigned)kArray) {
116580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fError = kExpectedArray;
116680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return -1;
116780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
116880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkOperand arrayOperand;
116980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.pop(&arrayOperand);
117080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkTypedArray* array = arrayOperand.fArray;
117180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkOperand operand;
117280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (array->getIndex(index, &operand) == false) {
117380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fError = kIndexOutOfRange;
117480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return -1;
117580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
117680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkOpType resultType = array->getOpType();
117780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fTypeStack.push(resultType);
117880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.push(operand);
117980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
118080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
118180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kIf: {
118280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScriptValue ifValue;
118380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkOpType ifType;
118480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fTypeStack.pop(&ifType);
118580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ifValue.fType = ToDisplayType(ifType);
118680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fOperandStack.pop(&ifValue.fOperand);
118780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (convertTo(SkType_Int, &ifValue) == false)
118880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return -1;
118980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (ifValue.fType != SkType_Int) {
119080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kExpectedIntForConditionOperator;
119180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return -1;
119280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
119380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            suppress.fSuppress = ifValue.fOperand.fS32 == 0;
119480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            suppress.fOperator = kIf;
119580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            suppress.fOpStackDepth = fOpStack.count();
119680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            suppress.fElse = false;
119780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fSuppressStack.push(suppress);
119880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // if left is true, do only up to colon
119980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // if left is false, do only after colon
120080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } break;
120180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kElse:
120280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruflipSuppress:
120380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fSuppressStack.top().fElse)
120480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fSuppressStack.pop();
120580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fSuppressStack.top().fElse = true;
120680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fSuppressStack.top().fSuppress ^= true;
120780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // flip last do / don't do consideration from last '?'
120880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
120980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kLogicalAnd:
121080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kLogicalOr: {
121180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fTypeStack.top() != kInt) {
121280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kExpectedBooleanExpression;
121380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return -1;
121480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
121580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            int32_t topInt = fOperandStack.top().fS32;
121680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fOpStack.top() != kLogicalAnd)
121780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                *fOpStack.push() = kLogicalAnd; // really means 'to bool', and is appropriate for 'or'
121880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (match == kLogicalOr ? topInt != 0 : topInt == 0) {
121980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                suppress.fSuppress = true;
122080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                suppress.fOperator = match;
122180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                suppress.fOpStackDepth = fOpStack.count();
122280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                suppress.fElse = false;
122380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fSuppressStack.push(suppress);
122480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
122580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fTypeStack.pop();
122680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fOperandStack.pop();
122780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
122880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }   break;
122980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
123080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0);
123180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
123280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QuerugoHome:
123380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return advance;
123480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
123580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
123680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScriptEngine::Error SkScriptEngine::opError() {
123780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int opCount = fOpStack.count();
123880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int operandCount = fOperandStack.count();
123980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (opCount == 0) {
124080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (operandCount != 1)
124180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kExpectedOperator;
124280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return kNoError;
124380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
124480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOp op = (SkOp) (fOpStack.top() & ~kArtificialOp);
124580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkOperatorAttributes* attributes = &gOpAttributes[op];
124680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (attributes->fLeftType != kNoType && operandCount < 2)
124780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return kExpectedValue;
124880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (attributes->fLeftType == kNoType && operandCount < 1)
124980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return kExpectedValue;
125080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return kNoError;
125180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
125280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
125380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::processOp() {
125480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOp op;
125580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fOpStack.pop(&op);
125680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    op = (SkOp) (op & ~kArtificialOp);
125780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const SkOperatorAttributes* attributes = &gOpAttributes[op];
125880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOpType type2;
125980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTypeStack.pop(&type2);
126080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOpType type1 = type2;
126180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOperand operand2;
126280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fOperandStack.pop(&operand2);
126380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOperand operand1 = operand2; // !!! not really needed, suppresses warning
126480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (attributes->fLeftType != kNoType) {
126580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTypeStack.pop(&type1);
126680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fOperandStack.pop(&operand1);
126780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (op == kFlipOps) {
126880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkTSwap(type1, type2);
126980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkTSwap(operand1, operand2);
127080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fOpStack.pop(&op);
127180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            op = (SkOp) (op & ~kArtificialOp);
127280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            attributes = &gOpAttributes[op];
127380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
127480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (type1 == kObject && (type1 & attributes->fLeftType) == 0) {
127580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkScriptValue val;
127680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            val.fType = ToDisplayType(type1);
127780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            val.fOperand = operand1;
127880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            bool success = handleUnbox(&val);
127980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (success == false)
128080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
128180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            type1 = ToOpType(val.fType);
128280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand1 = val.fOperand;
128380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
128480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
128580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (type2 == kObject && (type2 & attributes->fLeftType) == 0) {
128680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScriptValue val;
128780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        val.fType = ToDisplayType(type2);
128880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        val.fOperand = operand2;
128980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool success = handleUnbox(&val);
129080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (success == false)
129180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
129280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        type2 = ToOpType(val.fType);
129380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        operand2 = val.fOperand;
129480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
129580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (attributes->fLeftType != kNoType) {
129680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (type1 != type2) {
129780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if ((attributes->fLeftType & kString) && attributes->fBias & kTowardsString && ((type1 | type2) & kString)) {
129880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (type1 == kInt || type1 == kScalar) {
129980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    convertToString(operand1, type1 == kInt ? SkType_Int : SkType_Float);
130080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    type1 = kString;
130180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
130280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (type2 == kInt || type2 == kScalar) {
130380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    convertToString(operand2, type2 == kInt ? SkType_Int : SkType_Float);
130480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    type2 = kString;
130580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
130680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (attributes->fLeftType & kScalar && ((type1 | type2) & kScalar)) {
130780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (type1 == kInt) {
130880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    operand1.fScalar = IntToScalar(operand1.fS32);
130980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    type1 = kScalar;
131080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
131180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (type2 == kInt) {
131280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    operand2.fScalar = IntToScalar(operand2.fS32);
131380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                     type2 = kScalar;
131480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
131580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
131680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
131780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if ((type1 & attributes->fLeftType) == 0 || type1 != type2) {
131880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (type1 == kString) {
131980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                const char* result = SkParse::FindScalar(operand1.fString->c_str(), &operand1.fScalar);
132080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (result == NULL) {
132180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    fError = kExpectedNumber;
132280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return false;
132380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
132480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                type1 = kScalar;
132580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
132680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (type1 == kScalar && (attributes->fLeftType == kInt || type2 == kInt)) {
132780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand1.fS32 = SkScalarFloor(operand1.fScalar);
132880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                type1 = kInt;
132980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
133080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
133180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
133280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((type2 & attributes->fRightType) == 0 || type1 != type2) {
133380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (type2 == kString) {
133480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            const char* result = SkParse::FindScalar(operand2.fString->c_str(), &operand2.fScalar);
133580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (result == NULL) {
133680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fError = kExpectedNumber;
133780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
133880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
133980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            type2 = kScalar;
134080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
134180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (type2 == kScalar && (attributes->fRightType == kInt || type1 == kInt)) {
134280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = SkScalarFloor(operand2.fScalar);
134380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            type2 = kInt;
134480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
134580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
134680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (type2 == kScalar)
134780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        op = (SkOp) (op + 1);
134880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else if (type2 == kString)
134980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        op = (SkOp) (op + 2);
135080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch(op) {
135180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kAddInt:
135280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 += operand1.fS32;
135380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
135480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kAddScalar:
135580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fScalar += operand1.fScalar;
135680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
135780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kAddString:
135880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fTrackString.find(operand1.fString) < 0) {
135980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand1.fString = SkNEW_ARGS(SkString, (*operand1.fString));
136080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                track(operand1.fString);
136180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
136280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand1.fString->append(*operand2.fString);
136380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2 = operand1;
136480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
136580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kBitAnd:
136680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 &= operand1.fS32;
136780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
136880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kBitNot:
136980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = ~operand2.fS32;
137080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
137180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kBitOr:
137280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 |= operand1.fS32;
137380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
137480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kDivideInt:
137580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (operand2.fS32 == 0) {
137680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand2.fS32 = operand1.fS32 == 0 ? SK_NaN32 : operand1.fS32 > 0 ? SK_MaxS32 : -SK_MaxS32;
137780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
137880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
137980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                int32_t original = operand2.fS32;
138080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand2.fS32 = operand1.fS32 / operand2.fS32;
138180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (original * operand2.fS32 == operand1.fS32)
138280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    break;    // integer divide was good enough
138380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand2.fS32 = original;
138480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                type2 = kScalar;
138580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
138680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kDivideScalar:
138780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (operand2.fScalar == 0)
138880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand2.fScalar = operand1.fScalar == 0 ? SK_ScalarNaN : operand1.fScalar > 0 ? SK_ScalarMax : -SK_ScalarMax;
138980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            else
139080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand2.fScalar = SkScalarDiv(operand1.fScalar, operand2.fScalar);
139180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
139280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kEqualInt:
139380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = operand1.fS32 == operand2.fS32;
139480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
139580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kEqualScalar:
139680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = operand1.fScalar == operand2.fScalar;
139780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            type2 = kInt;
139880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
139980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kEqualString:
140080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = *operand1.fString == *operand2.fString;
140180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            type2 = kInt;
140280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
140380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kGreaterEqualInt:
140480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = operand1.fS32 >= operand2.fS32;
140580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
140680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kGreaterEqualScalar:
140780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = operand1.fScalar >= operand2.fScalar;
140880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            type2 = kInt;
140980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
141080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kGreaterEqualString:
141180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = strcmp(operand1.fString->c_str(), operand2.fString->c_str()) >= 0;
141280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            type2 = kInt;
141380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
141480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kLogicalAnd:
141580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = !! operand2.fS32;   // really, ToBool
141680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
141780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kLogicalNot:
141880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = ! operand2.fS32;
141980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
142080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kLogicalOr:
142180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0);    // should have already been processed
142280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
142380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kMinusInt:
142480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = -operand2.fS32;
142580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
142680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kMinusScalar:
142780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fScalar = -operand2.fScalar;
142880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
142980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kModuloInt:
143080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = operand1.fS32 % operand2.fS32;
143180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
143280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kModuloScalar:
143380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fScalar = SkScalarMod(operand1.fScalar, operand2.fScalar);
143480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
143580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kMultiplyInt:
143680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 *= operand1.fS32;
143780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
143880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kMultiplyScalar:
143980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fScalar = SkScalarMul(operand1.fScalar, operand2.fScalar);
144080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
144180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kShiftLeft:
144280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = operand1.fS32 << operand2.fS32;
144380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
144480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kShiftRight:
144580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = operand1.fS32 >> operand2.fS32;
144680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
144780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kSubtractInt:
144880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 = operand1.fS32 - operand2.fS32;
144980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
145080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kSubtractScalar:
145180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fScalar = operand1.fScalar - operand2.fScalar;
145280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
145380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kXor:
145480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand2.fS32 ^= operand1.fS32;
145580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
145680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
145780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0);
145880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
145980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTypeStack.push(type2);
146080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fOperandStack.push(operand2);
146180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
146280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
146380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
146480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::propertyCallBack(_propertyCallBack prop, void* userStorage) {
146580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UserCallBack callBack;
146680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    callBack.fPropertyCallBack = prop;
146780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    commonCallBack(kProperty, callBack, userStorage);
146880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
146980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
147080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::track(SkTypedArray* array) {
147180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fTrackArray.find(array) < 0);
147280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *(fTrackArray.end() - 1) = array;
147380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTrackArray.appendClear();
147480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
147580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
147680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::track(SkString* string) {
147780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fTrackString.find(string) < 0);
147880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *(fTrackString.end() - 1) = string;
147980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fTrackString.appendClear();
148080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
148180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
148280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::unboxCallBack(_unboxCallBack func, void* userStorage) {
148380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    UserCallBack callBack;
148480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    callBack.fUnboxCallBack = func;
148580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    commonCallBack(kUnbox, callBack, userStorage);
148680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
148780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
148880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::ConvertTo(SkScriptEngine* engine, SkDisplayTypes toType, SkScriptValue* value ) {
148980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(value);
149080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkDisplayType::IsEnum(NULL /* fMaker */, toType))
149180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        toType = SkType_Int;
149280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (toType == SkType_Point || toType == SkType_3D_Point)
149380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        toType = SkType_Float;
149480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (toType == SkType_Drawable)
149580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        toType = SkType_Displayable;
149680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDisplayTypes type = value->fType;
149780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (type == toType)
149880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
149980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOperand& operand = value->fOperand;
150080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool success = true;
150180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (toType) {
150280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_Int:
150380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (type == SkType_Boolean)
150480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
150580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (type == SkType_Float)
150680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                operand.fS32 = SkScalarFloor(operand.fScalar);
150780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            else {
150880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (type != SkType_String) {
150980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    success = false;
151080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    break; // error
151180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
151280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                success = SkParse::FindS32(operand.fString->c_str(), &operand.fS32) != NULL;
151380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
151480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
151580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_Float:
151680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (type == SkType_Int) {
1517d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                if (operand.fS32 == SK_NaN32)
151880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    operand.fScalar = SK_ScalarNaN;
151980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                else if (SkAbs32(operand.fS32) == SK_MaxS32)
152080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    operand.fScalar = SkSign32(operand.fS32) * SK_ScalarMax;
152180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                else
152280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    operand.fScalar = SkIntToScalar(operand.fS32);
152380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
152480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (type != SkType_String) {
152580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    success = false;
152680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    break; // error
152780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
152880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                success = SkParse::FindScalar(operand.fString->c_str(), &operand.fScalar) != NULL;
152980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
153080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
153180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_String: {
153280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkString* strPtr = new SkString();
153380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(engine);
153480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            engine->track(strPtr);
153580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (type == SkType_Int)
153680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                strPtr->appendS32(operand.fS32);
153780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            else if (type == SkType_Displayable)
153880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(0); // must call through instance version instead of static version
153980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            else {
154080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (type != SkType_Float) {
154180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    success = false;
154280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    break;
154380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
154480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                strPtr->appendScalar(operand.fScalar);
154580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
154680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand.fString = strPtr;
154780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } break;
154880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_Array: {
154980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkTypedArray* array = new SkTypedArray(type);
155080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *array->append() = operand;
155180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            engine->track(array);
155280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            operand.fArray = array;
155380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } break;
155480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
155580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0);
155680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
155780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    value->fType = toType;
155880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (success == false)
155980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        engine->fError = kTypeConversionFailed;
156080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return success;
156180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
156280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
156380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkScriptEngine::IntToScalar(int32_t s32) {
156480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar scalar;
1565d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (s32 == SK_NaN32)
156680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scalar = SK_ScalarNaN;
156780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else if (SkAbs32(s32) == SK_MaxS32)
156880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scalar = SkSign32(s32) * SK_ScalarMax;
156980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else
157080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        scalar = SkIntToScalar(s32);
157180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return scalar;
157280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
157380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
157480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkDisplayTypes SkScriptEngine::ToDisplayType(SkOpType type) {
157580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int val = type;
157680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (val) {
157780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kNoType:
157880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkType_Unknown;
157980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kInt:
158080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkType_Int;
158180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kScalar:
158280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkType_Float;
158380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kString:
158480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkType_String;
158580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kArray:
158680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkType_Array;
158780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kObject:
158880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkType_Displayable;
158980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//      case kStruct:
159080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//          return SkType_Structure;
159180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
159280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0);
159380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkType_Unknown;
159480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
159580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
159680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
159780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScriptEngine::SkOpType SkScriptEngine::ToOpType(SkDisplayTypes type) {
159880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkDisplayType::IsDisplayable(NULL /* fMaker */, type))
159980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return (SkOpType) kObject;
160080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkDisplayType::IsEnum(NULL /* fMaker */, type))
160180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return kInt;
160280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (type) {
160380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_ARGB:
160480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_MSec:
160580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_Int:
160680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kInt;
160780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_Float:
160880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_Point:
160980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_3D_Point:
161080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kScalar;
161180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_Base64:
161280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_DynamicString:
161380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_String:
161480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kString;
161580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_Array:
161680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return (SkOpType) kArray;
161780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case SkType_Unknown:
161880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kNoType;
161980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
162080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0);
162180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return kNoType;
162280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
162380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
162480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
162580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkScriptEngine::ValueToString(SkScriptValue value, SkString* string) {
162680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (value.fType) {
162780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kInt:
162880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            string->reset();
162980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            string->appendS32(value.fOperand.fS32);
163080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
163180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kScalar:
163280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            string->reset();
163380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            string->appendScalar(value.fOperand.fScalar);
163480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
163580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kString:
163680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            string->set(*value.fOperand.fString);
163780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
163880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
163980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(0);
164080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
164180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
164280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true; // no error
164380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
164480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
164580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SUPPORT_UNITTEST
164680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
164780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFloatingPoint.h"
164880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
164980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define DEF_SCALAR_ANSWER   0
165080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define DEF_STRING_ANSWER   NULL
165180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
165280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define testInt(expression) { #expression, SkType_Int, expression, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER }
165380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_SCALAR_IS_FLOAT
165480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define testScalar(expression) { #expression, SkType_Float, 0, (float) expression, DEF_STRING_ANSWER }
165580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define testRemainder(exp1, exp2) { #exp1 "%" #exp2, SkType_Float, 0, sk_float_mod(exp1, exp2), DEF_STRING_ANSWER }
165680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
165780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define testScalar(expression) { #expression, SkType_Float, 0, (int) ((expression) * 65536.0f), DEF_STRING_ANSWER }
165880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define testRemainder(exp1, exp2) { #exp1 "%" #exp2, SkType_Float, 0, (int) (sk_float_mod(exp1, exp2)  * 65536.0f), DEF_STRING_ANSWER }
165980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
166080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define testTrue(expression) { #expression, SkType_Int, 1, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER }
166180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define testFalse(expression) { #expression, SkType_Int, 0, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER }
166280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
166380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const SkScriptNAnswer scriptTests[]  = {
166480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1>1/2),
166580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt((6+7)*8),
166680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0&&1?2:3),
166780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(3*(4+5)),
166880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testScalar(1.0+2.0),
166980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testScalar(1.0+5),
167080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testScalar(3.0-1.0),
167180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testScalar(6-1.0),
167280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testScalar(- -5.5- -1.5),
167380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testScalar(2.5*6.),
167480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testScalar(0.5*4),
167580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testScalar(4.5/.5),
167680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testScalar(9.5/19),
167780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testRemainder(9.5, 0.5),
167880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testRemainder(9.,2),
167980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testRemainder(9,2.5),
168080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testRemainder(-9,2.5),
168180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(-9==-9.0),
168280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(-9.==-4.0-5),
168380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(-9.*1==-4-5),
168480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(-9!=-9.0),
168580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(-9.!=-4.0-5),
168680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(-9.*1!=-4-5),
168780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0x123),
168880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0XABC),
168980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0xdeadBEEF),
169080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {   "'123'+\"456\"", SkType_String, 0, 0, "123456" },
169180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {   "123+\"456\"", SkType_String, 0, 0, "123456" },
169280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {   "'123'+456", SkType_String, 0, 0, "123456" },
169380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {   "'123'|\"456\"", SkType_Int, 123|456, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER },
169480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {   "123|\"456\"", SkType_Int, 123|456, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER },
169580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {   "'123'|456", SkType_Int, 123|456, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER },
169680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {   "'2'<11", SkType_Int, 1, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER },
169780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {   "2<'11'", SkType_Int, 1, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER },
169880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {   "'2'<'11'", SkType_Int, 0, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER },
169980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(123),
170080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(-345),
170180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(+678),
170280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1+2+3),
170380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(3*4+5),
170480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(6+7*8),
170580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(-1-2-8/4),
170680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(-9%4),
170780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(9%-4),
170880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(-9%-4),
170980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(123|978),
171080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(123&978),
171180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(123^978),
171280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2<<4),
171380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(99>>3),
171480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(~55),
171580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(~~55),
171680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(!55),
171780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(!!55),
171880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // both int
171980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2<2),
172080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2<11),
172180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20<11),
172280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2<=2),
172380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2<=11),
172480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20<=11),
172580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2>2),
172680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2>11),
172780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20>11),
172880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2>=2),
172980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2>=11),
173080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20>=11),
173180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2==2),
173280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2==11),
173380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20==11),
173480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2!=2),
173580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2!=11),
173680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20!=11),
173780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // left int, right scalar
173880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2<2.),
173980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2<11.),
174080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20<11.),
174180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2<=2.),
174280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2<=11.),
174380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20<=11.),
174480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2>2.),
174580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2>11.),
174680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20>11.),
174780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2>=2.),
174880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2>=11.),
174980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20>=11.),
175080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2==2.),
175180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2==11.),
175280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20==11.),
175380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2!=2.),
175480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2!=11.),
175580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20!=11.),
175680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // left scalar, right int
175780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        testInt(2.<2),
175880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.<11),
175980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.<11),
176080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.<=2),
176180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.<=11),
176280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.<=11),
176380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.>2),
176480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.>11),
176580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.>11),
176680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.>=2),
176780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.>=11),
176880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.>=11),
176980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.==2),
177080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.==11),
177180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.==11),
177280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.!=2),
177380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.!=11),
177480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.!=11),
177580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // both scalar
177680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.<11.),
177780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.<11.),
177880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.<=2.),
177980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.<=11.),
178080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.<=11.),
178180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.>2.),
178280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.>11.),
178380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.>11.),
178480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.>=2.),
178580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.>=11.),
178680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.>=11.),
178780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.==2.),
178880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.==11.),
178980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.==11.),
179080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.!=2.),
179180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(2.!=11.),
179280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(20.!=11.),
179380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // int, string (string is int)
179480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2<'2'),
179580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2<'11'),
179680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(20<'11'),
179780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2<='2'),
179880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2<='11'),
179980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(20<='11'),
180080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2>'2'),
180180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2>'11'),
180280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(20>'11'),
180380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2>='2'),
180480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2>='11'),
180580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(20>='11'),
180680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2=='2'),
180780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2=='11'),
180880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2!='2'),
180980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2!='11'),
181080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // int, string (string is scalar)
181180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2<'2.'),
181280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2<'11.'),
181380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(20<'11.'),
181480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2=='2.'),
181580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2=='11.'),
181680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // scalar, string
181780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2.<'2.'),
181880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2.<'11.'),
181980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(20.<'11.'),
182080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue(2.=='2.'),
182180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse(2.=='11.'),
182280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // string, int
182380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('2'<2),
182480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue('2'<11),
182580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('20'<11),
182680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue('2'==2),
182780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('2'==11),
182880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // string, scalar
182980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('2'<2.),
183080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue('2'<11.),
183180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('20'<11.),
183280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue('2'==2.),
183380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('2'==11.),
183480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // string, string
183580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('2'<'2'),
183680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('2'<'11'),
183780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('20'<'11'),
183880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testTrue('2'=='2'),
183980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testFalse('2'=='11'),
184080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // logic
184180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1?2:3),
184280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0?2:3),
184380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1&&2||3),
184480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1&&0||3),
184580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1&&0||0),
184680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1||0&&3),
184780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0||0&&3),
184880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0||1&&3),
184980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1?(2?3:4):5),
185080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0?(2?3:4):5),
185180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1?(0?3:4):5),
185280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0?(0?3:4):5),
185380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1?2?3:4:5),
185480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0?2?3:4:5),
185580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1?0?3:4:5),
185680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0?0?3:4:5),
185780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
185880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1?2:(3?4:5)),
185980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0?2:(3?4:5)),
186080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1?0:(3?4:5)),
186180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0?0:(3?4:5)),
186280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1?2:3?4:5),
186380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0?2:3?4:5),
186480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(1?0:3?4:5),
186580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    testInt(0?0:3?4:5)
186680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , { "123.5", SkType_Float, 0, SkIntToScalar(123) + SK_Scalar1/2, DEF_STRING_ANSWER }
186780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
186880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
186980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkScriptNAnswer_testCount   SK_ARRAY_COUNT(scriptTests)
187080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
187180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkScriptEngine::UnitTest() {
187280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (unsigned index = 0; index < SkScriptNAnswer_testCount; index++) {
187380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScriptEngine engine(SkScriptEngine::ToOpType(scriptTests[index].fType));
187480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScriptValue value;
187580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const char* script = scriptTests[index].fScript;
187680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(engine.evaluateScript(&script, &value) == true);
187780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(value.fType == scriptTests[index].fType);
187880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar error;
187980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        switch (value.fType) {
188080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkType_Int:
188180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(value.fOperand.fS32 == scriptTests[index].fIntAnswer);
188280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
188380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkType_Float:
188480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                error = SkScalarAbs(value.fOperand.fScalar - scriptTests[index].fScalarAnswer);
188580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(error < SK_Scalar1 / 10000);
188680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
188780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case SkType_String:
188880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(strcmp(value.fOperand.fString->c_str(), scriptTests[index].fStringAnswer) == 0);
188980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
189080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            default:
189180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(0);
189280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
189380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
189480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
189580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
1896