From c1ed8bb33219a3c2f6b35e37f56febc022698121 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Fri, 20 Dec 2013 19:57:28 -0500 Subject: Add internal cell function __DEBUG_VAR to sniff arbitrary internal state. Useful for debugging in a more flashy way. But never ever document this for end users. If you are an end user reading this, use this at your own risk. You have been warned. --- formula/source/core/api/FormulaCompiler.cxx | 4 ++- include/formula/compiler.hrc | 5 +-- include/formula/opcode.hxx | 1 + sc/source/core/inc/interpre.hxx | 1 + sc/source/core/tool/compiler.cxx | 10 +++++- sc/source/core/tool/interpr4.cxx | 1 + sc/source/core/tool/interpr7.cxx | 49 +++++++++++++++++++++++++++++ 7 files changed, 67 insertions(+), 4 deletions(-) diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx index e8c40aa376f2..1051b7367593 100644 --- a/formula/source/core/api/FormulaCompiler.cxx +++ b/formula/source/core/api/FormulaCompiler.cxx @@ -39,7 +39,7 @@ namespace formula { using namespace ::com::sun::star; - static const sal_Char* pInternal[ 1 ] = { "TTT" }; + static const sal_Char* pInternal[2] = { "TTT", "__DEBUG_VAR" }; namespace { @@ -794,6 +794,8 @@ bool FormulaCompiler::IsOpCodeVolatile( OpCode eOp ) case ocIndirectXL: // ocOffset results in indirect references. case ocOffset: + // ocDebugVar shows internal value that may change as the internal state changes. + case ocDebugVar: bRet = true; break; default: diff --git a/include/formula/compiler.hrc b/include/formula/compiler.hrc index 9bda945bae51..e11f82594729 100644 --- a/include/formula/compiler.hrc +++ b/include/formula/compiler.hrc @@ -442,10 +442,11 @@ /*** Internal ***/ #define SC_OPCODE_INTERNAL_BEGIN 9999 #define SC_OPCODE_TTT 9999 -#define SC_OPCODE_INTERNAL_END 9999 +#define SC_OPCODE_DEBUG_VAR 10000 +#define SC_OPCODE_INTERNAL_END 10000 /*** from here on ExtraData contained ***/ -#define SC_OPCODE_DATA_TOKEN_1 10000 +#define SC_OPCODE_DATA_TOKEN_1 10001 #define SC_OPCODE_NONE 0xFFFF diff --git a/include/formula/opcode.hxx b/include/formula/opcode.hxx index 58f3d4188ba5..c86b3a396123 100644 --- a/include/formula/opcode.hxx +++ b/include/formula/opcode.hxx @@ -432,6 +432,7 @@ enum OpCodeEnum // internal stuff ocInternalBegin = SC_OPCODE_INTERNAL_BEGIN, ocTTT = SC_OPCODE_TTT, + ocDebugVar = SC_OPCODE_DEBUG_VAR, ocInternalEnd = SC_OPCODE_INTERNAL_END, // from here on ExtraData ocDataToken1 = SC_OPCODE_DATA_TOKEN_1, diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index f8fc0e9e1b45..cc675808a50e 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -563,6 +563,7 @@ void ScBitXor(); void ScBitRshift(); void ScBitLshift(); void ScTTT(); +void ScDebugVar(); /** Obtain the date serial number for a given date. @param bStrict diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 496c151f3fcf..dcb676e4a001 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -89,7 +90,7 @@ enum ScanState ssStop }; -static const sal_Char* pInternal[ 1 ] = { "TTT" }; +static const sal_Char* pInternal[2] = { "TTT", "__DEBUG_VAR" }; using namespace ::com::sun::star::i18n; @@ -3441,6 +3442,13 @@ bool ScCompiler::NextNewToken( bool bInArray ) if ( cSymbol[0] < 128 ) { bMayBeFuncName = rtl::isAsciiAlpha( cSymbol[0] ); + if (!bMayBeFuncName) + { + SvtMiscOptions aOpt; + if (aOpt.IsExperimentalMode()) + bMayBeFuncName = (cSymbol[0] == '_' && cSymbol[1] == '_'); + } + bAsciiNonAlnum = !bMayBeFuncName && !rtl::isAsciiDigit( cSymbol[0] ); } else diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 6983d3e8ac14..c5ebbd3009c2 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -4219,6 +4219,7 @@ StackVar ScInterpreter::Interpret() case ocBitRshift : ScBitRshift(); break; case ocBitLshift : ScBitLshift(); break; case ocTTT : ScTTT(); break; + case ocDebugVar : ScDebugVar(); break; case ocNone : nFuncFmtType = NUMBERFORMAT_UNDEFINED; break; default : PushError( errUnknownOpCode); break; } diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx index bb647c1eb698..aa07090cdd41 100644 --- a/sc/source/core/tool/interpr7.cxx +++ b/sc/source/core/tool/interpr7.cxx @@ -9,12 +9,16 @@ #include "interpre.hxx" #include +#include +#include #include #include #include #include "libxml/xpath.h" +#include +#include #include #include @@ -205,4 +209,49 @@ void ScInterpreter::ScWebservice() } } +void ScInterpreter::ScDebugVar() +{ + // This is to be used by developers only! Never document this for end + // users. This is a convenient way to extract arbitrary internal state to + // a cell for easier debugging. + + SvtMiscOptions aMiscOptions; + if (!aMiscOptions.IsExperimentalMode()) + { + PushError(ScErrorCodes::errNoName); + return; + } + + if (!MustHaveParamCount(GetByte(), 1)) + { + PushIllegalParameter(); + return; + } + + rtl_uString* p = GetString().getDataIgnoreCase(); + if (!p) + { + PushIllegalParameter(); + return; + } + + OUString aStrUpper(p); + + if (aStrUpper == "PIVOTCOUNT") + { + // Set the number of pivot tables in the document. + + double fVal = 0.0; + if (pDok->HasPivotTable()) + { + const ScDPCollection* pDPs = pDok->GetDPCollection(); + fVal = pDPs->GetCount(); + } + PushDouble(fVal); + return; + } + + PushIllegalParameter(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.1