From 6b8bd2bbb78bdc92a9ed264c9328b779600848aa Mon Sep 17 00:00:00 2001 From: Roger Shi Date: Tue, 8 Sep 2015 23:32:53 +0800 Subject: [PATCH 1/9] Fix issue #2245 --- compiler/aliases.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/aliases.nim b/compiler/aliases.nim index 3d3fc9a793..4b592ee607 100644 --- a/compiler/aliases.nim +++ b/compiler/aliases.nim @@ -146,7 +146,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult = # go down recursively; this is quite demanding: const Ix0Kinds = {nkDotExpr, nkBracketExpr, nkObjUpConv, nkObjDownConv, - nkCheckedFieldExpr} + nkCheckedFieldExpr, nkHiddenAddr} Ix1Kinds = {nkHiddenStdConv, nkHiddenSubConv, nkConv} DerefKinds = {nkHiddenDeref, nkDerefExpr} case b.kind From 8f9ce5285fe7923da2ebecda61f83dc056013e19 Mon Sep 17 00:00:00 2001 From: Roger Shi Date: Wed, 9 Sep 2015 11:40:13 +0800 Subject: [PATCH 2/9] fix #2367 --- lib/pure/json.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 540a1a8eb7..d98ed1042c 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1074,9 +1074,9 @@ when not defined(js): ## for nice error messages. var p: JsonParser p.open(s, filename) + defer: p.close() discard getTok(p) # read first token result = p.parseJson() - p.close() proc parseJson*(buffer: string): JsonNode = ## Parses JSON from `buffer`. From 58e1068f739a2115fe83db9bd6af34501eff1af4 Mon Sep 17 00:00:00 2001 From: Roger Shi Date: Wed, 9 Sep 2015 21:32:29 +0800 Subject: [PATCH 3/9] test case for #2245 --- tests/alias/talias.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/alias/talias.nim b/tests/alias/talias.nim index 6addc4704f..810ea20959 100644 --- a/tests/alias/talias.nim +++ b/tests/alias/talias.nim @@ -30,7 +30,7 @@ type c: char se: seq[TA] -proc p(param1, param2: TC): TC = +proc p(param1, param2: TC, param3: var TC): TC = var local: TC plocal: ptr TC @@ -43,6 +43,7 @@ proc p(param1, param2: TC): TC = plocal2[] ?<| local param1 ?<| param2 + local ?<| param3 local.arr[0] !<| param1 local.arr !<| param1 @@ -62,5 +63,5 @@ var a <| a a !<| b -discard p(x, x) +discard p(x, x, x) From 16fe63180f7192af5218df83878c89a6a5c554cd Mon Sep 17 00:00:00 2001 From: Roger Shi Date: Thu, 10 Sep 2015 15:16:01 +0800 Subject: [PATCH 4/9] test case for #2367 --- lib/pure/json.nim | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/pure/json.nim b/lib/pure/json.nim index d98ed1042c..abf6305f2c 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1203,6 +1203,17 @@ when isMainModule: testJson{["c", "d"]} = %true assert(testJson["c"]["d"].bval) + # make sure no memory leek when parsing invalid string + let startMemory = getOccupiedMem() + for i in 0 .. 10000: + try: + discard parseJson"""{ invalid""" + except: + discard + # memory diff should less than 2M + assert(abs(getOccupiedMem() - startMemory) < 2 * 1024 * 1024) + + # test `$` let stringified = $testJson let parsedAgain = parseJson(stringified) From b9df1323f7c117f0159e3afb26d5a3de83506f96 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Mon, 14 Sep 2015 01:42:46 +0200 Subject: [PATCH 5/9] Provide access to getsockname()/getpeername(). This patch implements procedures getLocalAddr() and getPeerAddr() that return the results of getsockname() and getpeername(), respectively, as pairs (string, Port) for both Socket and SockedHandle. --- lib/pure/net.nim | 8 +++++ lib/pure/rawsockets.nim | 66 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 141543c703..b7a40121fa 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -533,6 +533,14 @@ proc getSockOpt*(socket: Socket, opt: SOBool, level = SOL_SOCKET): bool {. var res = getSockOptInt(socket.fd, cint(level), toCInt(opt)) result = res != 0 +proc getLocalAddr*(socket: Socket): (string, Port) = + ## Get the socket's local address and port number + getLocalAddr(socket.fd, socket.domain) + +proc getPeerAddr*(socket: Socket): (string, Port) = + ## Get the socket's peer address and port number + getPeerAddr(socket.fd, socket.domain) + proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {. tags: [WriteIOEffect].} = ## Sets option ``opt`` to a boolean value specified by ``value``. diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index 7873e7226a..0a69b580e5 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -371,6 +371,72 @@ proc getSockName*(socket: SocketHandle): Port = raiseOSError(osLastError()) result = Port(rawsockets.ntohs(name.sin_port)) +proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = + ## returns the socket's local address and port number. + case domain + of AF_INET: + var name: Sockaddr_in + when useWinVersion: + name.sin_family = int16(ord(AF_INET)) + else: + name.sin_family = posix.AF_INET + var namelen = sizeof(name).SockLen + if getsockname(socket, cast[ptr SockAddr](addr(name)), + addr(namelen)) == -1'i32: + raiseOSError(osLastError()) + result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port))) + of AF_INET6: + var name: Sockaddr_in6 + when useWinVersion: + name.sin6_family = int16(ord(AF_INET6)) + else: + name.sin6_family = posix.AF_INET6 + var namelen = sizeof(name).SockLen + if getsockname(socket, cast[ptr SockAddr](addr(name)), + addr(namelen)) == -1'i32: + raiseOSError(osLastError()) + # Cannot use INET6_ADDRSTRLEN here, because it's a C define. + var buf: array[64, char] + if inet_ntop(name.sin6_family.cint, + addr name, buf.cstring, sizeof(buf).int32).isNil: + raiseOSError(osLastError()) + result = ($buf, Port(rawsockets.ntohs(name.sin6_port))) + else: + raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr") + +proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) = + ## returns the socket's peer address and port number. + case domain + of AF_INET: + var name: Sockaddr_in + when useWinVersion: + name.sin_family = int16(ord(AF_INET)) + else: + name.sin_family = posix.AF_INET + var namelen = sizeof(name).SockLen + if getpeername(socket, cast[ptr SockAddr](addr(name)), + addr(namelen)) == -1'i32: + raiseOSError(osLastError()) + result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port))) + of AF_INET6: + var name: Sockaddr_in6 + when useWinVersion: + name.sin6_family = int16(ord(AF_INET6)) + else: + name.sin6_family = posix.AF_INET6 + var namelen = sizeof(name).SockLen + if getpeername(socket, cast[ptr SockAddr](addr(name)), + addr(namelen)) == -1'i32: + raiseOSError(osLastError()) + # Cannot use INET6_ADDRSTRLEN here, because it's a C define. + var buf: array[64, char] + if inet_ntop(name.sin6_family.cint, + addr name, buf.cstring, sizeof(buf).int32).isNil: + raiseOSError(osLastError()) + result = ($buf, Port(rawsockets.ntohs(name.sin6_port))) + else: + raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr") + proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {. tags: [ReadIOEffect].} = ## getsockopt for integer options. From aeff57627b6165f3ba75d10f2aba5147fb686e8d Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Mon, 14 Sep 2015 14:25:40 +0300 Subject: [PATCH 6/9] Fixed JS gen for generic array types. --- compiler/jstypes.nim | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/jstypes.nim b/compiler/jstypes.nim index 8519383276..832d9996cd 100644 --- a/compiler/jstypes.nim +++ b/compiler/jstypes.nim @@ -116,8 +116,7 @@ proc genEnumInfo(p: PProc, typ: PType, name: Rope) = [name, genTypeInfo(p, typ.sons[0])]) proc genTypeInfo(p: PProc, typ: PType): Rope = - var t = typ - if t.kind == tyGenericInst: t = lastSon(t) + let t = typ.skipTypes({tyGenericInst}) result = "NTI$1" % [rope(t.id)] if containsOrIncl(p.g.typeInfoGenerated, t.id): return case t.kind @@ -141,7 +140,7 @@ proc genTypeInfo(p: PProc, typ: PType): Rope = [result, rope(ord(t.kind))] prepend(p.g.typeInfo, s) addf(p.g.typeInfo, "$1.base = $2;$n", - [result, genTypeInfo(p, typ.sons[1])]) + [result, genTypeInfo(p, t.sons[1])]) of tyEnum: genEnumInfo(p, t, result) of tyObject: genObjectInfo(p, t, result) of tyTuple: genTupleInfo(p, t, result) From 6ac2ba122366bdd320b1ab6ce7a6ca3cbb362800 Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Mon, 14 Sep 2015 20:32:09 +0300 Subject: [PATCH 7/9] Uint64 to string in pure nim. array[char] to string fixed in vm. --- compiler/vm.nim | 13 ++++++++++++- lib/system/repr.nim | 20 ++++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index 0db287c6aa..4dd3b5232d 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -320,8 +320,19 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool = dest.node.strVal = if src.intVal == 0: "false" else: "true" of tyFloat..tyFloat128: dest.node.strVal = $src.floatVal - of tyString, tyCString: + of tyString: dest.node.strVal = src.node.strVal + of tyCString: + if src.node.kind == nkBracket: + # Array of chars + var strVal = "" + for son in src.node.sons: + let c = char(son.intVal) + if c == '\0': break + strVal.add(c) + dest.node.strVal = strVal + else: + dest.node.strVal = src.node.strVal of tyChar: dest.node.strVal = $chr(src.intVal) else: diff --git a/lib/system/repr.nim b/lib/system/repr.nim index b4188527fe..1f81a08135 100644 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -21,9 +21,22 @@ proc reprPointer(x: pointer): string {.compilerproc.} = return $buf proc `$`(x: uint64): string = - var buf: array [0..59, char] - discard c_sprintf(buf, "%llu", x) - return $buf + if x == 0: + result = "0" + else: + var buf: array [60, char] + var i = 0 + var n = x + while n != 0: + let nn = n div 10'u64 + buf[i] = char(n - 10'u64 * nn + ord('0')) + inc i + n = nn + + let half = i div 2 + # Reverse + for t in 0 .. < half: swap(buf[t], buf[i-t-1]) + result = $buf proc reprStrAux(result: var string, s: string) = if cast[pointer](s) == nil: @@ -294,4 +307,3 @@ when not defined(useNimRtl): reprAux(result, addr(p), typ, cl) add result, "\n" deinitReprClosure(cl) - From ac16b151bad9d4d4bae6e6ac35c52b2c5173ec7a Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Mon, 14 Sep 2015 22:39:12 +0100 Subject: [PATCH 8/9] Added more bugfixes to news.txt --- web/news.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/web/news.txt b/web/news.txt index 4c7f23cf6c..1a312f67b3 100644 --- a/web/news.txt +++ b/web/news.txt @@ -306,6 +306,26 @@ xist" (`#2183 `_) - Fixed "gctest segfaults with --gc:markandsweep on x86_64" (`#2305 `_) + - Fixed "Coroutine changes break compilation on unsupported architectures" + (`#3245 `_) + - Fixed "Bugfix: Windows 32bit TinyCC support issue fixed" + (`#3237 `_) + - Fixed "db_mysql getValue() followed by exec() causing error" + (`#3220 `_) + - Fixed "xmltree.newEntity creates xnCData instead of xnEntity" + (`#3282 `_) + - Fixed "Methods and modules don't work together" + (`#2590 `_) + - Fixed "String slicing not working in the vm" + (`#3300 `_) + - Fixed "internal error: evalOp(mTypeOf)" + (`#3230 `_) + - Fixed "#! source code prefix collides with Unix Shebang" + (`#2559 `_) + - Fixed "wrong codegen for constant object" + (`#3195 `_) + - Fixed "Doc comments inside procs with implicit returns don't work" + (`#1528 `_) 2015-05-04 Version 0.11.2 released From 4da5e474148db9298ec0d730046544278d7e6827 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Tue, 15 Sep 2015 10:37:16 +0100 Subject: [PATCH 9/9] Implements getPeerAddr/getPeerName on Windows and adds IDX. --- lib/pure/net.nim | 8 ++++++-- lib/pure/rawsockets.nim | 4 ++++ lib/windows/winlean.nim | 8 +++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index b7a40121fa..0ce5b4d25d 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -534,11 +534,15 @@ proc getSockOpt*(socket: Socket, opt: SOBool, level = SOL_SOCKET): bool {. result = res != 0 proc getLocalAddr*(socket: Socket): (string, Port) = - ## Get the socket's local address and port number + ## Get the socket's local address and port number. + ## + ## This is high-level interface for `getsockname`:idx:. getLocalAddr(socket.fd, socket.domain) proc getPeerAddr*(socket: Socket): (string, Port) = - ## Get the socket's peer address and port number + ## Get the socket's peer address and port number. + ## + ## This is high-level interface for `getpeername`:idx:. getPeerAddr(socket.fd, socket.domain) proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {. diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index 0a69b580e5..f5860ef282 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -373,6 +373,8 @@ proc getSockName*(socket: SocketHandle): Port = proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = ## returns the socket's local address and port number. + ## + ## Similar to POSIX's `getsockname`:idx:. case domain of AF_INET: var name: Sockaddr_in @@ -406,6 +408,8 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) = ## returns the socket's peer address and port number. + ## + ## Similar to POSIX's `getpeername`:idx: case domain of AF_INET: var name: Sockaddr_in diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 24015dd3a6..84dac6d798 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -409,7 +409,7 @@ type bytes*: array[0..15, char] Sockaddr_in6* {.importc: "SOCKADDR_IN6", - header: "winsock2.h".} = object + header: "ws2tcpip.h".} = object sin6_family*: int16 sin6_port*: int16 # unsigned sin6_flowinfo*: int32 # unsigned @@ -511,6 +511,9 @@ proc connect*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {. proc getsockname*(s: SocketHandle, name: ptr SockAddr, namelen: ptr SockLen): cint {. stdcall, importc: "getsockname", dynlib: ws2dll.} +proc getpeername*(s: SocketHandle, name: ptr SockAddr, + namelen: ptr SockLen): cint {. + stdcall, importc, dynlib: ws2dll.} proc getsockopt*(s: SocketHandle, level, optname: cint, optval: pointer, optlen: ptr SockLen): cint {. stdcall, importc: "getsockopt", dynlib: ws2dll.} @@ -572,6 +575,9 @@ proc freeaddrinfo*(ai: ptr AddrInfo) {. proc inet_ntoa*(i: InAddr): cstring {. stdcall, importc, dynlib: ws2dll.} +proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring, + stringBufSize: int32): cstring {.stdcall, importc, dynlib: ws2dll.} + const MAXIMUM_WAIT_OBJECTS* = 0x00000040