summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorrockcavera <rockcavera@gmail.com>2022-01-07 04:26:55 -0300
committerGitHub <noreply@github.com>2022-01-07 08:26:55 +0100
commitc7d5b8c83ddf204c6e0cd7b6937d33318320ed91 (patch)
tree0fa2a955f7b5f840fc2bf391fa54bce480fe172a /lib
parent5ec8b609421a2e74e7d5f8d00293194faf4437d4 (diff)
downloadNim-c7d5b8c83ddf204c6e0cd7b6937d33318320ed91.tar.gz
Fix #19038 - making the Nim compiler work again on Windows XP (#19331)
* Update osenv.nim

* Update win_setenv.nim

* Update lib/pure/includes/osenv.nim

* Update lib/pure/includes/osenv.nim

* fixing cstring

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/includes/osenv.nim5
-rw-r--r--lib/std/private/win_setenv.nim41
2 files changed, 24 insertions, 22 deletions
diff --git a/lib/pure/includes/osenv.nim b/lib/pure/includes/osenv.nim
index 1a01ab9bc..4a776eb78 100644
--- a/lib/pure/includes/osenv.nim
+++ b/lib/pure/includes/osenv.nim
@@ -45,7 +45,7 @@ when not defined(nimscript):
     proc c_getenv(env: cstring): cstring {.
       importc: "getenv", header: "<stdlib.h>".}
     when defined(windows):
-      proc c_putenv_s(envname: cstring, envval: cstring): cint {.importc: "_putenv_s", header: "<stdlib.h>".}
+      proc c_putenv(envstring: cstring): cint {.importc: "_putenv", header: "<stdlib.h>".}
       from std/private/win_setenv import setEnvImpl
     else:
       proc c_setenv(envname: cstring, envval: cstring, overwrite: cint): cint {.importc: "setenv", header: "<stdlib.h>".}
@@ -121,7 +121,8 @@ when not defined(nimscript):
         ]#
         if key.len == 0 or '=' in key:
           raise newException(OSError, "invalid key, got: " & key)
-        if c_putenv_s(key, "") != 0'i32: bail
+        let envToDel = key & "="
+        if c_putenv(cstring envToDel) != 0'i32: bail
       else:
         if c_unsetenv(key) != 0'i32: bail
 
diff --git a/lib/std/private/win_setenv.nim b/lib/std/private/win_setenv.nim
index 91c3f15b0..0dfe0ed46 100644
--- a/lib/std/private/win_setenv.nim
+++ b/lib/std/private/win_setenv.nim
@@ -30,44 +30,45 @@ else:
     # same as winlean.setEnvironmentVariableA
 
   proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
-  proc c_putenv_s(envname: cstring, envval: cstring): cint {.importc: "_putenv_s", header: "<stdlib.h>".}
+  proc c_putenv(envstring: cstring): cint {.importc: "_putenv", header: "<stdlib.h>".}
   proc c_wgetenv(varname: ptr wchar_t): ptr wchar_t {.importc: "_wgetenv", header: "<stdlib.h>".}
 
   var errno {.importc, header: "<errno.h>".}: cint
-  var gWenviron {.importc:"_wenviron".}: ptr ptr wchar_t
+  var gWenviron {.importc: "_wenviron".}: ptr ptr wchar_t
     # xxx `ptr UncheckedArray[WideCString]` did not work
 
-  proc mbstowcs_s(pReturnValue: ptr csize_t, wcstr: ptr wchar_t, sizeInWords: csize_t, mbstr: cstring, count: csize_t): cint {.importc: "mbstowcs_s", header: "<stdlib.h>".}
+  proc mbstowcs(wcstr: ptr wchar_t, mbstr: cstring, count: csize_t): csize_t {.importc: "mbstowcs", header: "<stdlib.h>".}
     # xxx cint vs errno_t?
 
-  proc setEnvImpl*(name: cstring, value: cstring, overwrite: cint): cint =
+  proc setEnvImpl*(name: string, value: string, overwrite: cint): cint =
     const EINVAL = cint(22)
-    const MAX_ENV = 32767
-      # xxx get it from: `var MAX_ENV {.importc: "_MAX_ENV", header:"<stdlib.h>".}: cint`
-    if overwrite == 0 and c_getenv(name) != nil: return 0
-    if value[0] != '\0':
-      let e = c_putenv_s(name, value)
+    if overwrite == 0 and c_getenv(cstring(name)) != nil: return 0
+    if value != "":
+      let envstring = name & "=" & value
+      let e = c_putenv(cstring(envstring))
       if e != 0:
-        errno = e
+        errno = EINVAL
         return -1
       return 0
     #[
-    We are trying to set the value to an empty string, but `_putenv_s` deletes
+    We are trying to set the value to an empty string, but `_putenv` deletes
     entries if the value is an empty string, and just calling
     SetEnvironmentVariableA doesn't update `_environ`,
     so we have to do these terrible things.
     ]#
-    if c_putenv_s(name, "  ") != 0:
+    let envstring = name & "=  "
+    if c_putenv(cstring(envstring)) != 0:
       errno = EINVAL
       return -1
     # Here lies the documentation we blatently ignore to make this work.
-    var s = c_getenv(name)
+    var s = c_getenv(cstring(name))
     s[0] = '\0'
     #[
     This would result in a double null termination, which normally signifies the
     end of the environment variable list, so we stick a completely empty
     environment variable into the list instead.
     ]#
+    s = c_getenv(cstring(name))
     s[1] = '='
     #[
     If gWenviron is null, the wide environment has not been initialized
@@ -77,19 +78,19 @@ else:
     ]#
     if gWenviron != nil:
       # var buf: array[MAX_ENV + 1, WideCString]
-      var buf: array[MAX_ENV + 1, Utf16Char]
+      let requiredSize = mbstowcs(nil, cstring(name), 0).int
+      var buf = newSeq[Utf16Char](requiredSize + 1)
       let buf2 = cast[ptr wchar_t](buf[0].addr)
-      var len: csize_t
-      if mbstowcs_s(len.addr, buf2, buf.len.csize_t, name, MAX_ENV) != 0:
+      if mbstowcs(buf2, cstring(name), csize_t(requiredSize + 1)) == csize_t(high(uint)):
         errno = EINVAL
         return -1
-      let ptrToEnv = cast[WideCString](c_wgetenv(buf2))
+      var ptrToEnv = cast[WideCString](c_wgetenv(buf2))
       ptrToEnv[0] = '\0'.Utf16Char
-      let ptrToEnv2 = cast[WideCString](c_wgetenv(buf2))
-      ptrToEnv2[1] = '='.Utf16Char
+      ptrToEnv = cast[WideCString](c_wgetenv(buf2))
+      ptrToEnv[1] = '='.Utf16Char
 
     # And now, we have to update the outer environment to have a proper empty value.
-    if setEnvironmentVariableA(name, value) == 0:
+    if setEnvironmentVariableA(cstring(name), cstring(value)) == 0:
       errno = EINVAL
       return -1
     return 0