xref: /core/include/formula/errorcodes.hxx (revision da9a6f42)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_FORMULA_ERRORCODES_HXX
21 #define INCLUDED_FORMULA_ERRORCODES_HXX
22 
23 #include <rtl/math.hxx>
24 #include <sal/mathconf.h>
25 #include <sal/types.h>
26 
27 // Store as 16-bits, since error values are stored in tokens and formula results,
28 // and that can matter
29 enum class FormulaError : sal_uInt16
30 {
31     NONE                 = 0,
32 
33     IllegalChar          = 501,
34     IllegalArgument      = 502,
35     IllegalFPOperation   = 503, // #NUM!
36     IllegalParameter     = 504,
37     Pair                 = 507,
38     PairExpected         = 508,
39     OperatorExpected     = 509,
40     VariableExpected     = 510,
41     ParameterExpected    = 511,
42     CodeOverflow         = 512,
43     StringOverflow       = 513,
44     StackOverflow        = 514,
45     UnknownState         = 515,
46     UnknownVariable      = 516,
47     UnknownOpCode        = 517,
48     UnknownStackVariable = 518,
49     NoValue              = 519, // #VALUE!
50     UnknownToken         = 520,
51     NoCode               = 521, // #NULL!
52     CircularReference    = 522,
53     NoConvergence        = 523,
54     NoRef                = 524, // #REF!
55     NoName               = 525, // #NAME?
56 // ScInterpreter internal:  no numeric value but numeric queried. If this is
57 // set as mnStringNoValueError no error is generated but 0 returned.
58     CellNoValue          = 529,
59 // Interpreter: needed AddIn not found
60     NoAddin              = 530,
61 // Interpreter: needed Macro not found
62     NoMacro              = 531,
63 // Interpreter: Division by zero
64     DivisionByZero       = 532, // #DIV/0!
65 // Compiler: a non-simple (str,err,val) value was put in an array
66     NestedArray          = 533,
67 // ScInterpreter internal:  no numeric value but numeric queried. If this is
68 // temporarily (!) set as mnStringNoValueError, the error is generated and can
69 // be used to distinguish that condition from all other (inherited) errors. Do
70 // not use for anything else! Never push or inherit the error otherwise!
71     NotNumericString     = 534,
72 // ScInterpreter internal:  jump matrix already has a result at this position,
73 // do not overwrite in case of empty code path.
74     JumpMatHasResult     = 535,
75 // ScInterpreter internal:  (matrix) element is not a numeric value, i.e.
76 // string or empty, to be distinguished from the general FormulaError::NoValue NAN and not
77 // to be used as result.
78     ElementNaN           = 536,
79 // ScInterpreter/ScFormulaCell internal:  keep dirty, retry interpreting next
80 // round.
81     RetryCircular        = 537,
82 // If matrix could not be allocated.
83     MatrixSize           = 538,
84 // Bad inline array content, non-value/non-string.
85     BadArrayContent      = 539,
86 // Interpreter: signal result not available because updating links is not
87 // allowed (yet) and tell to try hybrid string as result.
88     LinkFormulaNeedingCheck = 540,
89 
90 // Interpreter: NA() not available condition, not a real error
91     NotAvailable         = 0x7fff
92 };
93 
94 /** Unconditionally construct a double value of NAN where the lower bits
95     represent an interpreter error code. */
96 inline double CreateDoubleError( FormulaError nErr )
97 {
98     sal_math_Double smVal;
99     ::rtl::math::setNan( &smVal.value );
100     smVal.nan_parts.fraction_lo = static_cast<unsigned>(nErr);
101     return smVal.value;
102 }
103 
104 /** Recreate the error code of a coded double error, if any. */
105 inline FormulaError GetDoubleErrorValue( double fVal )
106 {
107     if ( ::rtl::math::isFinite( fVal ) )
108         return FormulaError::NONE;
109     if ( ::rtl::math::isInf( fVal ) )
110         return FormulaError::IllegalFPOperation;       // normal INF
111     sal_uInt32 nErr = reinterpret_cast< sal_math_Double * >( &fVal)->nan_parts.fraction_lo;
112     if ( nErr & 0xffff0000 )
113         return FormulaError::NoValue;                  // just a normal NAN
114     if (!nErr)
115         // Another NAN, e.g. -nan(0x8000000000000) from calculating with -inf
116         return FormulaError::IllegalFPOperation;
117     // Any other error known to us as error code.
118     return static_cast<FormulaError>(nErr & 0x0000ffff);
119 }
120 
121 /** Error values that are accepted as detailed "#ERRxxx!" constants.
122 
123     Used in FormulaCompiler::GetErrorConstant() to prevent users from inventing
124     arbitrary values that already have or later might get a significant meaning.
125  */
126 inline bool isPublishedFormulaError( FormulaError nErr )
127 {
128     // Every value has to be handled explicitly, do not add a default case to
129     // let the compiler complain if a value is missing.
130     switch (nErr)
131     {
132         case FormulaError::NONE:
133             return false;
134 
135         case FormulaError::IllegalChar:
136         case FormulaError::IllegalArgument:
137         case FormulaError::IllegalFPOperation:
138         case FormulaError::IllegalParameter:
139         case FormulaError::Pair:
140         case FormulaError::PairExpected:
141         case FormulaError::OperatorExpected:
142         case FormulaError::VariableExpected:
143         case FormulaError::ParameterExpected:
144         case FormulaError::CodeOverflow:
145         case FormulaError::StringOverflow:
146         case FormulaError::StackOverflow:
147         case FormulaError::UnknownState:
148         case FormulaError::UnknownVariable:
149         case FormulaError::UnknownOpCode:
150         case FormulaError::UnknownStackVariable:
151         case FormulaError::NoValue:
152         case FormulaError::UnknownToken:
153         case FormulaError::NoCode:
154         case FormulaError::CircularReference:
155         case FormulaError::NoConvergence:
156         case FormulaError::NoRef:
157         case FormulaError::NoName:
158             return true;
159 
160         case FormulaError::CellNoValue:
161             return false;
162 
163         case FormulaError::NoAddin:
164         case FormulaError::NoMacro:
165         case FormulaError::DivisionByZero:
166         case FormulaError::NestedArray:
167         case FormulaError::BadArrayContent:
168             return true;
169 
170         case FormulaError::NotNumericString:
171         case FormulaError::JumpMatHasResult:
172         case FormulaError::ElementNaN:
173         case FormulaError::RetryCircular:
174             return false;
175 
176         case FormulaError::MatrixSize:
177         case FormulaError::LinkFormulaNeedingCheck:
178             return true;
179 
180         case FormulaError::NotAvailable:
181             return false;
182     }
183     return false;
184 }
185 
186 #endif // INCLUDED_FORMULA_ERRORCODES_HXX
187 
188 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
189