breaking change: arrays of char do not convert to cstring; ptr to array of char does

This commit is contained in:
Andreas Rumpf 2017-10-10 00:17:20 +02:00
commit 3308d26581
12 changed files with 73 additions and 36 deletions

View file

@ -5,3 +5,6 @@
- Removed basic2d/basic3d out of the stdlib and into Nimble packages. - Removed basic2d/basic3d out of the stdlib and into Nimble packages.
These packages deprecated however, use the ``glm``, ``arraymancer``, ``neo`` These packages deprecated however, use the ``glm``, ``arraymancer``, ``neo``
or another package. or another package.
- Arrays of char cannot be converted to ``cstring`` anymore, pointers to
arrays of char can! This means ``$`` for arrays can finally exist
in ``system.nim`` and do the right thing.

View file

@ -108,3 +108,4 @@ proc initDefines*() =
defineSymbol("nimHasCppDefine") defineSymbol("nimHasCppDefine")
defineSymbol("nimGenericInOutFlags") defineSymbol("nimGenericInOutFlags")
when false: defineSymbol("nimHasOpt") when false: defineSymbol("nimHasOpt")
defineSymbol("nimNoArrayToCstringConversion")

View file

@ -20,6 +20,11 @@ proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
elif f == 0.5 * f: elif f == 0.5 * f:
if f > 0.0: result = "INF" if f > 0.0: result = "INF"
else: result = "-INF" else: result = "-INF"
else:
when defined(nimNoArrayToCstringConversion):
result = newString(81)
let n = c_snprintf(result.cstring, result.len.uint, "%#.16e%s", f, literalPostfix.cstring)
setLen(result, n)
else: else:
var buf: array[0..80, char] var buf: array[0..80, char]
discard c_snprintf(buf.cstring, buf.len.uint, "%#.16e%s", f, literalPostfix.cstring) discard c_snprintf(buf.cstring, buf.len.uint, "%#.16e%s", f, literalPostfix.cstring)

View file

@ -1288,11 +1288,12 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
of tyString: result = isConvertible of tyString: result = isConvertible
of tyPtr: of tyPtr:
# ptr[Tag, char] is not convertible to 'cstring' for now: # ptr[Tag, char] is not convertible to 'cstring' for now:
if a.len == 1 and a.sons[0].kind == tyChar: result = isConvertible if a.len == 1:
of tyArray: let pointsTo = a.sons[0].skipTypes(abstractInst)
if (firstOrd(a.sons[0]) == 0) and if pointsTo.kind == tyChar: result = isConvertible
(skipTypes(a.sons[0], {tyRange}).kind in {tyInt..tyInt64}) and elif pointsTo.kind == tyArray and firstOrd(pointsTo.sons[0]) == 0 and
(a.sons[1].kind == tyChar): skipTypes(pointsTo.sons[0], {tyRange}).kind in {tyInt..tyInt64} and
pointsTo.sons[1].kind == tyChar:
result = isConvertible result = isConvertible
else: discard else: discard

View file

@ -667,14 +667,6 @@ proc lengthOrd*(t: PType): BiggestInt =
else: else:
result = lastOrd(t) - firstOrd(t) + 1 result = lastOrd(t) - firstOrd(t) + 1
proc isCompatibleToCString*(a: PType): bool =
if a.kind == tyArray:
if (firstOrd(a.sons[0]) == 0) and
(skipTypes(a.sons[0], {tyRange, tyGenericInst, tyAlias}).kind in
{tyInt..tyInt64, tyUInt..tyUInt64}) and
(a.sons[1].kind == tyChar):
result = true
# -------------- type equality ----------------------------------------------- # -------------- type equality -----------------------------------------------
type type

View file

@ -496,11 +496,12 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
addr(namelen)) == -1'i32: addr(namelen)) == -1'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
# Cannot use INET6_ADDRSTRLEN here, because it's a C define. # Cannot use INET6_ADDRSTRLEN here, because it's a C define.
var buf: array[64, char] result[0] = newString(64)
if inet_ntop(name.sin6_family.cint, if inet_ntop(name.sin6_family.cint,
addr name.sin6_addr, buf.cstring, sizeof(buf).int32).isNil: addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
raiseOSError(osLastError()) raiseOSError(osLastError())
result = ($buf.cstring, Port(nativesockets.ntohs(name.sin6_port))) setLen(result[0], result[0].cstring.len)
result[1] = Port(nativesockets.ntohs(name.sin6_port))
else: else:
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr") raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
@ -532,11 +533,12 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
addr(namelen)) == -1'i32: addr(namelen)) == -1'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
# Cannot use INET6_ADDRSTRLEN here, because it's a C define. # Cannot use INET6_ADDRSTRLEN here, because it's a C define.
var buf: array[64, char] result[0] = newString(64)
if inet_ntop(name.sin6_family.cint, if inet_ntop(name.sin6_family.cint,
addr name.sin6_addr, buf.cstring, sizeof(buf).int32).isNil: addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
raiseOSError(osLastError()) raiseOSError(osLastError())
result = ($buf.cstring, Port(nativesockets.ntohs(name.sin6_port))) setLen(result[0], result[0].cstring.len)
result[1] = Port(nativesockets.ntohs(name.sin6_port))
else: else:
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr") raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")

View file

@ -790,6 +790,9 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
while true: while true:
var x = readdir(d) var x = readdir(d)
if x == nil: break if x == nil: break
when defined(nimNoArrayToCstringConversion):
var y = $cstring(addr x.d_name)
else:
var y = $x.d_name.cstring var y = $x.d_name.cstring
if y != "." and y != "..": if y != "." and y != "..":
var s: Stat var s: Stat

View file

@ -1890,10 +1890,16 @@ proc formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
frmtstr[3] = '*' frmtstr[3] = '*'
frmtstr[4] = floatFormatToChar[format] frmtstr[4] = floatFormatToChar[format]
frmtstr[5] = '\0' frmtstr[5] = '\0'
when defined(nimNoArrayToCstringConversion):
L = c_sprintf(addr buf, addr frmtstr, precision, f)
else:
L = c_sprintf(buf, frmtstr, precision, f) L = c_sprintf(buf, frmtstr, precision, f)
else: else:
frmtstr[1] = floatFormatToChar[format] frmtstr[1] = floatFormatToChar[format]
frmtstr[2] = '\0' frmtstr[2] = '\0'
when defined(nimNoArrayToCstringConversion):
L = c_sprintf(addr buf, addr frmtstr, f)
else:
L = c_sprintf(buf, frmtstr, f) L = c_sprintf(buf, frmtstr, f)
result = newString(L) result = newString(L)
for i in 0 ..< L: for i in 0 ..< L:

View file

@ -142,6 +142,9 @@ elif defined(windows) or defined(dos):
dec(m) dec(m)
k = k div 10 k = k div 10
if k == 0: break if k == 0: break
when defined(nimNoArrayToCstringConversion):
result = getProcAddress(cast[THINSTANCE](lib), addr decorated)
else:
result = getProcAddress(cast[THINSTANCE](lib), decorated) result = getProcAddress(cast[THINSTANCE](lib), decorated)
if result != nil: return if result != nil: return
procAddrError(name) procAddrError(name)

View file

@ -289,8 +289,12 @@ proc raiseExceptionAux(e: ref Exception) =
add(buf, " [") add(buf, " [")
xadd(buf, e.name, e.name.len) xadd(buf, e.name, e.name.len)
add(buf, "]\n") add(buf, "]\n")
unhandled(buf): when defined(nimNoArrayToCstringConversion):
showErrorMessage(buf) template tbuf(): untyped = addr buf
else:
template tbuf(): untyped = buf
unhandled(tbuf()):
showErrorMessage(tbuf())
quitOrDebug() quitOrDebug()
proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} = proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =

View file

@ -16,9 +16,14 @@ proc reprInt(x: int64): string {.compilerproc.} = return $x
proc reprFloat(x: float): string {.compilerproc.} = return $x proc reprFloat(x: float): string {.compilerproc.} = return $x
proc reprPointer(x: pointer): string {.compilerproc.} = proc reprPointer(x: pointer): string {.compilerproc.} =
var buf: array[60, char] when defined(nimNoArrayToCstringConversion):
discard c_sprintf(buf.cstring, "%p", x) result = newString(60)
result = $buf.cstring let n = c_sprintf(addr result[0], "%p", x)
setLen(result, n)
else:
var buf: array[0..59, char]
discard c_sprintf(buf, "%p", x)
return $buf
proc `$`(x: uint64): string = proc `$`(x: uint64): string =
if x == 0: if x == 0:

View file

@ -24,6 +24,9 @@ proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
if a == b: return 0 if a == b: return 0
if a == nil: return -1 if a == nil: return -1
if b == nil: return 1 if b == nil: return 1
when defined(nimNoArrayToCstringConversion):
return c_strcmp(addr a.data, addr b.data)
else:
return c_strcmp(a.data, b.data) return c_strcmp(a.data, b.data)
proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} = proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
@ -320,6 +323,9 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
proc add*(result: var string; x: float) = proc add*(result: var string; x: float) =
var buf: array[0..64, char] var buf: array[0..64, char]
when defined(nimNoArrayToCstringConversion):
var n: int = c_sprintf(addr buf, "%.16g", x)
else:
var n: int = c_sprintf(buf, "%.16g", x) var n: int = c_sprintf(buf, "%.16g", x)
var hasDot = false var hasDot = false
for i in 0..n-1: for i in 0..n-1:
@ -342,7 +348,10 @@ proc add*(result: var string; x: float) =
else: else:
result.add "inf" result.add "inf"
else: else:
result.add buf var i = 0
while buf[i] != '\0':
result.add buf[i]
inc i
proc nimFloatToStr(f: float): string {.compilerproc.} = proc nimFloatToStr(f: float): string {.compilerproc.} =
result = newStringOfCap(8) result = newStringOfCap(8)
@ -507,6 +516,9 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
t[ti-2] = ('0'.ord + abs_exponent mod 10).char; abs_exponent = abs_exponent div 10 t[ti-2] = ('0'.ord + abs_exponent mod 10).char; abs_exponent = abs_exponent div 10
t[ti-3] = ('0'.ord + abs_exponent mod 10).char t[ti-3] = ('0'.ord + abs_exponent mod 10).char
when defined(nimNoArrayToCstringConversion):
number = c_strtod(addr t, nil)
else:
number = c_strtod(t, nil) number = c_strtod(t, nil)
proc nimInt64ToStr(x: int64): string {.compilerRtl.} = proc nimInt64ToStr(x: int64): string {.compilerRtl.} =