summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorandri lim <jangko128@gmail.com>2018-08-07 14:07:18 +0700
committerAndreas Rumpf <rumpf_a@web.de>2018-08-07 09:07:18 +0200
commitc3d5ec8eadf3aa887f34231c2d7b5818923818d4 (patch)
tree281055a93fc5f6fbc429c78a7e4b6b7624afe2d4
parentbe4816f5097ce72e124e5e087ffa4d386fa17d4d (diff)
downloadNim-c3d5ec8eadf3aa887f34231c2d7b5818923818d4.tar.gz
fixes #8421, fixes #7968, Nim compiler compiles with MSVC C89 version (#8556)
-rw-r--r--compiler/rodutils.nim21
-rw-r--r--lib/pure/math.nim82
-rw-r--r--lib/windows/winlean.nim2
3 files changed, 80 insertions, 25 deletions
diff --git a/compiler/rodutils.nim b/compiler/rodutils.nim
index 66d7f63c2..a774cdba7 100644
--- a/compiler/rodutils.nim
+++ b/compiler/rodutils.nim
@@ -10,6 +10,27 @@
 ## Serialization utilities for the compiler.
 import strutils, math
 
+# MSVC prior to 2013 doesn't have C99 functions
+when defined(windows) and (defined(vcc) or defined(bcc)):
+  {.emit: """#if defined(_MSC_VER) && _MSC_VER < 1900
+  #include <stdarg.h>
+  static int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
+    int count = -1;
+    if (size != 0) count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+    if (count == -1) count = _vscprintf(format, ap);
+    return count;
+  }
+  int snprintf(char *outBuf, size_t size, const char *format, ...) {
+    int count;
+    va_list ap;
+    va_start(ap, format);
+    count = c99_vsnprintf(outBuf, size, format, ap);
+    va_end(ap);
+    return count;
+  }
+  #endif
+  """.}
+
 proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf", header: "<stdio.h>", nodecl, varargs.}
 
 proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index b921b1841..eb09bf4a7 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -162,9 +162,6 @@ when not defined(JS): # C
   proc log10*(x: float32): float32 {.importc: "log10f", header: "<math.h>".}
   proc log10*(x: float64): float64 {.importc: "log10", header: "<math.h>".}
     ## Computes the common logarithm (base 10) of `x`
-  proc log2*(x: float32): float32 {.importc: "log2f", header: "<math.h>".}
-  proc log2*(x: float64): float64 {.importc: "log2", header: "<math.h>".}
-    ## Computes the binary logarithm (base 2) of `x`
   proc exp*(x: float32): float32 {.importc: "expf", header: "<math.h>".}
   proc exp*(x: float64): float64 {.importc: "exp", header: "<math.h>".}
     ## Computes the exponential function of `x` (pow(E, x))
@@ -268,6 +265,8 @@ proc arcsech*[T: float32|float64](x: T): T = arccosh(1.0 / x)
 proc arccsch*[T: float32|float64](x: T): T = arcsinh(1.0 / x)
   ## Computes the inverse hyperbolic cosecant of `x`
 
+const windowsCC89 = defined(windows) and (defined(vcc) or defined(bcc))
+
 when not defined(JS): # C
   proc hypot*(x, y: float32): float32 {.importc: "hypotf", header: "<math.h>".}
   proc hypot*(x, y: float64): float64 {.importc: "hypot", header: "<math.h>".}
@@ -280,25 +279,27 @@ when not defined(JS): # C
     ##
     ## To compute power between integers, use `^` e.g. 2 ^ 6
 
-  proc erf*(x: float32): float32 {.importc: "erff", header: "<math.h>".}
-  proc erf*(x: float64): float64 {.importc: "erf", header: "<math.h>".}
-    ## The error function
-  proc erfc*(x: float32): float32 {.importc: "erfcf", header: "<math.h>".}
-  proc erfc*(x: float64): float64 {.importc: "erfc", header: "<math.h>".}
-    ## The complementary error function
-
-  proc gamma*(x: float32): float32 {.importc: "tgammaf", header: "<math.h>".}
-  proc gamma*(x: float64): float64 {.importc: "tgamma", header: "<math.h>".}
-    ## The gamma function
-  proc tgamma*(x: float32): float32
-    {.deprecated: "use gamma instead", importc: "tgammaf", header: "<math.h>".}
-  proc tgamma*(x: float64): float64
-    {.deprecated: "use gamma instead", importc: "tgamma", header: "<math.h>".}
-    ## The gamma function
-    ## **Deprecated since version 0.19.0**: Use ``gamma`` instead.
-  proc lgamma*(x: float32): float32 {.importc: "lgammaf", header: "<math.h>".}
-  proc lgamma*(x: float64): float64 {.importc: "lgamma", header: "<math.h>".}
-    ## Natural log of the gamma function
+  # TODO: add C89 version on windows
+  when not windowsCC89:
+    proc erf*(x: float32): float32 {.importc: "erff", header: "<math.h>".}
+    proc erf*(x: float64): float64 {.importc: "erf", header: "<math.h>".}
+      ## The error function
+    proc erfc*(x: float32): float32 {.importc: "erfcf", header: "<math.h>".}
+    proc erfc*(x: float64): float64 {.importc: "erfc", header: "<math.h>".}
+      ## The complementary error function
+
+    proc gamma*(x: float32): float32 {.importc: "tgammaf", header: "<math.h>".}
+    proc gamma*(x: float64): float64 {.importc: "tgamma", header: "<math.h>".}
+      ## The gamma function
+    proc tgamma*(x: float32): float32
+      {.deprecated: "use gamma instead", importc: "tgammaf", header: "<math.h>".}
+    proc tgamma*(x: float64): float64
+      {.deprecated: "use gamma instead", importc: "tgamma", header: "<math.h>".}
+      ## The gamma function
+      ## **Deprecated since version 0.19.0**: Use ``gamma`` instead.
+    proc lgamma*(x: float32): float32 {.importc: "lgammaf", header: "<math.h>".}
+    proc lgamma*(x: float64): float64 {.importc: "lgamma", header: "<math.h>".}
+      ## Natural log of the gamma function
 
   proc floor*(x: float32): float32 {.importc: "floorf", header: "<math.h>".}
   proc floor*(x: float64): float64 {.importc: "floor", header: "<math.h>".}
@@ -314,7 +315,7 @@ when not defined(JS): # C
     ## .. code-block:: nim
     ##  echo ceil(-2.1) ## -2.0
 
-  when defined(windows) and (defined(vcc) or defined(bcc)):
+  when windowsCC89:
     # MSVC 2010 don't have trunc/truncf
     # this implementation was inspired by Go-lang Math.Trunc
     proc truncImpl(f: float64): float64 =
@@ -452,6 +453,28 @@ when not defined(JS):
     var exp: int32
     result = c_frexp(x, exp)
     exponent = exp
+
+  when windowsCC89:
+    # taken from Go-lang Math.Log2
+    const ln2 = 0.693147180559945309417232121458176568075500134360255254120680009
+    template log2Impl[T](x: T): T =
+      var exp: int32
+      var frac = frexp(x, exp)
+      # Make sure exact powers of two give an exact answer.
+      # Don't depend on Log(0.5)*(1/Ln2)+exp being exactly exp-1.
+      if frac == 0.5: return T(exp - 1)
+      log10(frac)*(1/ln2) + T(exp)
+
+    proc log2*(x: float32): float32 = log2Impl(x)
+    proc log2*(x: float64): float64 = log2Impl(x)
+      ## Log2 returns the binary logarithm of x.
+      ## The special cases are the same as for Log.
+
+  else:
+    proc log2*(x: float32): float32 {.importc: "log2f", header: "<math.h>".}
+    proc log2*(x: float64): float64 {.importc: "log2", header: "<math.h>".}
+      ## Computes the binary logarithm (base 2) of `x`
+
 else:
   proc frexp*[T: float32|float64](x: T, exponent: var int): T =
     if x == 0.0:
@@ -564,7 +587,7 @@ proc lcm*[T](x, y: T): T =
   ## Computes the least common multiple of ``x`` and ``y``.
   x div gcd(x, y) * y
 
-when isMainModule and not defined(JS):
+when isMainModule and not defined(JS) and not windowsCC89:
   # Check for no side effect annotation
   proc mySqrt(num: float): float {.noSideEffect.} =
     return sqrt(num)
@@ -692,3 +715,14 @@ when isMainModule:
 
   block: # log
     doAssert log(4.0, 3.0) == ln(4.0) / ln(3.0)
+    doAssert log2(8.0'f64) == 3.0'f64
+    doAssert log2(4.0'f64) == 2.0'f64
+    doAssert log2(2.0'f64) == 1.0'f64
+    doAssert log2(1.0'f64) == 0.0'f64
+    doAssert classify(log2(0.0'f64)) == fcNegInf
+
+    doAssert log2(8.0'f32) == 3.0'f32
+    doAssert log2(4.0'f32) == 2.0'f32
+    doAssert log2(2.0'f32) == 1.0'f32
+    doAssert log2(1.0'f32) == 0.0'f32
+    doAssert classify(log2(0.0'f32)) == fcNegInf
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 3263f1d37..60a6e5d9b 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -396,7 +396,7 @@ else:
 
   proc moveFileA*(lpExistingFileName, lpNewFileName: cstring): WINBOOL {.
     importc: "MoveFileA", stdcall, dynlib: "kernel32".}
-  proc moveFileExA*(lpExistingFileName, lpNewFileName: WideCString,
+  proc moveFileExA*(lpExistingFileName, lpNewFileName: cstring,
                     flags: DWORD): WINBOOL {.
     importc: "MoveFileExA", stdcall, dynlib: "kernel32".}