Resolves: tdf#115879 treat NOT as the 1-parameter function that it is

... instead of a low precedence unary operator with an odd
behaviour. This wasn't documented nor specified but maybe needed
for old(est) binary file format compatibility. Generate an error
for anything else than a context of a function with one argument.

There might be some corner cases of documents where some old usage
leads to error now, of which some may have worked by accident, but
some not as intended.

Related, the internal not exposed (but available) NEG was classified
similar as a unary operator but corectly handled as function at all
places. Classified as an ordinary 1-parameter function as well.

Change-Id: I3d84a6382243c8d64313e37346f81c857e71be95
Reviewed-on: https://gerrit.libreoffice.org/50055
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Eike Rathke <erack@redhat.com>
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 1866fa5..a83cc12 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -525,16 +525,7 @@ uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::create
            // regular unary operators
            for (sal_uInt16 nOp = SC_OPCODE_START_UN_OP; nOp < SC_OPCODE_STOP_UN_OP && nOp < mnSymbols; ++nOp)
            {
                switch (nOp)
                {
                    // NOT and NEG in fact are functions but for legacy reasons
                    // are sorted into unary operators for compiler interna.
                    case SC_OPCODE_NOT :
                    case SC_OPCODE_NEG :
                        break;   // nothing,
                    default:
                        lclPushOpCodeMapEntry( aVec, mpTable.get(), nOp );
                }
                lclPushOpCodeMapEntry( aVec, mpTable.get(), nOp );
            }
        }
        if ((nGroups & FormulaMapGroup::BINARY_OPERATORS) != 0)
@@ -568,9 +559,7 @@ uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::create
                SC_OPCODE_IF_NA,
                SC_OPCODE_CHOOSE,
                SC_OPCODE_AND,
                SC_OPCODE_OR,
                SC_OPCODE_NOT,
                SC_OPCODE_NEG
                SC_OPCODE_OR
            };
            lclPushOpCodeMapEntries( aVec, mpTable.get(), aOpCodes, SAL_N_ELEMENTS(aOpCodes) );
            // functions with 2 or more parameters.
@@ -1473,9 +1462,7 @@ void FormulaCompiler::Factor()
                NextToken();
            }
        }
        // special cases NOT() and NEG()
        else if( eOp == ocNot || eOp == ocNeg
              || (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR) )
        else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
        {
            if (eOp == ocIsoWeeknum && FormulaGrammar::isODFF( meGrammar ))
            {
@@ -1551,7 +1538,7 @@ void FormulaCompiler::Factor()
            }
            else
            {
                // standard handling of ocNot, ocNeg and 1-parameter opcodes
                // standard handling of 1-parameter opcodes
                pFacToken = mpToken;
                eOp = NextToken();
                if( nNumFmt == SvNumFormatType::UNDEFINED && eOp == ocNot )
@@ -1918,18 +1905,6 @@ void FormulaCompiler::CompareLine()
    }
}

void FormulaCompiler::NotLine()
{
    CompareLine();
    while (mpToken->GetOpCode() == ocNot)
    {
        FormulaTokenRef p = mpToken;
        NextToken();
        CompareLine();
        PutCode(p);
    }
}

OpCode FormulaCompiler::Expression()
{
    static const short nRecursionMax = 42;
@@ -1939,13 +1914,13 @@ OpCode FormulaCompiler::Expression()
        SetError( FormulaError::StackOverflow );
        return ocStop;      //! generate token instead?
    }
    NotLine();
    CompareLine();
    while (mpToken->GetOpCode() == ocAnd || mpToken->GetOpCode() == ocOr)
    {
        FormulaTokenRef p = mpToken;
        mpToken->SetByte( 2 );       // 2 parameters!
        NextToken();
        NotLine();
        CompareLine();
        PutCode(p);
    }
    return mpToken->GetOpCode();
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 13d6914..1d33b4d 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -92,7 +92,6 @@ bool FormulaToken::IsFunction() const
                                                                            // FuncAutoPilot)
        || eOp == ocMacro || eOp == ocExternal                  // macros, AddIns
        || eOp == ocAnd || eOp == ocOr                          // former binary, now x parameters
        || eOp == ocNot || eOp == ocNeg                         // unary but function
        || (eOp >= ocInternalBegin && eOp <= ocInternalEnd)     // internal
        ));
}
diff --git a/include/formula/FormulaCompiler.hxx b/include/formula/FormulaCompiler.hxx
index 26d996f..8171b0a 100644
--- a/include/formula/FormulaCompiler.hxx
+++ b/include/formula/FormulaCompiler.hxx
@@ -317,7 +317,6 @@ protected:
    void AddSubLine();
    void ConcatLine();
    void CompareLine();
    void NotLine();
    OpCode Expression();
    void PopTokenArray();
    void PushTokenArray( FormulaTokenArray*, bool );
diff --git a/include/formula/compiler.hxx b/include/formula/compiler.hxx
index a1ebabe..61b054c 100644
--- a/include/formula/compiler.hxx
+++ b/include/formula/compiler.hxx
@@ -97,10 +97,8 @@

/*** Unary operators ***/
#define SC_OPCODE_START_UN_OP        70
#define SC_OPCODE_NOT                70
#define SC_OPCODE_NEG                71
#define SC_OPCODE_NEG_SUB            72
#define SC_OPCODE_STOP_UN_OP         73
#define SC_OPCODE_NEG_SUB            70
#define SC_OPCODE_STOP_UN_OP         71

#define SC_OPCODE_START_FUNCTION     75

@@ -205,7 +203,9 @@
#define SC_OPCODE_ERROR_TYPE_ODF    175
#define SC_OPCODE_ENCODEURL         176
#define SC_OPCODE_ISOWEEKNUM        177
#define SC_OPCODE_STOP_1_PAR        178
#define SC_OPCODE_NOT               178
#define SC_OPCODE_NEG               179
#define SC_OPCODE_STOP_1_PAR        180

/*** Functions with more than one parameters ***/
#define SC_OPCODE_START_2_PAR       201
diff --git a/include/formula/opcode.hxx b/include/formula/opcode.hxx
index a96707b..acc5255 100644
--- a/include/formula/opcode.hxx
+++ b/include/formula/opcode.hxx
@@ -96,8 +96,6 @@ enum OpCode : sal_uInt16
        ocUnion             = SC_OPCODE_UNION,
        ocRange             = SC_OPCODE_RANGE,
    // Unary operators
        ocNot               = SC_OPCODE_NOT,
        ocNeg               = SC_OPCODE_NEG,
        ocNegSub            = SC_OPCODE_NEG_SUB,
    // Functions with no parameters
        ocPi                = SC_OPCODE_PI,
@@ -109,6 +107,8 @@ enum OpCode : sal_uInt16
        ocNotAvail          = SC_OPCODE_NO_VALUE,
        ocCurrent           = SC_OPCODE_CURRENT,
    // Functions with one parameter
        ocNot               = SC_OPCODE_NOT,
        ocNeg               = SC_OPCODE_NEG,
        ocDeg               = SC_OPCODE_DEG,
        ocRad               = SC_OPCODE_RAD,
        ocSin               = SC_OPCODE_SIN,
diff --git a/sc/source/core/data/funcdesc.cxx b/sc/source/core/data/funcdesc.cxx
index 26621c0f..d4373e1 100644
--- a/sc/source/core/data/funcdesc.cxx
+++ b/sc/source/core/data/funcdesc.cxx
@@ -427,7 +427,6 @@ ScFunctionList::ScFunctionList()
        { SC_OPCODE_CHOOSE, ENTRY(SC_OPCODE_CHOOSE_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_WAHL, VAR_ARGS+1, { 0, 0 } },
        { SC_OPCODE_AND, ENTRY(SC_OPCODE_AND_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_UND, VAR_ARGS, { 0 } },
        { SC_OPCODE_OR, ENTRY(SC_OPCODE_OR_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_ODER, VAR_ARGS, { 0 } },
        { SC_OPCODE_NOT, ENTRY(SC_OPCODE_NOT_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_NICHT, 1, { 0 } },
        { SC_OPCODE_PI, ENTRY(SC_OPCODE_PI_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_PI, 0, { } },
        { SC_OPCODE_RANDOM, ENTRY(SC_OPCODE_RANDOM_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ZUFALLSZAHL, 0, { } },
        { SC_OPCODE_TRUE, ENTRY(SC_OPCODE_TRUE_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_WAHR, 0, { } },
@@ -523,6 +522,7 @@ ScFunctionList::ScFunctionList()
        { SC_OPCODE_ERROR_TYPE_ODF, ENTRY(SC_OPCODE_ERROR_TYPE_ODF_ARY), 0, ID_FUNCTION_GRP_TABLE, HID_FUNC_ERROR_TYPE_ODF, 1, { 0 } },
        { SC_OPCODE_ENCODEURL, ENTRY(SC_OPCODE_ENCODEURL_ARY), 0, ID_FUNCTION_GRP_TEXT, HID_FUNC_ENCODEURL, 1, { 0 } },
        { SC_OPCODE_ISOWEEKNUM, ENTRY(SC_OPCODE_ISOWEEKNUM_ARY), 0, ID_FUNCTION_GRP_DATETIME, HID_FUNC_ISOWEEKNUM, 1, { 0 } },
        { SC_OPCODE_NOT, ENTRY(SC_OPCODE_NOT_ARY), 0, ID_FUNCTION_GRP_LOGIC, HID_FUNC_NICHT, 1, { 0 } },
        { SC_OPCODE_ARC_TAN_2, ENTRY(SC_OPCODE_ARC_TAN_2_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_ARCTAN2, 2, { 0, 0 } },
        { SC_OPCODE_CEIL, ENTRY(SC_OPCODE_CEIL_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_OBERGRENZE, 3, { 0, 1, 1 } },
        { SC_OPCODE_FLOOR, ENTRY(SC_OPCODE_FLOOR_ARY), 0, ID_FUNCTION_GRP_MATH, HID_FUNC_UNTERGRENZE, 3, { 0, 1, 1 } },