Browse Source

HPCC-8352 Move DBZaction into eclrtl and more cleaning up

* Also introduce a mark/release into the bcdCriticalBlock so that
divide by zero exceptions don't cause roxie to run out of bcd stack

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 12 years ago
parent
commit
9f44b4628c

+ 1 - 1
common/deftype/deftype.cpp

@@ -33,7 +33,7 @@
 #include <math.h>
 #include <algorithm>
 
-#include "bcd.hpp"
+#include "rtlbcd.hpp"
 #include "eclrtl.hpp"
 #include "eclrtl_imp.hpp"
 

+ 11 - 11
common/deftype/defvalue.cpp

@@ -26,7 +26,7 @@
 #include <math.h>
 #include <limits.h>
 
-#include "bcd.hpp"
+#include "rtlbcd.hpp"
 #include "eclrtl_imp.hpp"
 
 #if defined(_DEBUG) && defined(_WIN32) && !defined(USING_MPATROL)
@@ -2524,7 +2524,7 @@ IValue * multiplyValues(IValue * left, IValue * right)
     return ret;
 }
 
-IValue * divideValues(IValue * left, IValue * right, DBZaction onZero)
+IValue * divideValues(IValue * left, IValue * right, byte dbz)
 {
     Owned<ITypeInfo> pnt = getPromotedMulDivType(left->queryType(), right->queryType());
 
@@ -2532,10 +2532,10 @@ IValue * divideValues(IValue * left, IValue * right, DBZaction onZero)
     if (!right->getBoolValue())
     {
         //If no action is selected, return NULL so the expression doesn't get constant folded.
-        if (onZero == DBZnone)
+        if (dbz == DBZnone)
             return NULL;
 
-        if (onZero == DBZfail)
+        if (dbz == DBZfail)
             rtlFailDivideByZero();
     }
 
@@ -2564,7 +2564,7 @@ IValue * divideValues(IValue * left, IValue * right, DBZaction onZero)
         double res;
         if (rv)
             res = lv / rv;
-        else if (onZero == DBZnan)
+        else if (dbz == DBZnan)
             res =  rtlCreateRealNull();
         else
             res = 0.0;
@@ -2576,7 +2576,7 @@ IValue * divideValues(IValue * left, IValue * right, DBZaction onZero)
         BcdCriticalBlock bcdBlock;
         left->pushDecimalValue();
         right->pushDecimalValue();
-        DecDivide(onZero);
+        DecDivide(dbz);
         return createDecimalValueFromStack(pnt);
     }
     default:
@@ -2585,7 +2585,7 @@ IValue * divideValues(IValue * left, IValue * right, DBZaction onZero)
     }
 }
 
-IValue * modulusValues(IValue * left, IValue * right, DBZaction onZero)
+IValue * modulusValues(IValue * left, IValue * right, byte dbz)
 {
     Owned<ITypeInfo> pnt = getPromotedMulDivType(left->queryType(), right->queryType());
     
@@ -2593,10 +2593,10 @@ IValue * modulusValues(IValue * left, IValue * right, DBZaction onZero)
     if (!right->getBoolValue())
     {
         //If no action is selected, return NULL so the expression doesn't get constant folded.
-        if (onZero == DBZnone)
+        if (dbz == DBZnone)
             return NULL;
 
-        if (onZero == DBZfail)
+        if (dbz == DBZfail)
             rtlFailDivideByZero();
     }
 
@@ -2624,7 +2624,7 @@ IValue * modulusValues(IValue * left, IValue * right, DBZaction onZero)
         double res;
         if (rv)
             res = fmod(left->getRealValue(), rv);
-        else if (onZero == DBZnan)
+        else if (dbz == DBZnan)
             res =  rtlCreateRealNull();
         else
             res = 0.0;
@@ -2636,7 +2636,7 @@ IValue * modulusValues(IValue * left, IValue * right, DBZaction onZero)
         BcdCriticalBlock bcdBlock;
         left->pushDecimalValue();
         right->pushDecimalValue();
-        DecModulus(onZero);
+        DecModulus(dbz);
         return createDecimalValueFromStack(pnt);
     }
     default:

+ 2 - 2
common/deftype/defvalue.hpp

@@ -110,8 +110,8 @@ extern DEFTYPE_API IValue * createMinUIntValue(unsigned __int64 value);
 extern DEFTYPE_API IValue * addValues(IValue * left, IValue * right);
 extern DEFTYPE_API IValue * subtractValues(IValue * left, IValue * right);
 extern DEFTYPE_API IValue * multiplyValues(IValue * left, IValue * right);
-extern DEFTYPE_API IValue * divideValues(IValue * left, IValue * right, DBZaction onZero);
-extern DEFTYPE_API IValue * modulusValues(IValue * left, IValue * right, DBZaction onZero);
+extern DEFTYPE_API IValue * divideValues(IValue * left, IValue * right, byte dbz);
+extern DEFTYPE_API IValue * modulusValues(IValue * left, IValue * right, byte dbz);
 extern DEFTYPE_API IValue * powerValues(IValue * left, IValue * right);
 extern DEFTYPE_API IValue * shiftLeftValues(IValue * left, IValue * right);
 extern DEFTYPE_API IValue * shiftRightValues(IValue * left, IValue * right);

+ 1 - 1
common/fileview2/fvresultset.cpp

@@ -17,7 +17,7 @@
 
 #include "platform.h"
 #include "jliball.hpp"
-#include "bcd.hpp"
+#include "rtlbcd.hpp"
 #include "workunit.hpp"
 #include "seclib.hpp"
 #include "eclrtl.hpp"

+ 1 - 1
common/thorhelper/thorxmlwrite.cpp

@@ -22,7 +22,7 @@
 #include "rtlkey.hpp"
 #include "eclhelper.hpp"
 #include "deftype.hpp"
-#include "bcd.hpp"
+#include "rtlbcd.hpp"
 
 CommonXmlWriter::CommonXmlWriter(unsigned _flags, unsigned initialIndent, IXmlStreamFlusher *_flusher) 
 {

+ 1 - 0
common/workunit/workunit.cpp

@@ -39,6 +39,7 @@
 #include "dllserver.hpp"
 #include "thorhelper.hpp"
 #include "workflow.hpp"
+
 #include "nbcd.hpp"
 #include "seclib.hpp"
 

+ 2 - 0
ecl/hql/hqlatoms.cpp

@@ -122,6 +122,7 @@ _ATOM externalAtom;
 _ATOM failAtom;
 _ATOM failureAtom;
 _ATOM falseAtom;
+_ATOM fastAtom;
 _ATOM fewAtom;
 _ATOM fieldAtom;
 _ATOM fieldsAtom;
@@ -531,6 +532,7 @@ MODULE_INIT(INIT_PRIORITY_HQLATOM)
     MAKEATOM(fail);
     MAKEATOM(failure);
     MAKEATOM(false);
+    MAKEATOM(fast);
     MAKEATOM(few);
     MAKEATOM(field);
     MAKEATOM(fields);

+ 1 - 0
ecl/hql/hqlatoms.hpp

@@ -125,6 +125,7 @@ extern HQL_API _ATOM externalAtom;
 extern HQL_API _ATOM failAtom;
 extern HQL_API _ATOM failureAtom;
 extern HQL_API _ATOM falseAtom;
+extern HQL_API _ATOM fastAtom;
 extern HQL_API _ATOM fewAtom;
 extern HQL_API _ATOM fieldAtom;
 extern HQL_API _ATOM fieldsAtom;

+ 1 - 0
ecl/hqlcpp/hqlcpp.ipp

@@ -28,6 +28,7 @@
 #include "hqlwcpp.hpp"
 #include "hqltrans.ipp"
 #include "hqlusage.hpp"
+#include "eclrtl.hpp"
 
 #define DEBUG_TIMER(name, time)                     if (options.addTimingToWorkunit) { timeReporter->addTiming(name, time); }
 #define DEBUG_TIMERX(timeReporter, name, time)      if (timeReporter) { timeReporter->addTiming(name, time); }

+ 49 - 49
ecl/hqlcpp/hqlcppsys.ecl

@@ -306,55 +306,55 @@ const char * cppSystemText[]  = {
     "   unsigned8 castUInt6(unsigned8 value) :  eclrtl,pure,library='eclrtl',include,entrypoint='rtliCastUInt6';",
     "   unsigned8 castUInt7(unsigned8 value) :  eclrtl,pure,library='eclrtl',include,entrypoint='rtliCastUInt7';",
 
-    "   DecAbs() :  bcd,library='nbcd',entrypoint='DecAbs';",
-    "   DecAdd() :  bcd,library='nbcd',entrypoint='DecAdd';",
-    "   integer4 DecCompareDecimal(const data v1, const data1 v2) : bcd,pure,library='nbcd',entrypoint='DecCompareDecimal';",
-    "   integer4 DecCompareUDecimal(const data v1, const data1 v2) : bcd,pure,library='nbcd',entrypoint='DecCompareUDecimal';",
-    "   integer4 DecCompareNull() : bcd,library='nbcd',entrypoint='DecCompareNull';",
-    "   integer4 DecDistinct() :    bcd,library='nbcd',entrypoint='DecDistinct';",
-    "   integer4 DecDistinctR() :   bcd,library='nbcd',entrypoint='DecDistinctR';",
-    "   DecDivide(unsigned1 dbz) :   bcd,library='nbcd',entrypoint='DecDivide';",
-    "   DecModulus(unsigned1 dbz) :  bcd,library='nbcd',entrypoint='DecModulus';",
-    "   DecSub() :  bcd,library='nbcd',entrypoint='DecSub';",
-    "   DecSubR() : bcd,library='nbcd',entrypoint='DecSubR';",
-    "   DecNegate() :   bcd,library='nbcd',entrypoint='DecNegate';",
-    "   unsigned4 DecPopString(string tgt) :    bcd,library='nbcd',entrypoint='DecPopString';",
-    "   DecPopVString(string tgt) : bcd,library='nbcd',entrypoint='DecPopCString';",
-    "   varstring DecPopVStringX() :    bcd,library='nbcd',entrypoint='DecPopCStringX';",
-    "   integer8 DecPopInt64() :    bcd,library='nbcd',entrypoint='DecPopInt64';",
-    "   DecPopDecimal(data1 tgt,unsigned1 len,unsigned1 prec) : bcd,library='nbcd',entrypoint='DecPopDecimal';",
-    "   DecPopUDecimal(data1 tgt,unsigned1 len,unsigned1 prec) : bcd,library='nbcd',entrypoint='DecPopUDecimal';",
-    "   unsigned4 DecPopUlong() :   bcd,library='nbcd',entrypoint='DecPopUlong';",
-    "   real8 DecPopReal() :    bcd,library='nbcd',entrypoint='DecPopReal';",
-    "   DecPushString(const string tgt) :   bcd,library='nbcd',entrypoint='DecPushString';",
-    "   DecPushCString(const varstring src) :   bcd,library='nbcd',entrypoint='DecPushCString';",
-    "   DecPushInt64(integer8 src) :    bcd,library='nbcd',entrypoint='DecPushInt64';",
-    "   DecPushLong(integer4 src) : bcd,library='nbcd',entrypoint='DecPushLong';",
-    "   DecPushDecimal(const data1 src, unsigned1 declen, unsigned1 prec) : bcd,library='nbcd',entrypoint='DecPushDecimal';",
-    "   DecPushUDecimal(const data1 src, unsigned1 declen, unsigned1 prec) : bcd,library='nbcd',entrypoint='DecPushUDecimal';",
-    "   DecPushUInt64(unsigned8 src) :  bcd,library='nbcd',entrypoint='DecPushUInt64';",
-    "   DecPushULong(unsigned4 src) :   bcd,library='nbcd',entrypoint='DecPushULong';",
-    "   DecRound() :    bcd,library='nbcd',entrypoint='DecRound';",
-    "   DecRoundUp() :  bcd,library='nbcd',entrypoint='DecRoundUp';",
-    "   DecRoundTo(unsigned4 places) :  bcd,library='nbcd',entrypoint='DecRoundTo';",
-    "   DecDup() :  bcd,library='nbcd',entrypoint='DecDup';",
-    "   DecMul() :  bcd,library='nbcd',entrypoint='DecMul';",
-    "   DecDivideR(unsigned1 dbz) :  bcd,library='nbcd',entrypoint='DecDivideR';",
-    "   DecLongPower(integer4 pow) :    bcd,library='nbcd',entrypoint='DecLongPower';",
-    "   DecPushReal(real8 d) :  bcd,library='nbcd',entrypoint='DecPushReal';",
-    "   DecPushUtf8(utf8 d) :   bcd,library='nbcd',entrypoint='rtlDecPushUtf8';",
-    "   DecTruncate() :    bcd,library='nbcd',entrypoint='DecTruncate';",
-    "   DecTruncateAt(unsigned4 places) :  bcd,library='nbcd',entrypoint='DecTruncateAt';",
-
-    "   DecSetPrecision(unsigned1 len, unsigned1 prec) : bcd,library='nbcd',entrypoint='DecSetPrecision';",
-    "   integer4 DecPopLong() : bcd,library='nbcd',entrypoint='DecPopLong';",
-    "   DecSwap() : bcd,library='nbcd',entrypoint='DecSwap';",
-    "   DecUint4Power(unsigned4 pow) :  bcd,library='nbcd',entrypoint='DecUint4Power';",
-    "   string DecPopStringX() :    bcd,library='nbcd',entrypoint='DecPopStringX';",
-    "   DecLock() : bcd,library='nbcd',entrypoint='DecLock';",
-    "   DecUnlock() :   bcd,library='nbcd',entrypoint='DecUnlock';",
-    "   boolean DecValid(boolean isSigned, const data src) : bcd,pure,library='nbcd',entrypoint='DecValid';",
-    "   boolean DecValidTos() : bcd,pure,library='nbcd',entrypoint='DecValidTos';",
+    "   DecAbs() :  eclrtl,library='eclrtl',entrypoint='DecAbs';",
+    "   DecAdd() :  eclrtl,library='eclrtl',entrypoint='DecAdd';",
+    "   integer4 DecCompareDecimal(const data v1, const data1 v2) : eclrtl,pure,library='eclrtl',entrypoint='DecCompareDecimal';",
+    "   integer4 DecCompareUDecimal(const data v1, const data1 v2) : eclrtl,pure,library='eclrtl',entrypoint='DecCompareUDecimal';",
+    "   integer4 DecCompareNull() : eclrtl,library='eclrtl',entrypoint='DecCompareNull';",
+    "   integer4 DecDistinct() :    eclrtl,library='eclrtl',entrypoint='DecDistinct';",
+    "   integer4 DecDistinctR() :   eclrtl,library='eclrtl',entrypoint='DecDistinctR';",
+    "   DecDivide(unsigned1 dbz) :   eclrtl,library='eclrtl',entrypoint='DecDivide';",
+    "   DecModulus(unsigned1 dbz) :  eclrtl,library='eclrtl',entrypoint='DecModulus';",
+    "   DecSub() :  eclrtl,library='eclrtl',entrypoint='DecSub';",
+    "   DecSubR() : eclrtl,library='eclrtl',entrypoint='DecSubR';",
+    "   DecNegate() :   eclrtl,library='eclrtl',entrypoint='DecNegate';",
+    "   unsigned4 DecPopString(string tgt) :    eclrtl,library='eclrtl',entrypoint='DecPopString';",
+    "   DecPopVString(string tgt) : eclrtl,library='eclrtl',entrypoint='DecPopCString';",
+    "   varstring DecPopVStringX() :    eclrtl,library='eclrtl',entrypoint='DecPopCStringX';",
+    "   integer8 DecPopInt64() :    eclrtl,library='eclrtl',entrypoint='DecPopInt64';",
+    "   DecPopDecimal(data1 tgt,unsigned1 len,unsigned1 prec) : eclrtl,library='eclrtl',entrypoint='DecPopDecimal';",
+    "   DecPopUDecimal(data1 tgt,unsigned1 len,unsigned1 prec) : eclrtl,library='eclrtl',entrypoint='DecPopUDecimal';",
+    "   unsigned4 DecPopUlong() :   eclrtl,library='eclrtl',entrypoint='DecPopUlong';",
+    "   real8 DecPopReal() :    eclrtl,library='eclrtl',entrypoint='DecPopReal';",
+    "   DecPushString(const string tgt) :   eclrtl,library='eclrtl',entrypoint='DecPushString';",
+    "   DecPushCString(const varstring src) :   eclrtl,library='eclrtl',entrypoint='DecPushCString';",
+    "   DecPushInt64(integer8 src) :    eclrtl,library='eclrtl',entrypoint='DecPushInt64';",
+    "   DecPushLong(integer4 src) : eclrtl,library='eclrtl',entrypoint='DecPushLong';",
+    "   DecPushDecimal(const data1 src, unsigned1 declen, unsigned1 prec) : eclrtl,library='eclrtl',entrypoint='DecPushDecimal';",
+    "   DecPushUDecimal(const data1 src, unsigned1 declen, unsigned1 prec) : eclrtl,library='eclrtl',entrypoint='DecPushUDecimal';",
+    "   DecPushUInt64(unsigned8 src) :  eclrtl,library='eclrtl',entrypoint='DecPushUInt64';",
+    "   DecPushULong(unsigned4 src) :   eclrtl,library='eclrtl',entrypoint='DecPushULong';",
+    "   DecRound() :    eclrtl,library='eclrtl',entrypoint='DecRound';",
+    "   DecRoundUp() :  eclrtl,library='eclrtl',entrypoint='DecRoundUp';",
+    "   DecRoundTo(unsigned4 places) :  eclrtl,library='eclrtl',entrypoint='DecRoundTo';",
+    "   DecDup() :  eclrtl,library='eclrtl',entrypoint='DecDup';",
+    "   DecMul() :  eclrtl,library='eclrtl',entrypoint='DecMul';",
+    "   DecDivideR(unsigned1 dbz) :  eclrtl,library='eclrtl',entrypoint='DecDivideR';",
+    "   DecLongPower(integer4 pow) :    eclrtl,library='eclrtl',entrypoint='DecLongPower';",
+    "   DecPushReal(real8 d) :  eclrtl,library='eclrtl',entrypoint='DecPushReal';",
+    "   DecPushUtf8(utf8 d) :   eclrtl,library='eclrtl',entrypoint='rtlDecPushUtf8';",
+    "   DecTruncate() :    eclrtl,library='eclrtl',entrypoint='DecTruncate';",
+    "   DecTruncateAt(unsigned4 places) :  eclrtl,library='eclrtl',entrypoint='DecTruncateAt';",
+
+    "   DecSetPrecision(unsigned1 len, unsigned1 prec) : eclrtl,library='eclrtl',entrypoint='DecSetPrecision';",
+    "   integer4 DecPopLong() : eclrtl,library='eclrtl',entrypoint='DecPopLong';",
+    "   DecSwap() : eclrtl,library='eclrtl',entrypoint='DecSwap';",
+    "   DecUint4Power(unsigned4 pow) :  eclrtl,library='eclrtl',entrypoint='DecUint4Power';",
+    "   string DecPopStringX() :    eclrtl,library='eclrtl',entrypoint='DecPopStringX';",
+    "   DecLock() : eclrtl,library='eclrtl',entrypoint='DecLock';",
+    "   DecUnlock() :   eclrtl,library='eclrtl',entrypoint='DecUnlock';",
+    "   boolean DecValid(boolean isSigned, const data src) : eclrtl,pure,library='eclrtl',entrypoint='DecValid';",
+    "   boolean DecValidTos() : eclrtl,pure,library='eclrtl',entrypoint='DecValidTos';",
 
     "   integer8 _ROUND(real8 arg) :    eclrtl,pure,library='eclrtl',entrypoint='rtlRound';",
     "   real8 roundTo(real8 arg, integer4 _places) : eclrtl,pure,library='eclrtl',entrypoint='rtlRoundTo';",

+ 5 - 5
ecl/hqlcpp/hqlwcpp.cpp

@@ -598,13 +598,13 @@ bool HqlCppWriter::generateFunctionPrototype(IHqlExpression * funcdef, const cha
         out.append(s);
         return true;
     }
-    enum { ServiceApi, RtlApi, BcdApi, CApi, CppApi, LocalApi } api = ServiceApi;
+    enum { ServiceApi, RtlApi, FastApi, CApi, CppApi, LocalApi } api = ServiceApi;
     bool isVirtual = funcdef->hasProperty(virtualAtom);
     bool isLocal = body->hasProperty(localAtom);
     if (body->hasProperty(eclrtlAtom))
         api = RtlApi;
-    else if (body->hasProperty(bcdAtom))
-        api = BcdApi;
+    else if (body->hasProperty(fastAtom))
+        api = FastApi;
     else if (body->hasProperty(cAtom))
         api = CApi;
     else if (body->hasProperty(cppAtom))
@@ -624,7 +624,7 @@ bool HqlCppWriter::generateFunctionPrototype(IHqlExpression * funcdef, const cha
     {
     case ServiceApi: out.append(" SERVICE_API"); break;
     case RtlApi:     out.append(" RTL_API"); break;
-    case BcdApi:     out.append(" BCD_API"); break;
+    case FastApi:     out.append(" BCD_API"); break;
     }
     out.append(" ");
 
@@ -642,7 +642,7 @@ bool HqlCppWriter::generateFunctionPrototype(IHqlExpression * funcdef, const cha
             break;
         }
         break;
-    case BcdApi:
+    case FastApi:
         switch (compiler)
         {
         case Vs6CppCompiler:

+ 19 - 1
rtl/eclrtl/CMakeLists.txt

@@ -27,6 +27,7 @@ project( eclrtl )
 
 set (    SRCS 
          eclrtl.cpp 
+         rtlbcd.cpp 
          rtldistr.cpp 
          rtlds.cpp 
          rtlint.cpp 
@@ -36,7 +37,23 @@ set (    SRCS
          rtlfield.cpp 
          rtlread.cpp 
          rtltype.cpp 
-         rtlxml.cpp 
+         rtlxml.cpp
+         
+         eclinclude.hpp
+         eclrtl.hpp
+         eclrtl_imp.hpp
+         rtlbcd.hpp
+         rtldistr.hpp
+         rtlds_imp.hpp
+         rtlfield_imp.hpp
+         rtlkey2.hpp
+         rtlkey.hpp
+         rtlread_imp.hpp
+         rtlsize.hpp
+         rtltype.hpp
+
+         rtlbcdtest.cpp 
+
     )
 
 include_directories ( 
@@ -71,6 +88,7 @@ FOREACH( iFILES
     ${CMAKE_CURRENT_SOURCE_DIR}/eclinclude.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/eclrtl.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/eclrtl_imp.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/rtlbcd.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/rtldistr.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/rtlds_imp.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/rtlfield_imp.hpp

+ 1 - 8
rtl/eclrtl/eclinclude.hpp

@@ -67,13 +67,6 @@ typedef unsigned __int64 hash64_t;
 #include "rtlfield_imp.hpp"
 #include "rtlds_imp.hpp"
 #include "eclhelper_base.hpp"
-
-extern __declspec(dllimport) void _fastcall DecLock();
-extern __declspec(dllimport) void _fastcall DecUnlock();
-struct BcdCriticalBlock
-{
-    BcdCriticalBlock()      { DecLock(); }
-    ~BcdCriticalBlock()     { DecUnlock(); }
-};
+#include "rtlbcd.hpp"
 
 #endif

+ 1 - 9
rtl/eclrtl/eclrtl.cpp

@@ -29,7 +29,7 @@
 #include "jptree.hpp"
 #include "junicode.hpp"
 #include "eclrtl.hpp"
-#include "bcd.hpp"
+#include "rtlbcd.hpp"
 #include "eclrtl_imp.hpp"
 #include "unicode/uchar.h"
 #include "unicode/ucol.h"
@@ -45,14 +45,6 @@
 
 #include "roxiemem.hpp"
 
-#ifndef _WIN32
-//typedef long long __int64;
-#define _fastcall
-#define __fastcall
-#define _stdcall
-#define __stdcall
-#endif
-
 #define UTF8_CODEPAGE "UTF-8"
 #define UTF8_MAXSIZE     4
 

+ 2 - 0
rtl/eclrtl/eclrtl.hpp

@@ -60,6 +60,8 @@ interface IException;
 class StringBuffer;
 class MemoryBuffer;
 
+enum DBZaction { DBZnone, DBZzero, DBZnan, DBZfail }; // Different actions on divide by zero
+
 //-----------------------------------------------------------------------------
 
 // RegEx Compiler for ansii  strings (uses BOOST)

+ 94 - 60
rtl/nbcd/nbcds.cpp

@@ -16,241 +16,277 @@
 ############################################################################## */
 
 #include "platform.h"
-#include "nbcd.hpp"
 #include "jlib.hpp"
-#include "bcd.hpp"
+#include "rtlbcd.hpp"
+#include "nbcd.hpp"
 #include "jmutex.hpp"
 #include "jexcept.hpp"
 
-CriticalSection bcdCriticalSection;
+static CriticalSection bcdCriticalSection;
+static Decimal stack[32];
+static unsigned curStack;
+
+//---------------------------------------------------------------------------------------------------------------------
 
-nbcd_decl void _fastcall  DecLock()
+void DecLock()
 {
     bcdCriticalSection.enter();
 }
 
-nbcd_decl void _fastcall  DecUnlock()
+void DecUnlock()
 {
     bcdCriticalSection.leave();
 }
 
-static Decimal stack[32];
-unsigned  curStack;
+unsigned DecMarkStack()
+{
+    return curStack;
+}
+
+void DecReleaseStack(unsigned mark)
+{
+    curStack = mark;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+
+static void setDivideByZero(Decimal & tos, DBZaction dbz)
+{
+    switch (dbz)
+    {
+    case DBZfail:
+        rtlFailDivideByZero();
+        break;
+    case DBZnan:
+    case DBZzero:
+        tos.setZero();
+        break;
+    default:
+        throwUnexpected();
+    }
+}
+
 
 
-nbcd_decl void _fastcall  DecAbs()
+nbcd_decl void DecAbs()
 {
     stack[curStack-1].abs();
 }
 
-nbcd_decl void _fastcall  DecAdd()
+nbcd_decl void DecAdd()
 {
     curStack--;
     stack[curStack-1].add(stack[curStack]);
 }
 
-nbcd_decl int _fastcall  DecCompareNull()
+nbcd_decl int DecCompareNull()
 {
     curStack--;
     return stack[curStack].compareNull();
 }
 
-nbcd_decl int _fastcall  DecDistinct()
+nbcd_decl int DecDistinct()
 {
     curStack -= 2;
     return stack[curStack].compare(stack[curStack+1]);
 }
 
-nbcd_decl int _fastcall  DecDistinctR()
+nbcd_decl int DecDistinctR()
 {
     curStack -= 2;
     return stack[curStack+1].compare(stack[curStack]);
 }
 
-nbcd_decl void _fastcall  DecDivide(byte dbz)
+nbcd_decl void DecDivide(byte dbz)
 {
     curStack--;
-    stack[curStack-1].divide(stack[curStack], (DBZaction)dbz);
+    if (stack[curStack].isZero())
+        setDivideByZero(stack[curStack-1], (DBZaction)dbz);
+    else
+        stack[curStack-1].divide(stack[curStack]);
 }
 
-nbcd_decl void _fastcall  DecDivideR(byte dbz)
+nbcd_decl void DecDivideR(byte dbz)
 {
     DecSwap();
     DecDivide(dbz);
 }
 
-nbcd_decl void _fastcall  DecDup()
+nbcd_decl void DecDup()
 {
     stack[curStack].set(stack[curStack-1]);
     curStack++;
 }
 
-nbcd_decl void _fastcall  DecSetPrecision(unsigned char declen, unsigned char prec)
+nbcd_decl void DecSetPrecision(unsigned char declen, unsigned char prec)
 {
     stack[curStack-1].round(prec).setPrecision(declen, prec);
 }
 
-nbcd_decl void _fastcall  DecSub()
+nbcd_decl void DecSub()
 {
     curStack--;
     stack[curStack-1].subtract(stack[curStack]);
 }
 
-nbcd_decl void _fastcall  DecSubR()
+nbcd_decl void DecSubR()
 {
     DecSwap();
     DecSub();
 }
 
-nbcd_decl void _fastcall  DecInfo (unsigned & digits, unsigned & prec)
+nbcd_decl void DecInfo (unsigned & digits, unsigned & prec)
 {
     stack[curStack-1].getPrecision(digits, prec);
 }
 
-nbcd_decl void _fastcall  DecClipInfo (unsigned & digits, unsigned & prec)
+nbcd_decl void DecClipInfo (unsigned & digits, unsigned & prec)
 {
     stack[curStack-1].getClipPrecision(digits, prec);
 }
 
-nbcd_decl void _fastcall  DecLongPower(long pow)
+nbcd_decl void DecLongPower(long pow)
 {
     stack[curStack-1].power((int)pow);
 }
 
-nbcd_decl void _fastcall  DecUlongPower(unsigned long pow)
+nbcd_decl void DecUlongPower(unsigned long pow)
 {
     stack[curStack-1].power((unsigned)pow);
 }
 
-nbcd_decl void  _fastcall  DecModulus(byte dbz)
+nbcd_decl void  DecModulus(byte dbz)
 {
     curStack--;
-    stack[curStack-1].modulus(stack[curStack], (DBZaction)dbz);
+    if (stack[curStack].isZero())
+        setDivideByZero(stack[curStack-1], (DBZaction)dbz);
+    else
+        stack[curStack-1].modulus(stack[curStack]);
 }
 
-nbcd_decl void _fastcall  DecMul()
+nbcd_decl void DecMul()
 {
     curStack--;
     stack[curStack-1].multiply(stack[curStack]);
 }
 
-nbcd_decl void _fastcall  DecNegate()
+nbcd_decl void DecNegate()
 {
     stack[curStack-1].negate();
 }
 
-nbcd_decl void _fastcall  DecPopCString (unsigned length, char * buffer)
+nbcd_decl void DecPopCString (unsigned length, char * buffer)
 {
     stack[--curStack].getCString(length, buffer);
 }
 
-nbcd_decl char * _fastcall  DecPopCStringX()
+nbcd_decl char * DecPopCStringX()
 {
     return stack[--curStack].getCString();
 }
 
-nbcd_decl __int64 _fastcall  DecPopInt64()
+nbcd_decl __int64 DecPopInt64()
 {
     return stack[--curStack].getInt64();
 }
 
-nbcd_decl void _fastcall  DecPopDecimal(void * buffer,unsigned char declen,unsigned char prec)
+nbcd_decl void DecPopDecimal(void * buffer,unsigned char declen,unsigned char prec)
 {
     stack[--curStack].round(prec).getDecimal(declen, prec, buffer);
 }
 
-nbcd_decl void _fastcall  DecPopUDecimal(void * buffer,unsigned char declen,unsigned char prec)
+nbcd_decl void DecPopUDecimal(void * buffer,unsigned char declen,unsigned char prec)
 {
     stack[--curStack].round(prec).getUDecimal(declen, prec, buffer);
 }
 
-nbcd_decl int    _fastcall  DecPopLong()
+nbcd_decl int    DecPopLong()
 {
     return stack[--curStack].getInt();
 }
 
-nbcd_decl unsigned long _fastcall  DecPopUlong()
+nbcd_decl unsigned long DecPopUlong()
 {
     return stack[--curStack].getUInt();
 }
 
-nbcd_decl double _fastcall  DecPopReal()
+nbcd_decl double DecPopReal()
 {
     return stack[--curStack].getReal();
 }
 
-nbcd_decl unsigned _fastcall  DecPopString( unsigned length, char * buffer)
+nbcd_decl unsigned DecPopString( unsigned length, char * buffer)
 {
     stack[--curStack].getString(length, buffer);
     return length;  // significant length??
 }
 
-nbcd_decl void _fastcall  DecPopStringX( unsigned & length, char * & buffer)
+nbcd_decl void DecPopStringX( unsigned & length, char * & buffer)
 {
     stack[--curStack].getStringX(length, buffer);
 }
 
-nbcd_decl void _fastcall  DecPushCString(const char *s)
+nbcd_decl void DecPushCString(const char *s)
 {
     stack[curStack++].setCString(s);
 }
 
-nbcd_decl void _fastcall  DecPushInt64(__int64 value)
+nbcd_decl void DecPushInt64(__int64 value)
 {
     stack[curStack++].setInt64(value);
 }
 
-nbcd_decl void _fastcall  DecPushUInt64(unsigned __int64 value)
+nbcd_decl void DecPushUInt64(unsigned __int64 value)
 {
     stack[curStack++].setUInt64(value);
 }
 
-nbcd_decl void _fastcall  DecPushLong( long value)
+nbcd_decl void DecPushLong( long value)
 {
     stack[curStack++].setInt(value);
 }
 
-nbcd_decl void _fastcall  DecPushDecimal(const void * buffer,unsigned char declen,unsigned char prec)
+nbcd_decl void DecPushDecimal(const void * buffer,unsigned char declen,unsigned char prec)
 {
     stack[curStack++].setDecimal(declen, prec, buffer);
 }
 
-nbcd_decl void _fastcall  DecPushUDecimal(const void * buffer,unsigned char declen,unsigned char prec)
+nbcd_decl void DecPushUDecimal(const void * buffer,unsigned char declen,unsigned char prec)
 {
     stack[curStack++].setUDecimal(declen, prec, buffer);
 }
 
-nbcd_decl void _fastcall  DecPushReal( double value )
+nbcd_decl void DecPushReal( double value )
 {
     stack[curStack++].setReal(value);
 }
 
-nbcd_decl void _fastcall  DecPushString(unsigned length, const char * text)
+nbcd_decl void DecPushString(unsigned length, const char * text)
 {
     stack[curStack++].setString(length, text);
 }
 
-nbcd_decl void _fastcall  DecPushUlong( unsigned long value)
+nbcd_decl void DecPushUlong( unsigned long value)
 {
     stack[curStack++].setUInt(value);
 }
 
-nbcd_decl void _fastcall  DecRound()
+nbcd_decl void DecRound()
 {
     stack[curStack-1].round(0);
 }
 
-nbcd_decl void _fastcall  DecRoundUp()
+nbcd_decl void DecRoundUp()
 {
     stack[curStack-1].roundup(0);
 }
 
-nbcd_decl void _fastcall  DecRoundTo(unsigned places)
+nbcd_decl void DecRoundTo(unsigned places)
 {
     stack[curStack-1].round(places);
 }
 
-nbcd_decl void _fastcall  DecSwap()
+nbcd_decl void DecSwap()
 {
     char temp[sizeof(Decimal)];
     memcpy(&temp, &stack[curStack-1], sizeof(Decimal));
@@ -259,47 +295,45 @@ nbcd_decl void _fastcall  DecSwap()
 }
 
 
-nbcd_decl void _fastcall  DecTruncate()
+nbcd_decl void DecTruncate()
 {
     stack[curStack-1].truncate(0);
 }
 
-nbcd_decl void _fastcall  DecTruncateAt(unsigned places)
+nbcd_decl void DecTruncateAt(unsigned places)
 {
     stack[curStack-1].truncate(places);
 }
 
-nbcd_decl bool _fastcall  DecValid(bool isSigned, unsigned digits, const void * data)
+nbcd_decl bool DecValid(bool isSigned, unsigned digits, const void * data)
 {
     return decValid(isSigned, digits, data);
 }
 
-nbcd_decl bool _fastcall  DecValidTos()
+nbcd_decl bool DecValidTos()
 {
     return stack[--curStack].isValid();
 }
 
-nbcd_decl bool _fastcall  Dec2Bool(size32_t bytes, const void * data)
+nbcd_decl bool Dec2Bool(size32_t bytes, const void * data)
 {
     return dec2Bool(bytes, data);
 }
 
-nbcd_decl bool _fastcall  UDec2Bool(size32_t bytes, const void * data)
+nbcd_decl bool UDec2Bool(size32_t bytes, const void * data)
 {
     return udec2Bool(bytes, data);
 }
 
-nbcd_decl int _fastcall  DecCompareDecimal(size32_t bytes, const void * _left, const void * _right)
+nbcd_decl int DecCompareDecimal(size32_t bytes, const void * _left, const void * _right)
 {
     return decCompareDecimal(bytes, _left, _right);
 }
 
-nbcd_decl int    _fastcall  DecCompareUDecimal(size32_t bytes, const void * _left, const void * _right)
+nbcd_decl int    DecCompareUDecimal(size32_t bytes, const void * _left, const void * _right)
 {
     return decCompareUDecimal(bytes, _left, _right);
 }
 
 // internal
 
-nbcd_decl void * _fastcall  DecSaveStack( void )            { UNIMPLEMENTED; }
-nbcd_decl void _fastcall  DecRestoreStack( void * )     { UNIMPLEMENTED; }

+ 101 - 0
rtl/eclrtl/rtlbcd.hpp

@@ -0,0 +1,101 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef _RTLBCD_HPP_
+#define _RTLBCD_HPP_
+
+#include "eclrtl.hpp"
+
+ECLRTL_API void  DecAbs( void );         // make top of stack absolute
+ECLRTL_API void  DecAdd( void );         // add top two values on stack and replace with result
+ECLRTL_API int   DecCompareNull( void ); // compare top of stack to NULL, returns result, takes value of stack
+ECLRTL_API int   DecDistinct( void );    // compares second to top value on stack, removes them and returns result
+ECLRTL_API int   DecDistinctR( void );   // compares top to second value on stack, removes them and returns result
+ECLRTL_API void  DecDivide(byte dbz);      // divide second by top value on stack and replace with result
+ECLRTL_API void  DecDivideR(byte dbz);     // divide top by second value on stack and replace with result
+ECLRTL_API void  DecDup( void );         // duplicate value on top of decimal stack
+ECLRTL_API void  DecSetPrecision(unsigned char declen, unsigned char prec); // changes length and precision of top value on stack
+ECLRTL_API void  DecSub( void );         // substract top from second value on stack and replace with result
+ECLRTL_API void  DecSubR( void );        // substract second from top value on stack and replace with result
+ECLRTL_API void  DecInfo(unsigned & digits, unsigned & prec); // returns the digits and precision of top value on stack
+ECLRTL_API void  DecClipInfo(unsigned & digits, unsigned & prec);
+ECLRTL_API void  DecLongPower(long pow);   // calculates top of stack to the power of long and replaces with result
+ECLRTL_API void  DecModulus(byte dbz);   // modulus second by top value on stack and replace with result
+ECLRTL_API void  DecMul( void );         // multiply values top and second on the stack and replace with result
+ECLRTL_API void  DecNegate( void );      // negate value on top of the decimal stack
+ECLRTL_API void  DecPopCString (unsigned, char *); // Pops decimal accumulator into CString
+ECLRTL_API char * DecPopCStringX();       // Pop decimal accumulator into CString allocated on heap
+ECLRTL_API __int64 DecPopInt64( void );    // Pops decimal accumulator into __Int64
+ECLRTL_API void  DecPopDecimal(void * tgt,unsigned char declen,unsigned char prec); // Pops decimal value of the stack
+ECLRTL_API void  DecPopUDecimal(void * tgt,unsigned char declen,unsigned char prec); // Pops unsigned decimal value of the stack
+ECLRTL_API int   DecPopLong( void );       // Pops decimal accumulator into long
+ECLRTL_API unsigned long  DecPopUlong( void );    // Pops decimal accumulator into unsigned long
+ECLRTL_API double         DecPopReal( void );     // Pops decimal accumulator into real (double)
+ECLRTL_API unsigned     DecPopString( unsigned, char * );   // Pops decimal accumulator into string
+ECLRTL_API void  DecPopStringX( unsigned &, char * & );   // Pops decimal accumulator into string, determines size and allocates string
+ECLRTL_API void  DecPushCString(const char *s);  // Pushes CString onto decimal stack
+ECLRTL_API void  DecPushInt64(__int64 ); // Pushes __Int64 onto decimal stack
+ECLRTL_API void  DecPushUInt64(unsigned __int64 ); // Pushes unsigned __Int64 onto decimal stack
+ECLRTL_API void  DecPushLong( long );    // Pushes long value onto decimal stack
+ECLRTL_API void  DecPushDecimal(const void *,unsigned char declen,unsigned char prec); // Pushes decimal value onto the stack
+ECLRTL_API void  DecPushUDecimal(const void *,unsigned char declen,unsigned char prec); // Pushes unsigned decimal value onto the stack
+ECLRTL_API void  DecPushReal( double d );  // pushes real (double) onto decimal stack
+ECLRTL_API void  DecPushString(unsigned, const char * ); // Pushes string onto decimal stack
+ECLRTL_API void  DecPushUlong( unsigned long ); // Pushes unsigned long value onto decimal stack
+ECLRTL_API void  DecRestoreStack( void * ); // Restore decimal stack
+ECLRTL_API void  DecRound( void );       // round value on top of decimal stack
+ECLRTL_API void  DecRoundUp( void );       // round value on top of decimal stack
+ECLRTL_API void  DecRoundTo( unsigned places );       // round value on top of decimal stack
+ECLRTL_API void  * DecSaveStack( void );   // Save decimal stack
+ECLRTL_API void  DecSwap( void );          // swap top and second values on decimal stack
+ECLRTL_API void  DecTruncate( void );       // truncate value on top of decimal stack
+ECLRTL_API void  DecTruncateAt(unsigned places);       // truncate value on top of decimal stack
+ECLRTL_API void  DecUlongPower(unsigned long pow); // calculates top of stack to the power of unsigned long and replaces with result
+
+ECLRTL_API void  DecLock();
+ECLRTL_API void  DecUnlock();
+ECLRTL_API bool  DecValid(bool isSigned, unsigned digits, const void * data);
+ECLRTL_API bool  DecValidTos();
+ECLRTL_API bool  Dec2Bool(size32_t bytes, const void * data);
+ECLRTL_API bool  UDec2Bool(size32_t bytes, const void * data);
+
+ECLRTL_API int   DecCompareDecimal(size32_t bytes, const void * _left, const void * _right);
+ECLRTL_API int   DecCompareUDecimal(size32_t bytes, const void * _left, const void * _right);
+
+// internal
+void                     AddBytes(unsigned dest,unsigned src,unsigned num); 
+ECLRTL_API char  DecClip(void *);
+ECLRTL_API void  DecRoundPos(void *,int by);
+ECLRTL_API void  SetMAccum(unsigned char c);
+
+ECLRTL_API void  DecLock();
+ECLRTL_API void  DecUnlock();
+ECLRTL_API unsigned DecMarkStack();
+ECLRTL_API void DecReleaseStack(unsigned mark);
+
+class ECLRTL_API BcdCriticalBlock
+{
+public:
+    inline BcdCriticalBlock()       { DecLock(); mark = DecMarkStack(); }
+    inline ~BcdCriticalBlock()      { DecReleaseStack(mark); DecUnlock(); }
+
+protected:
+    unsigned mark;
+};
+
+
+#endif

+ 6 - 6
rtl/nbcd/nbcdtest.cpp

@@ -16,10 +16,10 @@
 ############################################################################## */
 
 #include "platform.h"
-#define DECIMAL_OVERLOAD
-#include "nbcd.hpp"
-#include "bcd.hpp"
 #include "jlog.hpp"
+#include "rtlbcd.hpp"
+
+#include "nbcd.hpp"
 
 #define _elements_in(a) (sizeof(a)/sizeof((a)[0]))
 
@@ -108,7 +108,7 @@ protected:
         char temp[80];
         Decimal a = left;
         Decimal b = right;
-        a.divide(b, DBZzero);
+        a.divide(b);
         a.getCString(sizeof(temp), temp);
         cppunit_assert(strcmp(expected, temp) == 0, "ERROR: testDivide/getCString: expected '%s', got '%s'", expected, temp);
         DecPushCString(left);
@@ -138,7 +138,7 @@ protected:
         char temp[80];
         Decimal a = left;
         Decimal b = right;
-        a.modulus(b, DBZzero);
+        a.modulus(b);
         a.getCString(sizeof(temp), temp);
         cppunit_assert(strcmp(expected, temp) == 0, "ERROR: testModulus: expected '%s', got '%s'", expected, temp);
     }
@@ -552,7 +552,7 @@ protected:
                 }
 
                 sofar1.multiply(value);
-                sofar2.divide(value, DBZzero);
+                sofar2.divide(value);
             }
             cppunit_assert(success, "ERROR: testBcdPower: one or more errors detected above.");
         }

+ 1 - 1
rtl/eclrtl/rtlint.cpp

@@ -24,7 +24,7 @@
 #include "jlib.hpp"
 #include "jptree.hpp"
 #include "eclrtl.hpp"
-#include "bcd.hpp"
+#include "rtlbcd.hpp"
 
 //#define _FAST_AND_LOOSE_
 

+ 1 - 18
rtl/eclrtl/rtlqstr.cpp

@@ -25,7 +25,7 @@
 #include "jlib.hpp"
 #include "jptree.hpp"
 #include "eclrtl.hpp"
-#include "bcd.hpp"
+#include "rtlbcd.hpp"
 #include "unicode/uchar.h"
 #include "unicode/ucol.h"
 #include "unicode/ustring.h"
@@ -37,14 +37,6 @@
 #include "jlog.hpp"
 #include "jmd5.hpp"
 
-#ifndef _WIN32
-//typedef long long __int64;
-#define _fastcall
-#define __fastcall
-#define _stdcall
-#define __stdcall
-#endif
-
 //=============================================================================
 // Miscellaneous string functions...
 
@@ -520,15 +512,6 @@ bool rtlQStrToBool(size32_t inlen, const char *in)
     return false;
 }
 
-#ifndef _WIN32
-extern "C" ECLRTL_API void cw_rtlQStrToStr(unsigned outlen, char * out, unsigned inlen, const char * in)
-#else
-extern "C" ECLRTL_API void __stdcall cw_rtlQStrToStr(unsigned outlen, char * out, unsigned inlen, const char * in)
-#endif
-{
-    rtlQStrToStr(QStrLength(outlen), out, QStrLength(inlen), in);
-}
-
 //---------------------------------------------------------------------------
 
 ECLRTL_API void rtlCreateQStrRange(size32_t & outlen, char * & out, unsigned fieldLen, unsigned compareLen, size32_t len, const char * qstr, byte fill)

+ 1 - 9
rtl/eclrtl/rtlxml.cpp

@@ -25,7 +25,7 @@
 #include "jlib.hpp"
 #include "jptree.hpp"
 #include "eclrtl.hpp"
-#include "bcd.hpp"
+#include "rtlbcd.hpp"
 #include "unicode/uchar.h"
 #include "unicode/ucol.h"
 #include "unicode/ustring.h"
@@ -38,14 +38,6 @@
 #include "jmd5.hpp"
 #include "rtlqstr.ipp"
 
-#ifndef _WIN32
-//typedef long long __int64;
-#define _fastcall
-#define __fastcall
-#define _stdcall
-#define __stdcall
-#endif
-
 //---------------------------------------------------------------------------
 
 void outputXmlString(unsigned len, const char *field, const char *fieldname, StringBuffer &out)

+ 3 - 2
rtl/nbcd/CMakeLists.txt

@@ -27,8 +27,9 @@ project( nbcd )
 
 set ( SRCS 
       nbcd.cpp 
-      nbcds.cpp 
-      nbcdtest.cpp 
+
+      nbcd.hpp 
+
       sourcedoc.xml
     )
 

+ 0 - 106
rtl/nbcd/bcd.hpp

@@ -1,106 +0,0 @@
-/*##############################################################################
-
-    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-############################################################################## */
-
-#ifndef _BCD_
-#define _BCD_
-#include "platform.h"
-
-#ifdef _WIN32
- #ifdef NBCD_EXPORTS
-  #define nbcd_decl __declspec(dllexport)
- #else
-  #define nbcd_decl __declspec(dllimport)
- #endif
-#else
- #define nbcd_decl
-#endif
-
-#ifndef _WIN32
-#define _fastcall
-#define __fastcall
-#endif
-
-nbcd_decl void  _fastcall  DecAbs( void );         // make top of stack absolute
-nbcd_decl void  _fastcall  DecAdd( void );         // add top two values on stack and replace with result
-nbcd_decl int   _fastcall  DecCompareNull( void ); // compare top of stack to NULL, returns result, takes value of stack
-nbcd_decl int   _fastcall  DecDistinct( void );    // compares second to top value on stack, removes them and returns result
-nbcd_decl int   _fastcall  DecDistinctR( void );   // compares top to second value on stack, removes them and returns result
-nbcd_decl void  _fastcall  DecDivide(byte dbz);      // divide second by top value on stack and replace with result
-nbcd_decl void  _fastcall  DecDivideR(byte dbz);     // divide top by second value on stack and replace with result
-nbcd_decl void  _fastcall  DecDup( void );         // duplicate value on top of decimal stack
-nbcd_decl void  _fastcall  DecSetPrecision(unsigned char declen, unsigned char prec); // changes length and precision of top value on stack
-nbcd_decl void  _fastcall  DecSub( void );         // substract top from second value on stack and replace with result
-nbcd_decl void  _fastcall  DecSubR( void );        // substract second from top value on stack and replace with result
-nbcd_decl void  _fastcall  DecInfo(unsigned & digits, unsigned & prec); // returns the digits and precision of top value on stack
-nbcd_decl void  _fastcall  DecClipInfo(unsigned & digits, unsigned & prec);
-nbcd_decl void  _fastcall  DecLongPower(long pow);   // calculates top of stack to the power of long and replaces with result
-nbcd_decl void  _fastcall  DecModulus(byte dbz);   // modulus second by top value on stack and replace with result
-nbcd_decl void  _fastcall  DecMul( void );         // multiply values top and second on the stack and replace with result
-nbcd_decl void  _fastcall  DecNegate( void );      // negate value on top of the decimal stack
-nbcd_decl void  _fastcall  DecPopCString (unsigned, char *); // Pops decimal accumulator into CString
-nbcd_decl char * _fastcall  DecPopCStringX();       // Pop decimal accumulator into CString allocated on heap
-nbcd_decl __int64 _fastcall  DecPopInt64( void );    // Pops decimal accumulator into __Int64 
-nbcd_decl void  _fastcall  DecPopDecimal(void * tgt,unsigned char declen,unsigned char prec); // Pops decimal value of the stack
-nbcd_decl void  _fastcall  DecPopUDecimal(void * tgt,unsigned char declen,unsigned char prec); // Pops unsigned decimal value of the stack
-nbcd_decl int   _fastcall  DecPopLong( void );       // Pops decimal accumulator into long
-nbcd_decl unsigned long  _fastcall  DecPopUlong( void );    // Pops decimal accumulator into unsigned long
-nbcd_decl double         _fastcall  DecPopReal( void );     // Pops decimal accumulator into real (double)
-nbcd_decl unsigned     _fastcall  DecPopString( unsigned, char * );   // Pops decimal accumulator into string
-nbcd_decl void  _fastcall  DecPopStringX( unsigned &, char * & );   // Pops decimal accumulator into string, determines size and allocates string
-nbcd_decl void  _fastcall  DecPushCString(const char *s);  // Pushes CString onto decimal stack
-nbcd_decl void  _fastcall  DecPushInt64(__int64 ); // Pushes __Int64 onto decimal stack
-nbcd_decl void  _fastcall  DecPushUInt64(unsigned __int64 ); // Pushes unsigned __Int64 onto decimal stack
-nbcd_decl void  _fastcall  DecPushLong( long );    // Pushes long value onto decimal stack 
-nbcd_decl void  _fastcall  DecPushDecimal(const void *,unsigned char declen,unsigned char prec); // Pushes decimal value onto the stack
-nbcd_decl void  _fastcall  DecPushUDecimal(const void *,unsigned char declen,unsigned char prec); // Pushes unsigned decimal value onto the stack
-nbcd_decl void  _fastcall  DecPushReal( double d );  // pushes real (double) onto decimal stack
-nbcd_decl void  _fastcall  DecPushString(unsigned, const char * ); // Pushes string onto decimal stack
-nbcd_decl void  _fastcall  DecPushUlong( unsigned long ); // Pushes unsigned long value onto decimal stack
-nbcd_decl void  _fastcall  DecRestoreStack( void * ); // Restore decimal stack
-nbcd_decl void  _fastcall  DecRound( void );       // round value on top of decimal stack
-nbcd_decl void  _fastcall  DecRoundUp( void );       // round value on top of decimal stack
-nbcd_decl void  _fastcall  DecRoundTo( unsigned places );       // round value on top of decimal stack
-nbcd_decl void  * _fastcall  DecSaveStack( void );   // Save decimal stack
-nbcd_decl void  _fastcall  DecSwap( void );          // swap top and second values on decimal stack 
-nbcd_decl void  _fastcall  DecTruncate( void );       // truncate value on top of decimal stack
-nbcd_decl void  _fastcall  DecTruncateAt(unsigned places);       // truncate value on top of decimal stack
-nbcd_decl void  _fastcall  DecUlongPower(unsigned long pow); // calculates top of stack to the power of unsigned long and replaces with result
-
-nbcd_decl void  _fastcall  DecLock();
-nbcd_decl void  _fastcall  DecUnlock();
-nbcd_decl bool  _fastcall  DecValid(bool isSigned, unsigned digits, const void * data);
-nbcd_decl bool  _fastcall  DecValidTos();
-nbcd_decl bool  _fastcall  Dec2Bool(size32_t bytes, const void * data);
-nbcd_decl bool  _fastcall  UDec2Bool(size32_t bytes, const void * data);
-
-nbcd_decl int   _fastcall  DecCompareDecimal(size32_t bytes, const void * _left, const void * _right);
-nbcd_decl int   _fastcall  DecCompareUDecimal(size32_t bytes, const void * _left, const void * _right);
-
-// internal
-void                     AddBytes(unsigned dest,unsigned src,unsigned num); 
-nbcd_decl char  _fastcall  DecClip(void *);       
-nbcd_decl void  _fastcall  DecRoundPos(void *,int by);        
-nbcd_decl void  _fastcall  SetMAccum(unsigned char c);                       
-
-struct nbcd_decl BcdCriticalBlock
-{
-    inline BcdCriticalBlock()       { DecLock(); }
-    inline ~BcdCriticalBlock()      { DecUnlock(); }
-};
-
-
-#endif

+ 14 - 21
rtl/nbcd/nbcd.cpp

@@ -142,7 +142,7 @@ int Decimal::compare(const Decimal & other) const
 }
 
 
-Decimal & Decimal::divide(const Decimal & other, DBZaction dbz)
+Decimal & Decimal::divide(const Decimal & other)
 {
     //NB: Round towards zero
     int lo1, hi1, lo2, hi2;
@@ -160,7 +160,8 @@ Decimal & Decimal::divide(const Decimal & other, DBZaction dbz)
     }
     if (hi2 < lo2)
     {
-        setDivideByZero(dbz);
+        //Division by zero defined to return 0 instead of throw an exception
+        setZero();
         return *this;
     }
 
@@ -250,10 +251,18 @@ void Decimal::extendRange(byte oLsb, byte oMsb)
 }
 
 
-Decimal & Decimal::modulus(const Decimal & other, DBZaction dbz)
+bool Decimal::isZero() const
+{
+    //NB: Round towards zero
+    int lo, hi;
+    clip(lo, hi);
+    return (hi < lo);
+}
+
+Decimal & Decimal::modulus(const Decimal & other)
 {
     Decimal left(*this);
-    left.divide(other, dbz).truncate(0).multiply(other);
+    left.divide(other).truncate(0).multiply(other);
     return subtract(left);
 }
 
@@ -342,8 +351,7 @@ Decimal & Decimal::power(int value)
     //This probably gives slightly more expected results, but both suffer from rounding errors.
     Decimal reciprocal;
     reciprocal.setInt(1);
-    // DBZzero means 0D^-3 will return 0 instead of throwing an error if divide by zero is set to DBZfail.
-    reciprocal.divide(*this, DBZzero);
+    reciprocal.divide(*this);
     set(reciprocal);
     doPower((unsigned)-value);
     return *this;
@@ -1159,21 +1167,6 @@ void Decimal::setZero()
 }
 
 
-void Decimal::setDivideByZero(DBZaction dbz)
-{
-    switch (dbz)
-    {
-    case DBZfail:
-        //No dependency on eclrtl, so throw a jlib exception directly
-        throw MakeStringException(MSGAUD_user, -1, "Division by zero");
-    case DBZnan:
-    case DBZzero:
-        setZero();
-        break;
-    default:
-        throwUnexpected();
-    }
-}
 //---------------------------------------------------------------------------
 
 

+ 13 - 10
rtl/nbcd/nbcd.hpp

@@ -28,6 +28,8 @@
  #define nbcd_decl
 #endif
 
+#define DECIMAL_OVERLOAD
+
 template <byte length, byte precision> class decimal;
 
 /*
@@ -56,8 +58,8 @@ public:
     Decimal & add(const Decimal & other);
     int compareNull() const;
     int compare(const Decimal & other) const;
-    Decimal & divide(const Decimal & other, DBZaction dbz);
-    Decimal & modulus(const Decimal & other, DBZaction dbz);
+    Decimal & divide(const Decimal & other);
+    Decimal & modulus(const Decimal & other);
     Decimal & multiply(const Decimal & other);
     Decimal & negate();
     Decimal & power(int value);
@@ -85,6 +87,7 @@ public:
     void getPrecision(unsigned & digits, unsigned & precison);
 
     // MORE: We could support NaNs for decimals at a later date by adding a member to this class.
+    bool isZero() const;
     bool isValid() const { return true; }
 
     void set(const Decimal & value);
@@ -129,7 +132,6 @@ protected:
     void extendRange(byte oLsb, byte oMsb);
     void extendRange(const Decimal & other)     { extendRange(other.lsb, other.msb); }
     void overflow();
-    void setDivideByZero(DBZaction dbz);
 
 private:
     Decimal & incLSD();
@@ -175,8 +177,8 @@ protected:
 inline Decimal operator + (const Decimal & left, const Decimal & right) { return Decimal(left).add(right); }
 inline Decimal operator - (const Decimal & left, const Decimal & right) { return Decimal(left).subtract(right); }
 inline Decimal operator * (const Decimal & left, const Decimal & right) { return Decimal(left).multiply(right); }
-inline Decimal operator / (const Decimal & left, const Decimal & right) { return Decimal(left).divide(right, DBZzero); }
-inline Decimal operator % (const Decimal & left, const Decimal & right) { return Decimal(left).modulus(right, DBZzero); }
+inline Decimal operator / (const Decimal & left, const Decimal & right) { return Decimal(left).divide(right); }
+inline Decimal operator % (const Decimal & left, const Decimal & right) { return Decimal(left).modulus(right); }
 inline bool operator == (const Decimal & left, const Decimal & right) { return left.compare(right) == 0; }
 inline bool operator != (const Decimal & left, const Decimal & right) { return left.compare(right) != 0; }
 inline bool operator >= (const Decimal & left, const Decimal & right) { return left.compare(right) >= 0; }
@@ -185,10 +187,11 @@ inline bool operator > (const Decimal & left, const Decimal & right) { return le
 inline bool operator < (const Decimal & left, const Decimal & right) { return left.compare(right) < 0; }
 #endif
 
-bool dec2Bool(size32_t bytes, const void * data);
-bool udec2Bool(size32_t bytes, const void * data);
-int decCompareDecimal(size32_t bytes, const void * _left, const void * _right);
-int decCompareUDecimal(size32_t bytes, const void * _left, const void * _right);
-bool decValid(bool isSigned, unsigned digits, const void * data);
+//Various utility helper functions:
+nbcd_decl bool dec2Bool(size32_t bytes, const void * data);
+nbcd_decl bool udec2Bool(size32_t bytes, const void * data);
+nbcd_decl int decCompareDecimal(size32_t bytes, const void * _left, const void * _right);
+nbcd_decl int decCompareUDecimal(size32_t bytes, const void * _left, const void * _right);
+nbcd_decl bool decValid(bool isSigned, unsigned digits, const void * data);
 
 #endif

+ 0 - 2
system/include/platform.h

@@ -431,8 +431,6 @@ typedef int socklen_t;
 // **** END   OF UNIX SPECIFIC SECTION ****
 #endif
 
-enum DBZaction { DBZnone, DBZzero, DBZnan, DBZfail }; // Different actions on divide by zero
-
 #define FLOAT_SIG_DIGITS    7
 #define DOUBLE_SIG_DIGITS   16