summaryrefslogtreecommitdiff
path: root/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp')
-rw-r--r--xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp854
1 files changed, 854 insertions, 0 deletions
diff --git a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp
new file mode 100644
index 0000000000..3b4dc7017d
--- /dev/null
+++ b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp
@@ -0,0 +1,854 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h"
+
+#include <utility>
+
+#include "core/fxcrt/fx_extension.h"
+
+namespace {
+
+const wchar_t* const gs_lpStrExpFuncName[] = {
+ L"foxit_xfa_formcalc_runtime.assign_value_operator",
+ L"foxit_xfa_formcalc_runtime.logical_or_operator",
+ L"foxit_xfa_formcalc_runtime.logical_and_operator",
+ L"foxit_xfa_formcalc_runtime.equality_operator",
+ L"foxit_xfa_formcalc_runtime.notequality_operator",
+ L"foxit_xfa_formcalc_runtime.less_operator",
+ L"foxit_xfa_formcalc_runtime.lessequal_operator",
+ L"foxit_xfa_formcalc_runtime.greater_operator",
+ L"foxit_xfa_formcalc_runtime.greaterequal_operator",
+ L"foxit_xfa_formcalc_runtime.plus_operator",
+ L"foxit_xfa_formcalc_runtime.minus_operator",
+ L"foxit_xfa_formcalc_runtime.multiple_operator",
+ L"foxit_xfa_formcalc_runtime.divide_operator",
+ L"foxit_xfa_formcalc_runtime.positive_operator",
+ L"foxit_xfa_formcalc_runtime.negative_operator",
+ L"foxit_xfa_formcalc_runtime.logical_not_operator",
+ L"foxit_xfa_formcalc_runtime.",
+ L"foxit_xfa_formcalc_runtime.dot_accessor",
+ L"foxit_xfa_formcalc_runtime.dotdot_accessor",
+ L"foxit_xfa_formcalc_runtime.concat_fm_object",
+ L"foxit_xfa_formcalc_runtime.is_fm_object",
+ L"foxit_xfa_formcalc_runtime.is_fm_array",
+ L"foxit_xfa_formcalc_runtime.get_fm_value",
+ L"foxit_xfa_formcalc_runtime.get_fm_jsobj",
+ L"foxit_xfa_formcalc_runtime.fm_var_filter",
+};
+
+struct XFA_FMBuildInFunc {
+ uint32_t m_uHash;
+ const wchar_t* m_buildinfunc;
+};
+
+const XFA_FMBuildInFunc g_BuildInFuncs[] = {
+ {0x0001f1f5, L"At"}, {0x00020b9c, L"FV"},
+ {0x00021aef, L"If"}, {0x00023ee6, L"PV"},
+ {0x04b5c9ee, L"Encode"}, {0x08e96685, L"DateFmt"},
+ {0x09f99db6, L"Abs"}, {0x09f9e583, L"Apr"},
+ {0x09fa043e, L"Avg"}, {0x0a9782a0, L"Get"},
+ {0x0b1b09df, L"Len"}, {0x0b3543a6, L"Max"},
+ {0x0b356ca4, L"Min"}, {0x0b358b60, L"Mod"},
+ {0x0b4fded4, L"NPV"}, {0x0b846bf1, L"Pmt"},
+ {0x0b8494f9, L"Put"}, {0x0bb8df5d, L"Ref"},
+ {0x0bd37a99, L"Str"}, {0x0bd37fb5, L"Sum"},
+ {0x1048469b, L"Cterm"}, {0x11e03660, L"Exists"},
+ {0x126236e6, L"Post"}, {0x127c6661, L"PPmt"},
+ {0x193ade3e, L"Right"}, {0x1ec8ab2c, L"Rate"},
+ {0x20e476dc, L"IsoTime2Num"}, {0x23eb6816, L"TimeFmt"},
+ {0x24fb17b0, L"LocalDateFmt"}, {0x28dee6e9, L"Format"},
+ {0x2d0890b8, L"Term"}, {0x2d71b00f, L"Time"},
+ {0x2f890fb1, L"Num2Time"}, {0x3767511d, L"Ceil"},
+ {0x3ffd1941, L"LocalTimeFmt"}, {0x442f68c8, L"Round"},
+ {0x46fd1128, L"Eval"}, {0x4d629440, L"Date2Num"},
+ {0x4dcf25f8, L"Concat"}, {0x4e00255d, L"UnitValue"},
+ {0x55a5cc29, L"Lower"}, {0x5e43e04c, L"WordNum"},
+ {0x620ce6ba, L"Ipmt"}, {0x6f544d49, L"Count"},
+ {0x7e241013, L"Within"}, {0x9b9a6e2b, L"IsoDate2Num"},
+ {0xb2c941c2, L"UnitType"}, {0xb598a1f7, L"Uuid"},
+ {0xbde9abde, L"Date"}, {0xc0010b80, L"Num2Date"},
+ {0xc1f6144c, L"Upper"}, {0xc44028f7, L"Oneof"},
+ {0xc62c1b2c, L"Space"}, {0xd0ff50f9, L"HasValue"},
+ {0xd1537042, L"Floor"}, {0xd2ac9cf1, L"Time2Num"},
+ {0xd907aee5, L"Num2GMTime"}, {0xdf24f7c4, L"Decode"},
+ {0xe2664803, L"Substr"}, {0xe3e7b528, L"Stuff"},
+ {0xe6792d4e, L"Rtrim"}, {0xe8c23f5b, L"Parse"},
+ {0xea18d121, L"Choose"}, {0xebfef69c, L"Replace"},
+ {0xf5ad782b, L"Left"}, {0xf7bb2248, L"Ltrim"},
+};
+
+struct XFA_FMSOMMethod {
+ uint32_t m_uHash;
+ const wchar_t* m_wsSomMethodName;
+ uint32_t m_dParameters;
+};
+const XFA_FMSOMMethod gs_FMSomMethods[] = {
+ {0x00000068, L"h", 0x01},
+ {0x00000077, L"w", 0x01},
+ {0x00000078, L"x", 0x01},
+ {0x00000079, L"y", 0x01},
+ {0x05eb5b0f, L"pageSpan", 0x01},
+ {0x10f1b1bd, L"page", 0x01},
+ {0x3bf1c2a5, L"absPageSpan", 0x01},
+ {0x3c752495, L"verify", 0x0d},
+ {0x44c352ad, L"formNodes", 0x01},
+ {0x5775c2cc, L"absPageInBatch", 0x01},
+ {0x5ee00996, L"setElement", 0x01},
+ {0x7033bfd5, L"insert", 0x03},
+ {0x8c5feb32, L"sheetInBatch", 0x01},
+ {0x8f3a8379, L"sheet", 0x01},
+ {0x92dada4f, L"saveFilteredXML", 0x01},
+ {0x9cab7cae, L"remove", 0x01},
+ {0xa68635f1, L"sign", 0x61},
+ {0xaac241c8, L"isRecordGroup", 0x01},
+ {0xd8ed1467, L"clear", 0x01},
+ {0xda12e518, L"append", 0x01},
+ {0xe74f0653, L"absPage", 0x01},
+};
+
+} // namespace
+
+CFX_WideStringC XFA_FM_EXPTypeToString(
+ XFA_FM_SimpleExpressionType simpleExpType) {
+ return gs_lpStrExpFuncName[simpleExpType];
+}
+
+CXFA_FMSimpleExpression::CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op)
+ : m_line(line), m_op(op) {}
+
+bool CXFA_FMSimpleExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ return true;
+}
+
+bool CXFA_FMSimpleExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
+ return true;
+}
+
+XFA_FM_TOKEN CXFA_FMSimpleExpression::GetOperatorToken() const {
+ return m_op;
+}
+
+CXFA_FMNullExpression::CXFA_FMNullExpression(uint32_t line)
+ : CXFA_FMSimpleExpression(line, TOKnull) {}
+
+bool CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << L"null";
+ return true;
+}
+
+CXFA_FMNumberExpression::CXFA_FMNumberExpression(uint32_t line,
+ CFX_WideStringC wsNumber)
+ : CXFA_FMSimpleExpression(line, TOKnumber), m_wsNumber(wsNumber) {}
+
+CXFA_FMNumberExpression::~CXFA_FMNumberExpression() {}
+
+bool CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << m_wsNumber;
+ return true;
+}
+
+CXFA_FMStringExpression::CXFA_FMStringExpression(uint32_t line,
+ CFX_WideStringC wsString)
+ : CXFA_FMSimpleExpression(line, TOKstring), m_wsString(wsString) {}
+
+CXFA_FMStringExpression::~CXFA_FMStringExpression() {}
+
+bool CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ CFX_WideString tempStr(m_wsString);
+ if (tempStr.GetLength() <= 2) {
+ javascript << tempStr;
+ return true;
+ }
+ javascript.AppendChar(L'\"');
+ for (int32_t i = 1; i < tempStr.GetLength() - 1; i++) {
+ wchar_t oneChar = tempStr[i];
+ switch (oneChar) {
+ case L'\"':
+ i++;
+ javascript << L"\\\"";
+ break;
+ case 0x0d:
+ break;
+ case 0x0a:
+ javascript << L"\\n";
+ break;
+ default:
+ javascript.AppendChar(oneChar);
+ break;
+ }
+ }
+ javascript.AppendChar(L'\"');
+ return true;
+}
+
+CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression(
+ uint32_t line,
+ CFX_WideStringC wsIdentifier)
+ : CXFA_FMSimpleExpression(line, TOKidentifier),
+ m_wsIdentifier(wsIdentifier) {}
+
+CXFA_FMIdentifierExpression::~CXFA_FMIdentifierExpression() {}
+
+bool CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ CFX_WideString tempStr(m_wsIdentifier);
+ if (tempStr == L"$") {
+ tempStr = L"this";
+ } else if (tempStr == L"!") {
+ tempStr = L"xfa.datasets";
+ } else if (tempStr == L"$data") {
+ tempStr = L"xfa.datasets.data";
+ } else if (tempStr == L"$event") {
+ tempStr = L"xfa.event";
+ } else if (tempStr == L"$form") {
+ tempStr = L"xfa.form";
+ } else if (tempStr == L"$host") {
+ tempStr = L"xfa.host";
+ } else if (tempStr == L"$layout") {
+ tempStr = L"xfa.layout";
+ } else if (tempStr == L"$template") {
+ tempStr = L"xfa.template";
+ } else if (tempStr[0] == L'!') {
+ tempStr = EXCLAMATION_IN_IDENTIFIER + tempStr.Mid(1);
+ }
+ javascript << tempStr;
+ return true;
+}
+
+CXFA_FMUnaryExpression::CXFA_FMUnaryExpression(
+ uint32_t line,
+ XFA_FM_TOKEN op,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp)
+ : CXFA_FMSimpleExpression(line, op), m_pExp(std::move(pExp)) {}
+
+CXFA_FMUnaryExpression::~CXFA_FMUnaryExpression() {}
+
+bool CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ return true;
+}
+
+CXFA_FMBinExpression::CXFA_FMBinExpression(
+ uint32_t line,
+ XFA_FM_TOKEN op,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
+ : CXFA_FMSimpleExpression(line, op),
+ m_pExp1(std::move(pExp1)),
+ m_pExp2(std::move(pExp2)) {}
+
+CXFA_FMBinExpression::~CXFA_FMBinExpression() {}
+
+bool CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ return true;
+}
+
+CXFA_FMAssignExpression::CXFA_FMAssignExpression(
+ uint32_t line,
+ XFA_FM_TOKEN op,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
+ : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
+
+bool CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << L"if (";
+ javascript << gs_lpStrExpFuncName[ISFMOBJECT];
+ javascript << L"(";
+ CFX_WideTextBuf tempExp1;
+ if (!m_pExp1->ToJavaScript(tempExp1))
+ return false;
+ javascript << tempExp1;
+ javascript << L"))\n{\n";
+ javascript << gs_lpStrExpFuncName[ASSIGN];
+ javascript << L"(";
+ javascript << tempExp1;
+ javascript << L", ";
+ if (CFXA_IsTooBig(javascript))
+ return false;
+
+ CFX_WideTextBuf tempExp2;
+ if (!m_pExp2->ToJavaScript(tempExp2))
+ return false;
+ javascript << tempExp2;
+ javascript << L");\n}\n";
+ if (m_pExp1->GetOperatorToken() == TOKidentifier &&
+ tempExp1.AsStringC() != L"this") {
+ javascript << L"else\n{\n";
+ javascript << tempExp1;
+ javascript << L" = ";
+ javascript << gs_lpStrExpFuncName[ASSIGN];
+ javascript << L"(";
+ javascript << tempExp1;
+ javascript << L", ";
+ javascript << tempExp2;
+ javascript << L");\n}\n";
+ }
+ return !CFXA_IsTooBig(javascript);
+}
+
+bool CXFA_FMAssignExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
+ javascript << L"if (";
+ javascript << gs_lpStrExpFuncName[ISFMOBJECT];
+ javascript << L"(";
+ CFX_WideTextBuf tempExp1;
+ if (!m_pExp1->ToJavaScript(tempExp1))
+ return false;
+ javascript << tempExp1;
+ javascript << L"))\n{\n";
+ javascript << RUNTIMEFUNCTIONRETURNVALUE;
+ javascript << L" = ";
+ javascript << gs_lpStrExpFuncName[ASSIGN];
+ javascript << L"(";
+ javascript << tempExp1;
+ javascript << L", ";
+ if (CFXA_IsTooBig(javascript))
+ return false;
+
+ CFX_WideTextBuf tempExp2;
+ if (!m_pExp2->ToJavaScript(tempExp2))
+ return false;
+ javascript << tempExp2;
+ javascript << L");\n}\n";
+ if (m_pExp1->GetOperatorToken() == TOKidentifier &&
+ tempExp1.AsStringC() != L"this") {
+ javascript << L"else\n{\n";
+ javascript << RUNTIMEFUNCTIONRETURNVALUE;
+ javascript << L" = ";
+ javascript << tempExp1;
+ javascript << L" = ";
+ javascript << gs_lpStrExpFuncName[ASSIGN];
+ javascript << L"(";
+ javascript << tempExp1;
+ javascript << L", ";
+ javascript << tempExp2;
+ javascript << L");\n}\n";
+ }
+ return !CFXA_IsTooBig(javascript);
+}
+
+CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression(
+ uint32_t line,
+ XFA_FM_TOKEN op,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
+ : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
+
+bool CXFA_FMLogicalOrExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << gs_lpStrExpFuncName[LOGICALOR];
+ javascript << L"(";
+ if (!m_pExp1->ToJavaScript(javascript))
+ return false;
+ javascript << L", ";
+ if (!m_pExp2->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return !CFXA_IsTooBig(javascript);
+}
+
+CXFA_FMLogicalAndExpression::CXFA_FMLogicalAndExpression(
+ uint32_t line,
+ XFA_FM_TOKEN op,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
+ : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
+
+bool CXFA_FMLogicalAndExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << gs_lpStrExpFuncName[LOGICALAND];
+ javascript << L"(";
+ if (!m_pExp1->ToJavaScript(javascript))
+ return false;
+ javascript << L", ";
+ if (!m_pExp2->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return !CFXA_IsTooBig(javascript);
+}
+
+CXFA_FMEqualityExpression::CXFA_FMEqualityExpression(
+ uint32_t line,
+ XFA_FM_TOKEN op,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
+ : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
+
+bool CXFA_FMEqualityExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ switch (m_op) {
+ case TOKeq:
+ case TOKkseq:
+ javascript << gs_lpStrExpFuncName[EQUALITY];
+ break;
+ case TOKne:
+ case TOKksne:
+ javascript << gs_lpStrExpFuncName[NOTEQUALITY];
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+ javascript << L"(";
+ if (!m_pExp1->ToJavaScript(javascript))
+ return false;
+ javascript << L", ";
+ if (!m_pExp2->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return !CFXA_IsTooBig(javascript);
+}
+
+CXFA_FMRelationalExpression::CXFA_FMRelationalExpression(
+ uint32_t line,
+ XFA_FM_TOKEN op,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
+ : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
+
+bool CXFA_FMRelationalExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ switch (m_op) {
+ case TOKlt:
+ case TOKkslt:
+ javascript << gs_lpStrExpFuncName[LESS];
+ break;
+ case TOKgt:
+ case TOKksgt:
+ javascript << gs_lpStrExpFuncName[GREATER];
+ break;
+ case TOKle:
+ case TOKksle:
+ javascript << gs_lpStrExpFuncName[LESSEQUAL];
+ break;
+ case TOKge:
+ case TOKksge:
+ javascript << gs_lpStrExpFuncName[GREATEREQUAL];
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+ javascript << L"(";
+ if (!m_pExp1->ToJavaScript(javascript))
+ return false;
+ javascript << L", ";
+ if (!m_pExp2->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return !CFXA_IsTooBig(javascript);
+}
+
+CXFA_FMAdditiveExpression::CXFA_FMAdditiveExpression(
+ uint32_t line,
+ XFA_FM_TOKEN op,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
+ : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
+
+bool CXFA_FMAdditiveExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ switch (m_op) {
+ case TOKplus:
+ javascript << gs_lpStrExpFuncName[PLUS];
+ break;
+ case TOKminus:
+ javascript << gs_lpStrExpFuncName[MINUS];
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+ javascript << L"(";
+ if (!m_pExp1->ToJavaScript(javascript))
+ return false;
+ javascript << L", ";
+ if (!m_pExp2->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return !CFXA_IsTooBig(javascript);
+}
+
+CXFA_FMMultiplicativeExpression::CXFA_FMMultiplicativeExpression(
+ uint32_t line,
+ XFA_FM_TOKEN op,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
+ : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
+
+bool CXFA_FMMultiplicativeExpression::ToJavaScript(
+ CFX_WideTextBuf& javascript) {
+ switch (m_op) {
+ case TOKmul:
+ javascript << gs_lpStrExpFuncName[MULTIPLE];
+ break;
+ case TOKdiv:
+ javascript << gs_lpStrExpFuncName[DIVIDE];
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+ javascript << L"(";
+ if (!m_pExp1->ToJavaScript(javascript))
+ return false;
+ javascript << L", ";
+ if (!m_pExp2->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return !CFXA_IsTooBig(javascript);
+}
+
+CXFA_FMPosExpression::CXFA_FMPosExpression(
+ uint32_t line,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp)
+ : CXFA_FMUnaryExpression(line, TOKplus, std::move(pExp)) {}
+
+bool CXFA_FMPosExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << gs_lpStrExpFuncName[POSITIVE];
+ javascript << L"(";
+ if (!m_pExp->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return true;
+}
+
+CXFA_FMNegExpression::CXFA_FMNegExpression(
+ uint32_t line,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp)
+ : CXFA_FMUnaryExpression(line, TOKminus, std::move(pExp)) {}
+
+bool CXFA_FMNegExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << gs_lpStrExpFuncName[NEGATIVE];
+ javascript << L"(";
+ if (!m_pExp->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return true;
+}
+
+CXFA_FMNotExpression::CXFA_FMNotExpression(
+ uint32_t line,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp)
+ : CXFA_FMUnaryExpression(line, TOKksnot, std::move(pExp)) {}
+
+bool CXFA_FMNotExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << gs_lpStrExpFuncName[NOT];
+ javascript << L"(";
+ if (!m_pExp->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return true;
+}
+
+CXFA_FMCallExpression::CXFA_FMCallExpression(
+ uint32_t line,
+ std::unique_ptr<CXFA_FMSimpleExpression> pExp,
+ std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments,
+ bool bIsSomMethod)
+ : CXFA_FMUnaryExpression(line, TOKcall, std::move(pExp)),
+ m_bIsSomMethod(bIsSomMethod),
+ m_Arguments(std::move(pArguments)) {}
+
+CXFA_FMCallExpression::~CXFA_FMCallExpression() {}
+
+bool CXFA_FMCallExpression::IsBuildInFunc(CFX_WideTextBuf* funcName) {
+ uint32_t uHash = FX_HashCode_GetW(funcName->AsStringC(), true);
+ const XFA_FMBuildInFunc* pEnd = g_BuildInFuncs + FX_ArraySize(g_BuildInFuncs);
+ const XFA_FMBuildInFunc* pFunc =
+ std::lower_bound(g_BuildInFuncs, pEnd, uHash,
+ [](const XFA_FMBuildInFunc& func, uint32_t hash) {
+ return func.m_uHash < hash;
+ });
+ if (pFunc < pEnd && uHash == pFunc->m_uHash) {
+ funcName->Clear();
+ *funcName << pFunc->m_buildinfunc;
+ return true;
+ }
+ return false;
+}
+
+uint32_t CXFA_FMCallExpression::IsMethodWithObjParam(
+ const CFX_WideStringC& methodName) {
+ uint32_t uHash = FX_HashCode_GetW(methodName, false);
+ XFA_FMSOMMethod somMethodWithObjPara;
+ uint32_t parameters = 0x00;
+ int32_t iStart = 0,
+ iEnd = (sizeof(gs_FMSomMethods) / sizeof(gs_FMSomMethods[0])) - 1;
+ int32_t iMid = (iStart + iEnd) / 2;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ somMethodWithObjPara = gs_FMSomMethods[iMid];
+ if (uHash == somMethodWithObjPara.m_uHash) {
+ parameters = somMethodWithObjPara.m_dParameters;
+ break;
+ } else if (uHash < somMethodWithObjPara.m_uHash) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return parameters;
+}
+
+bool CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ CFX_WideTextBuf funcName;
+ if (!m_pExp->ToJavaScript(funcName))
+ return false;
+ if (m_bIsSomMethod) {
+ javascript << funcName;
+ javascript << L"(";
+ uint32_t methodPara = IsMethodWithObjParam(funcName.AsStringC());
+ if (methodPara > 0) {
+ for (size_t i = 0; i < m_Arguments.size(); ++i) {
+ // Currently none of our expressions use objects for a parameter over
+ // the 6th. Make sure we don't overflow the shift when doing this
+ // check. If we ever need more the 32 object params we can revisit.
+ if (i < 32 && (methodPara & (0x01 << i)) > 0) {
+ javascript << gs_lpStrExpFuncName[GETFMJSOBJ];
+ } else {
+ javascript << gs_lpStrExpFuncName[GETFMVALUE];
+ }
+ javascript << L"(";
+ const auto& expr = m_Arguments[i];
+ if (!expr->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ if (i + 1 < m_Arguments.size()) {
+ javascript << L", ";
+ }
+ if (CFXA_IsTooBig(javascript))
+ return false;
+ }
+ } else {
+ for (const auto& expr : m_Arguments) {
+ javascript << gs_lpStrExpFuncName[GETFMVALUE];
+ javascript << L"(";
+ if (!expr->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ if (expr != m_Arguments.back())
+ javascript << L", ";
+ if (CFXA_IsTooBig(javascript))
+ return false;
+ }
+ }
+ javascript << L")";
+ } else {
+ bool isEvalFunc = false;
+ bool isExistsFunc = false;
+ if (IsBuildInFunc(&funcName)) {
+ if (funcName.AsStringC() == L"Eval") {
+ isEvalFunc = true;
+ javascript << L"eval.call(this, ";
+ javascript << gs_lpStrExpFuncName[CALL];
+ javascript << L"Translate";
+ } else if (funcName.AsStringC() == L"Exists") {
+ isExistsFunc = true;
+ javascript << gs_lpStrExpFuncName[CALL];
+ javascript << funcName;
+ } else {
+ javascript << gs_lpStrExpFuncName[CALL];
+ javascript << funcName;
+ }
+ } else {
+ javascript << funcName;
+ }
+ javascript << L"(";
+ if (isExistsFunc) {
+ javascript << L"\n(\nfunction ()\n{\ntry\n{\n";
+ if (!m_Arguments.empty()) {
+ const auto& expr = m_Arguments[0];
+ javascript << L"return ";
+ if (!expr->ToJavaScript(javascript))
+ return false;
+ javascript << L";\n}\n";
+ } else {
+ javascript << L"return 0;\n}\n";
+ }
+ javascript << L"catch(accessExceptions)\n";
+ javascript << L"{\nreturn 0;\n}\n}\n).call(this)\n";
+ } else {
+ for (const auto& expr : m_Arguments) {
+ if (!expr->ToJavaScript(javascript))
+ return false;
+ if (expr != m_Arguments.back())
+ javascript << L", ";
+ if (CFXA_IsTooBig(javascript))
+ return false;
+ }
+ }
+ javascript << L")";
+ if (isEvalFunc) {
+ javascript << L")";
+ }
+ }
+ return true;
+}
+
+CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression(
+ uint32_t line,
+ std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
+ XFA_FM_TOKEN op,
+ CFX_WideStringC wsIdentifier,
+ std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)
+ : CXFA_FMBinExpression(line,
+ op,
+ std::move(pAccessor),
+ std::move(pIndexExp)),
+ m_wsIdentifier(wsIdentifier) {}
+
+CXFA_FMDotAccessorExpression::~CXFA_FMDotAccessorExpression() {}
+
+bool CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << gs_lpStrExpFuncName[DOT];
+ javascript << L"(";
+ CFX_WideTextBuf tempExp1;
+ if (m_pExp1) {
+ if (!m_pExp1->ToJavaScript(tempExp1))
+ return false;
+ javascript << tempExp1;
+ } else {
+ javascript << L"null";
+ }
+ javascript << L", ";
+ javascript << L"\"";
+ if (CFXA_IsTooBig(javascript))
+ return false;
+
+ if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier)
+ javascript << tempExp1;
+ javascript << L"\", ";
+ if (m_op == TOKdotscream) {
+ javascript << L"\"#";
+ javascript << m_wsIdentifier;
+ javascript << L"\", ";
+ } else if (m_op == TOKdotstar) {
+ javascript << L"\"*\", ";
+ } else if (m_op == TOKcall) {
+ javascript << L"\"\", ";
+ } else {
+ javascript << L"\"";
+ javascript << m_wsIdentifier;
+ javascript << L"\", ";
+ }
+ if (!m_pExp2->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return !CFXA_IsTooBig(javascript);
+}
+
+CXFA_FMIndexExpression::CXFA_FMIndexExpression(
+ uint32_t line,
+ XFA_FM_AccessorIndex accessorIndex,
+ std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp,
+ bool bIsStarIndex)
+ : CXFA_FMUnaryExpression(line, TOKlbracket, std::move(pIndexExp)),
+ m_accessorIndex(accessorIndex),
+ m_bIsStarIndex(bIsStarIndex) {}
+
+bool CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ switch (m_accessorIndex) {
+ case ACCESSOR_NO_INDEX:
+ javascript << L"0";
+ break;
+ case ACCESSOR_NO_RELATIVEINDEX:
+ javascript << L"1";
+ break;
+ case ACCESSOR_POSITIVE_INDEX:
+ javascript << L"2";
+ break;
+ case ACCESSOR_NEGATIVE_INDEX:
+ javascript << L"3";
+ break;
+ default:
+ javascript << L"0";
+ }
+ if (!m_bIsStarIndex) {
+ javascript << L", ";
+ if (m_pExp) {
+ if (!m_pExp->ToJavaScript(javascript))
+ return false;
+ } else {
+ javascript << L"0";
+ }
+ }
+ return true;
+}
+
+CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression(
+ uint32_t line,
+ std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
+ XFA_FM_TOKEN op,
+ CFX_WideStringC wsIdentifier,
+ std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)
+ : CXFA_FMBinExpression(line,
+ op,
+ std::move(pAccessor),
+ std::move(pIndexExp)),
+ m_wsIdentifier(wsIdentifier) {}
+
+CXFA_FMDotDotAccessorExpression::~CXFA_FMDotDotAccessorExpression() {}
+
+bool CXFA_FMDotDotAccessorExpression::ToJavaScript(
+ CFX_WideTextBuf& javascript) {
+ javascript << gs_lpStrExpFuncName[DOTDOT];
+ javascript << L"(";
+ CFX_WideTextBuf tempExp1;
+ if (!m_pExp1->ToJavaScript(tempExp1))
+ return false;
+ javascript << tempExp1;
+ javascript << L", ";
+ javascript << L"\"";
+ if (CFXA_IsTooBig(javascript))
+ return false;
+
+ if (m_pExp1->GetOperatorToken() == TOKidentifier)
+ javascript << tempExp1;
+ javascript << L"\", ";
+ javascript << L"\"";
+ javascript << m_wsIdentifier;
+ javascript << L"\", ";
+ if (!m_pExp2->ToJavaScript(javascript))
+ return false;
+ javascript << L")";
+ return !CFXA_IsTooBig(javascript);
+}
+
+CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression(
+ uint32_t line,
+ std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1,
+ std::unique_ptr<CXFA_FMSimpleExpression> pCallExp)
+ : CXFA_FMBinExpression(line,
+ TOKdot,
+ std::move(pAccessorExp1),
+ std::move(pCallExp)) {}
+
+bool CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
+ javascript << L"(\nfunction ()\n{\n";
+ javascript << L"var method_return_value = null;\n";
+ javascript << L"var accessor_object = ";
+ if (!m_pExp1->ToJavaScript(javascript))
+ return false;
+ javascript << L";\n";
+ javascript << L"if (";
+ javascript << gs_lpStrExpFuncName[ISFMARRAY];
+ javascript << L"(accessor_object))\n{\n";
+ javascript << L"for(var index = accessor_object.length - 1; index > 1; "
+ L"index--)\n{\n";
+ javascript << L"method_return_value = accessor_object[index].";
+ if (CFXA_IsTooBig(javascript))
+ return false;
+
+ CFX_WideTextBuf tempExp2;
+ if (!m_pExp2->ToJavaScript(tempExp2))
+ return false;
+ javascript << tempExp2;
+ javascript << L";\n}\n}\n";
+ javascript << L"else\n{\nmethod_return_value = accessor_object.";
+ javascript << tempExp2;
+ javascript << L";\n}\n";
+ javascript << L"return method_return_value;\n";
+ javascript << L"}\n).call(this)";
+ return !CFXA_IsTooBig(javascript);
+}
+
+bool CFXA_IsTooBig(const CFX_WideTextBuf& javascript) {
+ return javascript.GetSize() > 256 * 1024 * 1024;
+}