diff options
author | Araq <rumpf_a@web.de> | 2019-09-02 10:27:35 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2019-09-02 10:27:35 +0200 |
commit | e76568764698be7561501c4809e996f3f1608f74 (patch) | |
tree | 04700154851f27af457836751a8425882b50e97d /lib | |
parent | e6ec88d4c39c458404061198b2a2f6b86c2caeaf (diff) | |
parent | ad82e65387f39970b0f12cbcb12d8b382236f3da (diff) | |
download | Nim-e76568764698be7561501c4809e996f3f1608f74.tar.gz |
Merge branch 'devel' into uint-range-checks
Diffstat (limited to 'lib')
-rw-r--r-- | lib/core/locks.nim | 4 | ||||
-rw-r--r-- | lib/core/seqs.nim | 2 | ||||
-rw-r--r-- | lib/core/strs.nim | 49 | ||||
-rw-r--r-- | lib/impure/rdstdin.nim | 40 | ||||
-rw-r--r-- | lib/nimbase.h | 12 | ||||
-rw-r--r-- | lib/nimhcr.nim | 3 | ||||
-rw-r--r-- | lib/pure/complex.nim | 2 | ||||
-rw-r--r-- | lib/pure/hashes.nim | 196 | ||||
-rw-r--r-- | lib/pure/httpclient.nim | 132 | ||||
-rw-r--r-- | lib/pure/json.nim | 17 | ||||
-rw-r--r-- | lib/pure/lexbase.nim | 7 | ||||
-rw-r--r-- | lib/pure/net.nim | 6 | ||||
-rw-r--r-- | lib/pure/unicode.nim | 7 | ||||
-rw-r--r-- | lib/system.nim | 92 | ||||
-rw-r--r-- | lib/system/alloc.nim | 12 | ||||
-rw-r--r-- | lib/system/ansi_c.nim | 2 | ||||
-rw-r--r-- | lib/system/assertions.nim | 10 | ||||
-rw-r--r-- | lib/system/debugger.nim | 303 | ||||
-rw-r--r-- | lib/system/endb.nim | 579 | ||||
-rw-r--r-- | lib/system/excpt.nim | 12 | ||||
-rw-r--r-- | lib/system/gc_ms.nim | 2 | ||||
-rw-r--r-- | lib/system/iterators.nim | 9 |
22 files changed, 250 insertions, 1248 deletions
diff --git a/lib/core/locks.nim b/lib/core/locks.nim index d6d579ba0..0143957ce 100644 --- a/lib/core/locks.nim +++ b/lib/core/locks.nim @@ -60,11 +60,11 @@ template withLock*(a: Lock, body: untyped) = ## Acquires the given lock, executes the statements in body and ## releases the lock after the statements finish executing. mixin acquire, release - a.acquire() + acquire(a) {.locks: [a].}: try: body finally: - a.release() + release(a) {.pop.} diff --git a/lib/core/seqs.nim b/lib/core/seqs.nim index 2892e4d8a..01839a4de 100644 --- a/lib/core/seqs.nim +++ b/lib/core/seqs.nim @@ -202,7 +202,7 @@ when false: assert i < x.len x.data[i] = y - proc `@`*[T](elems: openArray[T]): NimSeqV2[T] = + proc `@`*[T](elems: sink openArray[T]): NimSeqV2[T] = result.cap = elems.len result.len = elems.len result.data = cast[type(result.data)](alloc(result.cap * sizeof(T))) diff --git a/lib/core/strs.nim b/lib/core/strs.nim index 92c39331f..3b7a46ff1 100644 --- a/lib/core/strs.nim +++ b/lib/core/strs.nim @@ -9,20 +9,6 @@ ## Default new string implementation used by Nim's core. -when false: - # these are to be implemented or changed in the code generator. - - #proc rawNewStringNoInit(space: int): NimString {.compilerproc.} - # seems to be unused. - proc copyDeepString(src: NimString): NimString {.inline.} - # ----------------- sequences ---------------------------------------------- - - proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerproc.} - proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {. - compilerRtl.} - proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} - proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} - import allocators type @@ -45,41 +31,6 @@ template frees(s) = if not isLiteral(s): s.p.allocator.dealloc(s.p.allocator, s.p, contentSize(s.p.cap)) -when not defined(nimV2): - proc `=destroy`(s: var string) = - var a = cast[ptr NimStringV2](addr s) - frees(a) - a.len = 0 - a.p = nil - - proc `=sink`(x: var string, y: string) = - var a = cast[ptr NimStringV2](addr x) - var b = cast[ptr NimStringV2](unsafeAddr y) - # we hope this is optimized away for not yet alive objects: - if unlikely(a.p == b.p): return - frees(a) - a.len = b.len - a.p = b.p - - proc `=`(x: var string, y: string) = - var a = cast[ptr NimStringV2](addr x) - var b = cast[ptr NimStringV2](unsafeAddr y) - if unlikely(a.p == b.p): return - frees(a) - a.len = b.len - if isLiteral(b): - # we can shallow copy literals: - a.p = b.p - else: - let allocator = if a.p != nil and a.p.allocator != nil: a.p.allocator else: getLocalAllocator() - # we have to allocate the 'cap' here, consider - # 'let y = newStringOfCap(); var x = y' - # on the other hand... These get turned into moves now. - a.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(b.len))) - a.p.allocator = allocator - a.p.cap = b.len - copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1) - proc resize(old: int): int {.inline.} = if old <= 0: result = 4 elif old < 65536: result = old * 2 diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim index 742db0cc6..b78c0d8cf 100644 --- a/lib/impure/rdstdin.nim +++ b/lib/impure/rdstdin.nim @@ -33,46 +33,6 @@ when defined(Windows): stdout.write(prompt) result = readLine(stdin, line) - import winlean - - const - VK_SHIFT* = 16 - VK_CONTROL* = 17 - VK_MENU* = 18 - KEY_EVENT* = 1 - - type - KEY_EVENT_RECORD = object - bKeyDown: WINBOOL - wRepeatCount: uint16 - wVirtualKeyCode: uint16 - wVirtualScanCode: uint16 - unicodeChar: uint16 - dwControlKeyState: uint32 - INPUT_RECORD = object - eventType*: int16 - reserved*: int16 - event*: KEY_EVENT_RECORD - safetyBuffer: array[0..5, DWORD] - - proc readConsoleInputW*(hConsoleInput: Handle, lpBuffer: var INPUT_RECORD, - nLength: uint32, - lpNumberOfEventsRead: var uint32): WINBOOL{. - stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".} - - proc getch(): uint16 = - let hStdin = getStdHandle(STD_INPUT_HANDLE) - var - irInputRecord: INPUT_RECORD - dwEventsRead: uint32 - - while readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead) != 0: - if irInputRecord.eventType == KEY_EVENT and - irInputRecord.event.wVirtualKeyCode notin {VK_SHIFT, VK_MENU, VK_CONTROL}: - result = irInputRecord.event.unicodeChar - discard readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead) - return result - elif defined(genode): proc readLineFromStdin*(prompt: string): TaintedString {. tags: [ReadIOEffect, WriteIOEffect].} = diff --git a/lib/nimbase.h b/lib/nimbase.h index a4bde0bd4..eadc34f66 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -374,18 +374,6 @@ typedef char* NCSTRING; # define NIM_IMAN 0 #endif -static N_INLINE(NI, float64ToInt32)(double x) { - /* nowadays no hack necessary anymore */ - return x >= 0 ? (NI)(x+0.5) : (NI)(x-0.5); -} - -static N_INLINE(NI32, float32ToInt32)(float x) { - /* nowadays no hack necessary anymore */ - return x >= 0 ? (NI32)(x+0.5) : (NI32)(x-0.5); -} - -#define float64ToInt64(x) ((NI64) (x)) - #define NIM_STRLIT_FLAG ((NU)(1) << ((NIM_INTBITS) - 2)) /* This has to be the same as system.strlitFlag! */ #define STRING_LITERAL(name, str, length) \ diff --git a/lib/nimhcr.nim b/lib/nimhcr.nim index 79f3fd350..396747527 100644 --- a/lib/nimhcr.nim +++ b/lib/nimhcr.nim @@ -111,6 +111,7 @@ # - ARM support for the trampolines # - investigate: # - soon the system module might be importing other modules - the init order...? +# (revert https://github.com/nim-lang/Nim/pull/11971 when working on this) # - rethink the closure iterators # - ability to keep old versions of dynamic libraries alive # - because of async server code @@ -421,7 +422,7 @@ when defined(createNimHcr): modules.add(name, newModuleDesc()) let copiedName = name & ".copy." & dllExt - copyFile(name, copiedName) + copyFileWithPermissions(name, copiedName) let lib = loadLib(copiedName) assert lib != nil diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim index 442bf62db..7c669cd6d 100644 --- a/lib/pure/complex.nim +++ b/lib/pure/complex.nim @@ -372,7 +372,7 @@ when isMainModule: doAssert((a+b) == z) doAssert((a+b) =~ 0.0) doAssert((a/b) == m1) - doAssert((1.0/a) == complex(0.2, -0.4)) + doAssert((1.0/a) =~ complex(0.2, -0.4)) doAssert((a*b) == complex(3.0, -4.0)) doAssert(10.0*a == tt) doAssert(a*10.0 == tt) diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 6af515609..c1338376e 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -49,9 +49,6 @@ type ## always have a size of a power of two and can use the ``and`` ## operator instead of ``mod`` for truncation of the hash value. -const - IntSize = sizeof(int) - proc `!&`*(h: Hash, val: int): Hash {.inline.} = ## Mixes a hash value `h` with `val` to produce a new hash value. ## @@ -108,13 +105,12 @@ proc hash*(x: pointer): Hash {.inline.} = else: result = cast[Hash](cast[uint](x) shr 3) # skip the alignment -when not defined(booting): - proc hash*[T: proc](x: T): Hash {.inline.} = - ## Efficient hashing of proc vars. Closures are supported too. - when T is "closure": - result = hash(rawProc(x)) !& hash(rawEnv(x)) - else: - result = hash(pointer(x)) +proc hash*[T: proc](x: T): Hash {.inline.} = + ## Efficient hashing of proc vars. Closures are supported too. + when T is "closure": + result = hash(rawProc(x)) !& hash(rawEnv(x)) + else: + result = hash(pointer(x)) proc hash*(x: int): Hash {.inline.} = ## Efficient hashing of integers. @@ -151,27 +147,87 @@ proc hash*(x: float): Hash {.inline.} = proc hash*[A](x: openArray[A]): Hash proc hash*[A](x: set[A]): Hash -template bytewiseHashing(result: Hash, x: typed, start, stop: int) = - for i in start .. stop: - result = result !& hash(x[i]) - result = !$result -template hashImpl(result: Hash, x: typed, start, stop: int) = +when defined(JS): + proc imul(a, b: uint32): uint32 = + # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul + let mask = 0xffff'u32 + var + aHi = (a shr 16) and mask + aLo = a and mask + bHi = (b shr 16) and mask + bLo = b and mask + result = (aLo * bLo) + (aHi * bLo + aLo * bHi) shl 16 +else: + template imul(a, b: uint32): untyped = a * b + +proc rotl32(x: uint32, r: int): uint32 {.inline.} = + (x shl r) or (x shr (32 - r)) + +proc murmurHash(x: openArray[byte]): Hash = + # https://github.com/PeterScott/murmur3/blob/master/murmur3.c + const + c1 = 0xcc9e2d51'u32 + c2 = 0x1b873593'u32 + n1 = 0xe6546b64'u32 + m1 = 0x85ebca6b'u32 + m2 = 0xc2b2ae35'u32 let - elementSize = sizeof(x[start]) - stepSize = IntSize div elementSize - var i = start - while i <= stop+1 - stepSize: - var n = 0 - when nimvm: - # we cannot cast in VM, so we do it manually - for j in countdown(stepSize-1, 0): - n = (n shl (8*elementSize)) or ord(x[i+j]) + size = len(x) + stepSize = 4 # 32-bit + n = size div stepSize + var + h1: uint32 + i = 0 + + # body + while i < n * stepSize: + var k1: uint32 + when defined(js): + var j = stepSize + while j > 0: + dec j + k1 = (k1 shl 8) or (ord(x[i+j])).uint32 else: - n = cast[ptr Hash](unsafeAddr x[i])[] - result = result !& n - i += stepSize - bytewiseHashing(result, x, i, stop) # hash the remaining elements and finish + k1 = cast[ptr uint32](unsafeAddr x[i])[] + inc i, stepSize + + k1 = imul(k1, c1) + k1 = rotl32(k1, 15) + k1 = imul(k1, c2) + + h1 = h1 xor k1 + h1 = rotl32(h1, 13) + h1 = h1*5 + n1 + + # tail + var k1: uint32 + var rem = size mod stepSize + while rem > 0: + dec rem + k1 = (k1 shl 8) or (ord(x[i+rem])).uint32 + k1 = imul(k1, c1) + k1 = rotl32(k1, 15) + k1 = imul(k1, c2) + h1 = h1 xor k1 + + # finalization + h1 = h1 xor size.uint32 + h1 = h1 xor (h1 shr 16) + h1 = imul(h1, m1) + h1 = h1 xor (h1 shr 13) + h1 = imul(h1, m2) + h1 = h1 xor (h1 shr 16) + return cast[Hash](h1) + +proc hashVmImpl(x: string, sPos, ePos: int): Hash = + doAssert false, "implementation override in compiler/vmops.nim" + +proc hashVmImplChar(x: openArray[char], sPos, ePos: int): Hash = + doAssert false, "implementation override in compiler/vmops.nim" + +proc hashVmImplByte(x: openArray[byte], sPos, ePos: int): Hash = + doAssert false, "implementation override in compiler/vmops.nim" proc hash*(x: string): Hash = ## Efficient hashing of strings. @@ -182,7 +238,16 @@ proc hash*(x: string): Hash = runnableExamples: doAssert hash("abracadabra") != hash("AbracadabrA") - hashImpl(result, x, 0, high(x)) + when not defined(nimToOpenArrayCString): + result = 0 + for c in x: + result = result !& ord(c) + result = !$result + else: + when nimvm: + result = hashVmImpl(x, 0, high(x)) + else: + result = murmurHash(toOpenArrayByte(x, 0, high(x))) proc hash*(x: cstring): Hash = ## Efficient hashing of null-terminated strings. @@ -191,7 +256,19 @@ proc hash*(x: cstring): Hash = doAssert hash(cstring"AbracadabrA") == hash("AbracadabrA") doAssert hash(cstring"abracadabra") != hash(cstring"AbracadabrA") - hashImpl(result, x, 0, high(x)) + when not defined(nimToOpenArrayCString): + result = 0 + var i = 0 + while x[i] != '\0': + result = result !& ord(x[i]) + inc i + result = !$result + else: + when not defined(JS) and defined(nimToOpenArrayCString): + murmurHash(toOpenArrayByte(x, 0, x.high)) + else: + let xx = $x + murmurHash(toOpenArrayByte(xx, 0, high(xx))) proc hash*(sBuf: string, sPos, ePos: int): Hash = ## Efficient hashing of a string buffer, from starting @@ -202,7 +279,13 @@ proc hash*(sBuf: string, sPos, ePos: int): Hash = var a = "abracadabra" doAssert hash(a, 0, 3) == hash(a, 7, 10) - hashImpl(result, sBuf, sPos, ePos) + when not defined(nimToOpenArrayCString): + result = 0 + for i in sPos..ePos: + result = result !& ord(sBuf[i]) + result = !$result + else: + murmurHash(toOpenArrayByte(sBuf, sPos, ePos)) proc hashIgnoreStyle*(x: string): Hash = ## Efficient hashing of strings; style is ignored. @@ -300,12 +383,20 @@ proc hash*[T: tuple](x: T): Hash = result = result !& hash(f) result = !$result + proc hash*[A](x: openArray[A]): Hash = ## Efficient hashing of arrays and sequences. - when A is char|SomeInteger: - hashImpl(result, x, 0, x.high) + when A is byte: + result = murmurHash(x) + elif A is char: + when nimvm: + result = hashVmImplChar(x, 0, x.high) + else: + result = murmurHash(toOpenArrayByte(x, 0, x.high)) else: - bytewiseHashing(result, x, 0, x.high) + for a in x: + result = result !& hash(a) + result = !$result proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash = ## Efficient hashing of portions of arrays and sequences, from starting @@ -316,10 +407,20 @@ proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash = let a = [1, 2, 5, 1, 2, 6] doAssert hash(a, 0, 1) == hash(a, 3, 4) - when A is char|SomeInteger: - hashImpl(result, aBuf, sPos, ePos) + when A is byte: + when nimvm: + result = hashVmImplByte(aBuf, sPos, ePos) + else: + result = murmurHash(toOpenArray(aBuf, sPos, ePos)) + elif A is char: + when nimvm: + result = hashVmImplChar(aBuf, sPos, ePos) + else: + result = murmurHash(toOpenArrayByte(aBuf, sPos, ePos)) else: - bytewiseHashing(result, aBuf, sPos, ePos) + for i in sPos .. ePos: + result = result !& hash(aBuf[i]) + result = !$result proc hash*[A](x: set[A]): Hash = ## Efficient hashing of sets. @@ -334,11 +435,15 @@ when isMainModule: a = "" b = newSeq[char]() c = newSeq[int]() + d = cstring"" + e = "abcd" doAssert hash(a) == 0 doAssert hash(b) == 0 doAssert hash(c) == 0 + doAssert hash(d) == 0 doAssert hashIgnoreCase(a) == 0 doAssert hashIgnoreStyle(a) == 0 + doAssert hash(e, 3, 2) == 0 block sameButDifferent: doAssert hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) doAssert hash("aa bb aaaa1234") == hash(cstring"aa bb aaaa1234") @@ -346,14 +451,14 @@ when isMainModule: doAssert hashIgnoreStyle("aa_bb_AAaa1234") == hashIgnoreCase("aaBBAAAa1234") block smallSize: # no multibyte hashing let - xx = @['H','e','l','l','o'] - ii = @[72'i8, 101, 108, 108, 111] - ss = "Hello" + xx = @['H','i'] + ii = @[72'u8, 105] + ss = "Hi" doAssert hash(xx) == hash(ii) doAssert hash(xx) == hash(ss) doAssert hash(xx) == hash(xx, 0, xx.high) doAssert hash(ss) == hash(ss, 0, ss.high) - block largeSize: # longer than 8 characters, should trigger multibyte hashing + block largeSize: # longer than 4 characters let xx = @['H','e','l','l','o'] xxl = @['H','e','l','l','o','w','e','e','n','s'] @@ -362,9 +467,6 @@ when isMainModule: doAssert hash(xxl) == hash(xxl, 0, xxl.high) doAssert hash(ssl) == hash(ssl, 0, ssl.high) doAssert hash(xx) == hash(xxl, 0, 4) - block misc: - let - a = [1'u8, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4] - b = [1'i8, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4] - doAssert hash(a) == hash(b) - doAssert hash(a, 2, 5) == hash(b, 2, 5) + doAssert hash(xx) == hash(ssl, 0, 4) + doAssert hash(xx, 0, 3) == hash(xxl, 0, 3) + doAssert hash(xx, 0, 3) == hash(ssl, 0, 3) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 5a98c5ede..f89a928ab 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -1,7 +1,7 @@ # # # Nim's Runtime Library -# (c) Copyright 2016 Dominik Picheta, Andreas Rumpf +# (c) Copyright 2019 Nim Contributors # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -175,7 +175,7 @@ ## let client = newHttpClient(maxRedirects = 0) ## -import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, +import net, strutils, uri, parseutils, base64, os, mimetypes, math, random, httpcore, times, tables, streams, std/monotimes import asyncnet, asyncdispatch, asyncfile import nativesockets @@ -276,134 +276,6 @@ proc fileError(msg: string) = e.msg = msg raise e -proc parseChunks(s: Socket, timeout: int): string = - result = "" - var ri = 0 - while true: - var chunkSizeStr = "" - var chunkSize = 0 - s.readLine(chunkSizeStr, timeout) - var i = 0 - if chunkSizeStr == "": - httpError("Server terminated connection prematurely") - while i < chunkSizeStr.len: - case chunkSizeStr[i] - of '0'..'9': - chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('0')) - of 'a'..'f': - chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('a') + 10) - of 'A'..'F': - chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('A') + 10) - of ';': - # http://tools.ietf.org/html/rfc2616#section-3.6.1 - # We don't care about chunk-extensions. - break - else: - httpError("Invalid chunk size: " & chunkSizeStr) - inc(i) - if chunkSize <= 0: - s.skip(2, timeout) # Skip \c\L - break - result.setLen(ri+chunkSize) - var bytesRead = 0 - while bytesRead != chunkSize: - let ret = recv(s, addr(result[ri]), chunkSize-bytesRead, timeout) - ri += ret - bytesRead += ret - s.skip(2, timeout) # Skip \c\L - # Trailer headers will only be sent if the request specifies that we want - # them: http://tools.ietf.org/html/rfc2616#section-3.6.1 - -proc parseBody(s: Socket, headers: HttpHeaders, httpVersion: string, timeout: int): string = - result = "" - if headers.getOrDefault"Transfer-Encoding" == "chunked": - result = parseChunks(s, timeout) - else: - # -REGION- Content-Length - # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3 - var contentLengthHeader = headers.getOrDefault"Content-Length" - if contentLengthHeader != "": - var length = contentLengthHeader.parseInt() - if length > 0: - result = newString(length) - var received = 0 - while true: - if received >= length: break - let r = s.recv(addr(result[received]), length-received, timeout) - if r == 0: break - received += r - if received != length: - httpError("Got invalid content length. Expected: " & $length & - " got: " & $received) - else: - # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO - - # -REGION- Connection: Close - # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5 - let implicitConnectionClose = - httpVersion == "1.0" or - # This doesn't match the HTTP spec, but it fixes issues for non-conforming servers. - (httpVersion == "1.1" and headers.getOrDefault"Connection" == "") - if headers.getOrDefault"Connection" == "close" or implicitConnectionClose: - var buf = "" - while true: - buf = newString(4000) - let r = s.recv(addr(buf[0]), 4000, timeout) - if r == 0: break - buf.setLen(r) - result.add(buf) - -proc parseResponse(s: Socket, getBody: bool, timeout: int): Response = - new result - var parsedStatus = false - var linei = 0 - var fullyRead = false - var line = "" - result.headers = newHttpHeaders() - while true: - line = "" - linei = 0 - s.readLine(line, timeout) - if line == "": break # We've been disconnected. - if line == "\c\L": - fullyRead = true - break - if not parsedStatus: - # Parse HTTP version info and status code. - var le = skipIgnoreCase(line, "HTTP/", linei) - if le <= 0: httpError("invalid http version") - inc(linei, le) - le = skipIgnoreCase(line, "1.1", linei) - if le > 0: result.version = "1.1" - else: - le = skipIgnoreCase(line, "1.0", linei) - if le <= 0: httpError("unsupported http version") - result.version = "1.0" - inc(linei, le) - # Status code - linei.inc skipWhitespace(line, linei) - result.status = line[linei .. ^1] - parsedStatus = true - else: - # Parse headers - var name = "" - var le = parseUntil(line, name, ':', linei) - if le <= 0: httpError("invalid headers") - inc(linei, le) - if line[linei] != ':': httpError("invalid headers") - inc(linei) # Skip : - - result.headers.add(name, line[linei.. ^1].strip()) - # Ensure the server isn't trying to DoS us. - if result.headers.len > headerLimit: - httpError("too many headers") - - if not fullyRead: - httpError("Connection was closed before full request has been made") - if getBody: - result.body = parseBody(s, result.headers, result.version, timeout) - else: - result.body = "" when not defined(ssl): type SSLContext = ref object diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 1ef08f547..23b23b4a4 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1369,11 +1369,20 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode = for `forLoopI` in 0 ..< `jsonNode`.len: list[`forLoopI`] =`constructorNode`; list ) - + of "tuple": + let typeNode = getTypeImpl(typeSym) + result = createConstructor(typeNode, jsonNode) else: - # Generic type. + # Generic type or some `seq[T]` alias let obj = getType(typeSym) - result = processType(typeSym, obj, jsonNode, false) + case obj.kind + of nnkBracketExpr: + # probably a `seq[T]` alias + let typeNode = getTypeImpl(typeSym) + result = createConstructor(typeNode, jsonNode) + else: + # generic type + result = processType(typeSym, obj, jsonNode, false) of nnkSym: # Handle JsonNode. if ($typeSym).cmpIgnoreStyle("jsonnode") == 0: @@ -1385,7 +1394,7 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode = if typeNode.typeKind == ntyDistinct: result = createConstructor(typeNode, jsonNode) elif obj.kind == nnkBracketExpr: - # When `Sym "Foo"` turns out to be a `ref object`. + # When `Sym "Foo"` turns out to be a `ref object` or `tuple` result = createConstructor(obj, jsonNode) else: result = processType(typeSym, obj, jsonNode, false) diff --git a/lib/pure/lexbase.nim b/lib/pure/lexbase.nim index 11ec45a37..0ef4a147a 100644 --- a/lib/pure/lexbase.nim +++ b/lib/pure/lexbase.nim @@ -100,7 +100,7 @@ proc fillBaseLexer(L: var BaseLexer, pos: int): int = result = 0 proc handleCR*(L: var BaseLexer, pos: int): int = - ## Call this if you scanned over '\c' in the buffer; it returns the the + ## Call this if you scanned over '\c' in the buffer; it returns the ## position to continue the scanning from. `pos` must be the position ## of the '\c'. assert(L.buf[pos] == '\c') @@ -111,7 +111,7 @@ proc handleCR*(L: var BaseLexer, pos: int): int = L.lineStart = result proc handleLF*(L: var BaseLexer, pos: int): int = - ## Call this if you scanned over '\L' in the buffer; it returns the the + ## Call this if you scanned over '\L' in the buffer; it returns the ## position to continue the scanning from. `pos` must be the position ## of the '\L'. assert(L.buf[pos] == '\L') @@ -120,7 +120,8 @@ proc handleLF*(L: var BaseLexer, pos: int): int = L.lineStart = result proc handleRefillChar*(L: var BaseLexer, pos: int): int = - ## To be documented. + ## Call this if a terminator character other than a new line is scanned + ## at `pos`; it returns the position to continue the scanning from. assert(L.buf[pos] in L.refillChars) result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result; diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 8c4229c88..c337680f1 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -530,8 +530,12 @@ when defineSsl: ## ## The last two parameters specify the certificate file path and the key file ## path, a server socket will most likely not work without these. + ## ## Certificates can be generated using the following command: - ## ``openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem``. + ## - ``openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout mykey.pem -out mycert.pem`` + ## or using ECDSA: + ## - ``openssl ecparam -out mykey.pem -name secp256k1 -genkey`` + ## - ``openssl req -new -key mykey.pem -x509 -nodes -days 365 -out mycert.pem`` var newCTX: SSL_CTX case protVersion of protSSLv23: diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 35c364221..30d805334 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -31,11 +31,6 @@ type ## Type that can hold a single Unicode code point. ## ## A Rune may be composed with other Runes to a character on the screen. - Rune16* = distinct int16 ## \ - ## Type that can hold a single UTF-16 encoded character. - ## - ## A single Rune16 may not be enough to hold an arbitrary Unicode code point. - template ones(n: untyped): untyped = ((1 shl n)-1) @@ -388,7 +383,7 @@ proc runeStrAtPos*(s: string, pos: Natural): string = ## * `runeAtPos proc <#runeAtPos,string,int>`_ ## * `fastRuneAt template <#fastRuneAt.t,string,int,untyped>`_ let o = runeOffset(s, pos) - s[o.. (o+runeLenAt(s, o)-1)] + s[o .. (o+runeLenAt(s, o)-1)] proc runeSubStr*(s: string, pos: int, len: int = int.high): string = ## Returns the UTF-8 substring starting at code point ``pos`` diff --git a/lib/system.nim b/lib/system.nim index 61c9ee57f..9605049fc 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1132,57 +1132,57 @@ proc chr*(u: range[0..255]): char {.magic: "Chr", noSideEffect.} # built-in operators when defined(nimNoZeroExtendMagic): - proc ze*(x: int8): int = + proc ze*(x: int8): int {.deprecated.} = ## zero extends a smaller integer type to ``int``. This treats `x` as ## unsigned. ## **Deprecated since version 0.19.9**: Use unsigned integers instead. cast[int](uint(cast[uint8](x))) - proc ze*(x: int16): int = + proc ze*(x: int16): int {.deprecated.} = ## zero extends a smaller integer type to ``int``. This treats `x` as ## unsigned. ## **Deprecated since version 0.19.9**: Use unsigned integers instead. cast[int](uint(cast[uint16](x))) - proc ze64*(x: int8): int64 = + proc ze64*(x: int8): int64 {.deprecated.} = ## zero extends a smaller integer type to ``int64``. This treats `x` as ## unsigned. ## **Deprecated since version 0.19.9**: Use unsigned integers instead. cast[int64](uint64(cast[uint8](x))) - proc ze64*(x: int16): int64 = + proc ze64*(x: int16): int64 {.deprecated.} = ## zero extends a smaller integer type to ``int64``. This treats `x` as ## unsigned. ## **Deprecated since version 0.19.9**: Use unsigned integers instead. cast[int64](uint64(cast[uint16](x))) - proc ze64*(x: int32): int64 = + proc ze64*(x: int32): int64 {.deprecated.} = ## zero extends a smaller integer type to ``int64``. This treats `x` as ## unsigned. ## **Deprecated since version 0.19.9**: Use unsigned integers instead. cast[int64](uint64(cast[uint32](x))) - proc ze64*(x: int): int64 = + proc ze64*(x: int): int64 {.deprecated.} = ## zero extends a smaller integer type to ``int64``. This treats `x` as ## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``. ## (This is the case on 64 bit processors.) ## **Deprecated since version 0.19.9**: Use unsigned integers instead. cast[int64](uint64(cast[uint](x))) - proc toU8*(x: int): int8 = + proc toU8*(x: int): int8 {.deprecated.} = ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits ## from `x`. ## **Deprecated since version 0.19.9**: Use unsigned integers instead. cast[int8](x) - proc toU16*(x: int): int16 = + proc toU16*(x: int): int16 {.deprecated.} = ## treats `x` as unsigned and converts it to an ``int16`` by taking the last ## 16 bits from `x`. ## **Deprecated since version 0.19.9**: Use unsigned integers instead. cast[int16](x) - proc toU32*(x: int64): int32 = + proc toU32*(x: int64): int32 {.deprecated.} = ## treats `x` as unsigned and converts it to an ``int32`` by taking the ## last 32 bits from `x`. ## **Deprecated since version 0.19.9**: Use unsigned integers instead. @@ -1794,21 +1794,25 @@ proc cmp*(x, y: string): int {.noSideEffect, procvar.} ## **Note**: The precise result values depend on the used C runtime library and ## can differ between operating systems! -proc `@`* [IDX, T](a: array[IDX, T]): seq[T] {. - magic: "ArrToSeq", noSideEffect.} - ## Turns an array into a sequence. - ## - ## This most often useful for constructing - ## sequences with the array constructor: ``@[1, 2, 3]`` has the type - ## ``seq[int]``, while ``[1, 2, 3]`` has the type ``array[0..2, int]``. - ## - ## .. code-block:: Nim - ## let - ## a = [1, 3, 5] - ## b = "foo" - ## - ## echo @a # => @[1, 3, 5] - ## echo @b # => @['f', 'o', 'o'] +when defined(nimHasDefault): + proc `@`* [IDX, T](a: sink array[IDX, T]): seq[T] {. + magic: "ArrToSeq", noSideEffect.} + ## Turns an array into a sequence. + ## + ## This most often useful for constructing + ## sequences with the array constructor: ``@[1, 2, 3]`` has the type + ## ``seq[int]``, while ``[1, 2, 3]`` has the type ``array[0..2, int]``. + ## + ## .. code-block:: Nim + ## let + ## a = [1, 3, 5] + ## b = "foo" + ## + ## echo @a # => @[1, 3, 5] + ## echo @b # => @['f', 'o', 'o'] +else: + proc `@`* [IDX, T](a: array[IDX, T]): seq[T] {. + magic: "ArrToSeq", noSideEffect.} when defined(nimHasDefault): proc default*(T: typedesc): T {.magic: "Default", noSideEffect.} @@ -2089,7 +2093,7 @@ when not defined(JS) and not defined(nimscript) and hostOS != "standalone": when not defined(JS) and not defined(nimscript) and hasAlloc and not defined(gcDestructors): proc addChar(s: NimString, c: char): NimString {.compilerproc, benign.} -when not defined(gcDestructors): +when not defined(gcDestructors) or defined(nimscript): proc add*[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.} ## Generic proc for adding a data item `y` to a container `x`. ## @@ -2277,8 +2281,7 @@ type # these work for most platforms: PInt64* = ptr int64 ## An alias for ``ptr int64``. PInt32* = ptr int32 ## An alias for ``ptr int32``. -proc toFloat*(i: int): float {. - magic: "ToFloat", noSideEffect, importc: "toFloat".} +proc toFloat*(i: int): float {.noSideEffect, inline.} = ## Converts an integer `i` into a ``float``. ## ## If the conversion fails, `ValueError` is raised. @@ -2290,13 +2293,13 @@ proc toFloat*(i: int): float {. ## b = 3.7 ## ## echo a.toFloat + b # => 5.7 + float(i) -proc toBiggestFloat*(i: BiggestInt): BiggestFloat {. - magic: "ToBiggestFloat", noSideEffect, importc: "toBiggestFloat".} +proc toBiggestFloat*(i: BiggestInt): BiggestFloat {.noSideEffect, inline.} = ## Same as `toFloat <#toFloat,int>`_ but for ``BiggestInt`` to ``BiggestFloat``. + BiggestFloat(i) -proc toInt*(f: float): int {. - magic: "ToInt", noSideEffect, importc: "toInt".} +proc toInt*(f: float): int {.noSideEffect.} = ## Converts a floating point number `f` into an ``int``. ## ## Conversion rounds `f` half away from 0, see @@ -2310,10 +2313,11 @@ proc toInt*(f: float): int {. ## doAssert toInt(0.49) == 0 ## doAssert toInt(0.5) == 1 ## doAssert toInt(-0.5) == -1 # rounding is symmetrical + if f >= 0: int(f+0.5) else: int(f-0.5) -proc toBiggestInt*(f: BiggestFloat): BiggestInt {. - magic: "ToBiggestInt", noSideEffect, importc: "toBiggestInt".} +proc toBiggestInt*(f: BiggestFloat): BiggestInt {.noSideEffect.} = ## Same as `toInt <#toInt,float>`_ but for ``BiggestFloat`` to ``BiggestInt``. + if f >= 0: BiggestInt(f+0.5) else: BiggestInt(f-0.5) proc addQuitProc*(quitProc: proc() {.noconv.}) {. importc: "atexit", header: "<stdlib.h>".} @@ -2677,6 +2681,7 @@ when defined(nimNewRoof): ## ## for i in countup(2, 9, 3): ## echo i # => 2; 5; 8 + mixin inc when T is IntLikeForCount: var res = int(a) while res <= int(b): @@ -2697,6 +2702,7 @@ when defined(nimNewRoof): ## .. code-block:: Nim ## for i in 3 .. 7: ## echo i # => 3; 4; 5; 6; 7 + mixin inc when T is IntLikeForCount: var res = int(a) while res <= int(b): @@ -2726,6 +2732,7 @@ when defined(nimNewRoof): dotdotImpl(uint32) iterator `..<`*[T](a, b: T): T {.inline.} = + mixin inc var i = T(a) while i < b: yield i @@ -2781,6 +2788,7 @@ else: ## .. code-block:: Nim ## for i in 3 .. 7: ## echo i # => 3; 4; 5; 6; 7 + mixin inc when T is IntLikeForCount: var res = int(a) while res <= int(b): @@ -2793,6 +2801,7 @@ else: inc(res) iterator `..<`*[S, T](a: S, b: T): T {.inline.} = + mixin inc var i = T(a) while i < b: yield i @@ -3630,10 +3639,6 @@ when not defined(JS): #and not defined(nimscript): if result == 0: result = x.len - y.len - when not defined(nimscript) and hostOS != "standalone": - when defined(endb): - proc endbStep() - when declared(newSeq): proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] = ## Converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be @@ -3807,9 +3812,6 @@ when not defined(JS): #and not defined(nimscript): currException = exc {.push stack_trace: off, profiler:off.} - when defined(endb) and not defined(nimscript): - include "system/debugger" - when (defined(profiler) or defined(memProfiler)) and not defined(nimscript): include "system/profiler" {.pop.} # stacktrace @@ -4499,6 +4501,11 @@ when defined(nimconfig): when not defined(js): proc toOpenArray*[T](x: ptr UncheckedArray[T]; first, last: int): openArray[T] {. magic: "Slice".} + when defined(nimToOpenArrayCString): + proc toOpenArray*(x: cstring; first, last: int): openArray[char] {. + magic: "Slice".} + proc toOpenArrayByte*(x: cstring; first, last: int): openArray[byte] {. + magic: "Slice".} proc toOpenArray*[T](x: seq[T]; first, last: int): openArray[T] {. magic: "Slice".} @@ -4508,8 +4515,13 @@ proc toOpenArray*[I, T](x: array[I, T]; first, last: I): openArray[T] {. magic: "Slice".} proc toOpenArray*(x: string; first, last: int): openArray[char] {. magic: "Slice".} + proc toOpenArrayByte*(x: string; first, last: int): openArray[byte] {. magic: "Slice".} +proc toOpenArrayByte*(x: openArray[char]; first, last: int): openArray[byte] {. + magic: "Slice".} +proc toOpenArrayByte*(x: seq[char]; first, last: int): openArray[byte] {. + magic: "Slice".} type ForLoopStmt* {.compilerproc.} = object ## \ diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 9c47d9de9..efbd95089 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -984,7 +984,7 @@ when defined(nimTypeNames): # ---------------------- thread memory region ------------------------------- -template instantiateForRegion(allocator: untyped) = +template instantiateForRegion(allocator: untyped) {.dirty.} = {.push stackTrace: off.} when defined(fulldebug): @@ -1006,8 +1006,8 @@ template instantiateForRegion(allocator: untyped) = proc dealloc(p: pointer) = dealloc(allocator, p) - proc realloc(p: pointer, newsize: Natural): pointer = - result = realloc(allocator, p, newsize) + proc realloc(p: pointer, newSize: Natural): pointer = + result = realloc(allocator, p, newSize) when false: proc countFreeMem(): int = @@ -1054,13 +1054,13 @@ template instantiateForRegion(allocator: untyped) = else: dealloc(p) - proc reallocShared(p: pointer, newsize: Natural): pointer = + proc reallocShared(p: pointer, newSize: Natural): pointer = when hasThreadSupport: acquireSys(heapLock) - result = realloc(sharedHeap, p, newsize) + result = realloc(sharedHeap, p, newSize) releaseSys(heapLock) else: - result = realloc(p, newsize) + result = realloc(p, newSize) when hasThreadSupport: template sharedMemStatsShared(v: int) = diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 76c78a3b9..16e7a14d6 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -30,7 +30,7 @@ proc c_strcmp*(a, b: cstring): cint {. proc c_strlen*(a: cstring): csize {. importc: "strlen", header: "<string.h>", noSideEffect.} proc c_abort*() {. - importc: "abort", header: "<stdlib.h>", noSideEffect.} + importc: "abort", header: "<stdlib.h>", noSideEffect, noreturn.} when defined(linux) and defined(amd64): diff --git a/lib/system/assertions.nim b/lib/system/assertions.nim index 0deb957c9..2131394e0 100644 --- a/lib/system/assertions.nim +++ b/lib/system/assertions.nim @@ -27,12 +27,12 @@ proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} = Hide(raiseAssert)(msg) template assertImpl(cond: bool, msg: string, expr: string, enabled: static[bool]) = - const - loc = instantiationInfo(fullPaths = compileOption("excessiveStackTrace")) - ploc = $loc - bind instantiationInfo - mixin failedAssertImpl when enabled: + const + loc = instantiationInfo(fullPaths = compileOption("excessiveStackTrace")) + ploc = $loc + bind instantiationInfo + mixin failedAssertImpl {.line: loc.}: if not cond: failedAssertImpl(ploc & " `" & expr & "` " & msg) diff --git a/lib/system/debugger.nim b/lib/system/debugger.nim deleted file mode 100644 index fd0ae2399..000000000 --- a/lib/system/debugger.nim +++ /dev/null @@ -1,303 +0,0 @@ -# -# -# Nim's Runtime Library -# (c) Copyright 2013 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This file implements basic features for any debugger. - -type - VarSlot* {.compilerproc, final.} = object ## a slot in a frame - address*: pointer ## the variable's address - typ*: PNimType ## the variable's type - name*: cstring ## the variable's name; for globals this is "module.name" - - PExtendedFrame = ptr ExtendedFrame - ExtendedFrame = object # If the debugger is enabled the compiler - # provides an extended frame. Of course - # only slots that are - # needed are allocated and not 10_000, - # except for the global data description. - f: TFrame - slots: array[0..10_000, VarSlot] - -var - dbgGlobalData: ExtendedFrame # this reserves much space, but - # for now it is the most practical way - -proc dbgRegisterGlobal(name: cstring, address: pointer, - typ: PNimType) {.compilerproc.} = - let i = dbgGlobalData.f.len - if i >= high(dbgGlobalData.slots): - #debugOut("[Warning] cannot register global ") - return - dbgGlobalData.slots[i].name = name - dbgGlobalData.slots[i].typ = typ - dbgGlobalData.slots[i].address = address - inc(dbgGlobalData.f.len) - -proc getLocal*(frame: PFrame; slot: int): VarSlot {.inline.} = - ## retrieves the meta data for the local variable at `slot`. CAUTION: An - ## invalid `slot` value causes a corruption! - result = cast[PExtendedFrame](frame).slots[slot] - -proc getGlobalLen*(): int {.inline.} = - ## gets the number of registered globals. - result = dbgGlobalData.f.len - -proc getGlobal*(slot: int): VarSlot {.inline.} = - ## retrieves the meta data for the global variable at `slot`. CAUTION: An - ## invalid `slot` value causes a corruption! - result = dbgGlobalData.slots[slot] - -# ------------------- breakpoint support ------------------------------------ - -type - Breakpoint* = object ## represents a break point - low*, high*: int ## range from low to high; if disabled - ## both low and high are set to their negative values - filename*: cstring ## the filename of the breakpoint - -var - dbgBP: array[0..127, Breakpoint] # breakpoints - dbgBPlen: int - dbgBPbloom: int64 # we use a bloom filter to speed up breakpoint checking - - dbgFilenames*: array[0..300, cstring] ## registered filenames; - ## 'nil' terminated - dbgFilenameLen: int - -proc dbgRegisterFilename(filename: cstring) {.compilerproc.} = - # XXX we could check for duplicates here for DLL support - dbgFilenames[dbgFilenameLen] = filename - inc dbgFilenameLen - -proc dbgRegisterBreakpoint(line: int, - filename, name: cstring) {.compilerproc.} = - let x = dbgBPlen - if x >= high(dbgBP): - #debugOut("[Warning] cannot register breakpoint") - return - inc(dbgBPlen) - dbgBP[x].filename = filename - dbgBP[x].low = line - dbgBP[x].high = line - dbgBPbloom = dbgBPbloom or line - -proc addBreakpoint*(filename: cstring, lo, hi: int): bool = - let x = dbgBPlen - if x >= high(dbgBP): return false - inc(dbgBPlen) - result = true - dbgBP[x].filename = filename - dbgBP[x].low = lo - dbgBP[x].high = hi - for line in lo..hi: dbgBPbloom = dbgBPbloom or line - -const - FileSystemCaseInsensitive = defined(windows) or defined(dos) or defined(os2) - -proc fileMatches(c, bp: cstring): bool = - # bp = breakpoint filename - # c = current filename - # we consider it a match if bp is a suffix of c - # and the character for the suffix does not exist or - # is one of: \ / : - # depending on the OS case does not matter! - var blen: int = bp.len - var clen: int = c.len - if blen > clen: return false - # check for \ / : - if clen-blen-1 >= 0 and c[clen-blen-1] notin {'\\', '/', ':'}: - return false - var i = 0 - while i < blen: - var x = bp[i] - var y = c[i+clen-blen] - when FileSystemCaseInsensitive: - if x >= 'A' and x <= 'Z': x = chr(ord(x) - ord('A') + ord('a')) - if y >= 'A' and y <= 'Z': y = chr(ord(y) - ord('A') + ord('a')) - if x != y: return false - inc(i) - return true - -proc canonFilename*(filename: cstring): cstring = - ## returns 'nil' if the filename cannot be found. - for i in 0 .. dbgFilenameLen-1: - result = dbgFilenames[i] - if fileMatches(result, filename): return result - result = nil - -iterator listBreakpoints*(): ptr Breakpoint = - ## lists all breakpoints. - for i in 0..dbgBPlen-1: yield addr(dbgBP[i]) - -proc isActive*(b: ptr Breakpoint): bool = b.low > 0 -proc flip*(b: ptr Breakpoint) = - ## enables or disables 'b' depending on its current state. - b.low = -b.low; b.high = -b.high - -proc checkBreakpoints*(filename: cstring, line: int): ptr Breakpoint = - ## in which breakpoint (if any) we are. - if (dbgBPbloom and line) != line: return nil - for b in listBreakpoints(): - if line >= b.low and line <= b.high and filename == b.filename: return b - -# ------------------- watchpoint support ------------------------------------ - -type - Hash = int - Watchpoint {.pure, final.} = object - name: cstring - address: pointer - typ: PNimType - oldValue: Hash - -var - watchpoints: array[0..99, Watchpoint] - watchpointsLen: int - -proc `!&`(h: Hash, val: int): Hash {.inline.} = - result = h +% val - result = result +% result shl 10 - result = result xor (result shr 6) - -proc `!$`(h: Hash): Hash {.inline.} = - result = h +% h shl 3 - result = result xor (result shr 11) - result = result +% result shl 15 - -proc hash(data: pointer, size: int): Hash = - var h: Hash = 0 - var p = cast[cstring](data) - var i = 0 - var s = size - while s > 0: - h = h !& ord(p[i]) - inc(i) - dec(s) - result = !$h - -proc hashGcHeader(data: pointer): Hash = - const headerSize = sizeof(int)*2 - result = hash(cast[pointer](cast[int](data) -% headerSize), headerSize) - -proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool, - h: Hash): Hash -proc genericHashAux(dest: pointer, n: ptr TNimNode, shallow: bool, - h: Hash): Hash = - var d = cast[ByteAddress](dest) - case n.kind - of nkSlot: - result = genericHashAux(cast[pointer](d +% n.offset), n.typ, shallow, h) - of nkList: - result = h - for i in 0..n.len-1: - result = result !& genericHashAux(dest, n.sons[i], shallow, result) - of nkCase: - result = h !& hash(cast[pointer](d +% n.offset), n.typ.size) - var m = selectBranch(dest, n) - if m != nil: result = genericHashAux(dest, m, shallow, result) - of nkNone: sysAssert(false, "genericHashAux") - -proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool, - h: Hash): Hash = - sysAssert(mt != nil, "genericHashAux 2") - case mt.kind - of tyString: - var x = cast[PPointer](dest)[] - result = h - if x != nil: - let s = cast[NimString](x) - when defined(trackGcHeaders): - result = result !& hashGcHeader(x) - else: - result = result !& hash(x, s.len) - of tySequence: - var x = cast[PPointer](dest) - var dst = cast[ByteAddress](cast[PPointer](dest)[]) - result = h - if dst != 0: - when defined(trackGcHeaders): - result = result !& hashGcHeader(cast[PPointer](dest)[]) - else: - for i in 0..cast[PGenericSeq](dst).len-1: - result = result !& genericHashAux( - cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize), - mt.base, shallow, result) - of tyObject, tyTuple: - # we don't need to copy m_type field for tyObject, as they are equal anyway - result = genericHashAux(dest, mt.node, shallow, h) - of tyArray, tyArrayConstr: - let d = cast[ByteAddress](dest) - result = h - for i in 0..(mt.size div mt.base.size)-1: - result = result !& genericHashAux(cast[pointer](d +% i*% mt.base.size), - mt.base, shallow, result) - of tyRef: - when defined(trackGcHeaders): - var s = cast[PPointer](dest)[] - if s != nil: - result = result !& hashGcHeader(s) - else: - if shallow: - result = h !& hash(dest, mt.size) - else: - result = h - var s = cast[PPointer](dest)[] - if s != nil: - result = result !& genericHashAux(s, mt.base, shallow, result) - else: - result = h !& hash(dest, mt.size) # hash raw bits - -proc genericHash(dest: pointer, mt: PNimType): int = - result = genericHashAux(dest, mt, false, 0) - -proc dbgRegisterWatchpoint(address: pointer, name: cstring, - typ: PNimType) {.compilerproc.} = - let L = watchPointsLen - for i in 0 .. pred(L): - if watchPoints[i].name == name: - # address may have changed: - watchPoints[i].address = address - return - if L >= watchPoints.high: - #debugOut("[Warning] cannot register watchpoint") - return - watchPoints[L].name = name - watchPoints[L].address = address - watchPoints[L].typ = typ - watchPoints[L].oldValue = genericHash(address, typ) - inc watchPointsLen - -proc dbgUnregisterWatchpoints*() = - watchPointsLen = 0 - -var - dbgLineHook*: proc () {.nimcall.} - ## set this variable to provide a procedure that should be called before - ## each executed instruction. This should only be used by debuggers! - ## Only code compiled with the ``debugger:on`` switch calls this hook. - - dbgWatchpointHook*: proc (watchpointName: cstring) {.nimcall.} - -proc checkWatchpoints = - let L = watchPointsLen - for i in 0 .. pred(L): - let newHash = genericHash(watchPoints[i].address, watchPoints[i].typ) - if newHash != watchPoints[i].oldValue: - dbgWatchpointHook(watchPoints[i].name) - watchPoints[i].oldValue = newHash - -proc endb(line: int, file: cstring) {.compilerproc, noinline.} = - # This proc is called before every Nim code line! - if framePtr == nil: return - if dbgWatchpointHook != nil: checkWatchpoints() - framePtr.line = line # this is done here for smaller code size! - framePtr.filename = file - if dbgLineHook != nil: dbgLineHook() - -include "system/endb" diff --git a/lib/system/endb.nim b/lib/system/endb.nim deleted file mode 100644 index 6c99f8d12..000000000 --- a/lib/system/endb.nim +++ /dev/null @@ -1,579 +0,0 @@ -# -# -# Nim's Runtime Library -# (c) Copyright 2013 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# This file implements the embedded debugger that can be linked -# with the application. Mostly we do not use dynamic memory here as that -# would interfere with the GC and trigger ON/OFF errors if the -# user program corrupts memory. Unfortunately, for dispaying -# variables we use the ``system.repr()`` proc which uses Nim -# strings and thus allocates memory from the heap. Pity, but -# I do not want to implement ``repr()`` twice. - -const - EndbBeg = "*** endb" - EndbEnd = "***\n" - -type - StaticStr = object - len: int - data: array[0..100, char] - - BreakpointFilename = object - b: ptr Breakpoint - filename: StaticStr - - DbgState = enum - dbOff, # debugger is turned off - dbStepInto, # debugger is in tracing mode - dbStepOver, - dbSkipCurrent, - dbQuiting, # debugger wants to quit - dbBreakpoints # debugger is only interested in breakpoints - -var - dbgUser: StaticStr # buffer for user input; first command is ``step_into`` - # needs to be global cause we store the last command - # in it - dbgState: DbgState # state of debugger - dbgSkipToFrame: PFrame # frame to be skipped to - - maxDisplayRecDepth: int = 5 # do not display too much data! - - brkPoints: array[0..127, BreakpointFilename] - -proc setLen(s: var StaticStr, newLen=0) = - s.len = newLen - s.data[newLen] = '\0' - -proc add(s: var StaticStr, c: char) = - if s.len < high(s.data)-1: - s.data[s.len] = c - s.data[s.len+1] = '\0' - inc s.len - -proc add(s: var StaticStr, c: cstring) = - var i = 0 - while c[i] != '\0': - add s, c[i] - inc i - -proc assign(s: var StaticStr, c: cstring) = - setLen(s) - add s, c - -proc `==`(a, b: StaticStr): bool = - if a.len == b.len: - for i in 0 .. a.len-1: - if a.data[i] != b.data[i]: return false - return true - -proc `==`(a: StaticStr, b: cstring): bool = - result = c_strcmp(unsafeAddr a.data, b) == 0 - -proc write(f: CFilePtr, s: cstring) = c_fputs(s, f) -proc writeLine(f: CFilePtr, s: cstring) = - c_fputs(s, f) - c_fputs("\n", f) - -proc write(f: CFilePtr, s: StaticStr) = - write(f, cstring(unsafeAddr s.data)) - -proc write(f: CFilePtr, i: int) = - when sizeof(int) == 8: - discard c_fprintf(f, "%lld", i) - else: - discard c_fprintf(f, "%ld", i) - -proc close(f: CFilePtr): cint {. - importc: "fclose", header: "<stdio.h>", discardable.} - -proc c_fgetc(stream: CFilePtr): cint {. - importc: "fgetc", header: "<stdio.h>".} -proc c_ungetc(c: cint, f: CFilePtr): cint {. - importc: "ungetc", header: "<stdio.h>", discardable.} - -var - cstdin* {.importc: "stdin", header: "<stdio.h>".}: CFilePtr - -proc listBreakPoints() = - write(cstdout, EndbBeg) - write(cstdout, "| Breakpoints:\n") - for b in listBreakpoints(): - write(cstdout, abs(b.low)) - if b.high != b.low: - write(cstdout, "..") - write(cstdout, abs(b.high)) - write(cstdout, " ") - write(cstdout, b.filename) - if b.isActive: - write(cstdout, " [disabled]\n") - else: - write(cstdout, "\n") - write(cstdout, EndbEnd) - -proc openAppend(filename: cstring): CFilePtr = - proc fopen(filename, mode: cstring): CFilePtr {.importc: "fopen", header: "<stdio.h>".} - - result = fopen(filename, "ab") - if result != nil: - write(result, "----------------------------------------\n") - -proc dbgRepr(p: pointer, typ: PNimType): string = - var cl: ReprClosure - initReprClosure(cl) - cl.recDepth = maxDisplayRecDepth - # locks for the GC turned out to be a bad idea... - # inc(recGcLock) - result = "" - reprAux(result, p, typ, cl) - # dec(recGcLock) - deinitReprClosure(cl) - -proc writeVariable(stream: CFilePtr, slot: VarSlot) = - write(stream, slot.name) - write(stream, " = ") - writeLine(stream, dbgRepr(slot.address, slot.typ)) - -proc listFrame(stream: CFilePtr, f: PFrame) = - write(stream, EndbBeg) - write(stream, "| Frame (") - write(stream, f.len) - write(stream, " slots):\n") - for i in 0 .. f.len-1: - writeLine(stream, getLocal(f, i).name) - write(stream, EndbEnd) - -proc listLocals(stream: CFilePtr, f: PFrame) = - write(stream, EndbBeg) - write(stream, "| Frame (") - write(stream, f.len) - write(stream, " slots):\n") - for i in 0 .. f.len-1: - writeVariable(stream, getLocal(f, i)) - write(stream, EndbEnd) - -proc listGlobals(stream: CFilePtr) = - write(stream, EndbBeg) - write(stream, "| Globals:\n") - for i in 0 .. getGlobalLen()-1: - writeLine(stream, getGlobal(i).name) - write(stream, EndbEnd) - -proc debugOut(msg: cstring) = - # the *** *** markers are for easy recognition of debugger - # output for external frontends. - write(cstdout, EndbBeg) - write(cstdout, "| ") - write(cstdout, msg) - write(cstdout, EndbEnd) - -proc dbgFatal(msg: cstring) = - debugOut(msg) - dbgAborting = true # the debugger wants to abort - quit(1) - -proc dbgShowCurrentProc(dbgFramePointer: PFrame) = - if dbgFramePointer != nil: - write(cstdout, "*** endb| now in proc: ") - write(cstdout, dbgFramePointer.procname) - write(cstdout, " ***\n") - else: - write(cstdout, "*** endb| (proc name not available) ***\n") - -proc dbgShowExecutionPoint() = - write(cstdout, "*** endb| ") - write(cstdout, framePtr.filename) - write(cstdout, "(") - write(cstdout, framePtr.line) - write(cstdout, ") ") - write(cstdout, framePtr.procname) - write(cstdout, " ***\n") - -proc scanAndAppendWord(src: cstring, a: var StaticStr, start: int): int = - result = start - # skip whitespace: - while src[result] in {'\t', ' '}: inc(result) - while true: - case src[result] - of 'a'..'z', '0'..'9': add(a, src[result]) - of '_': discard # just skip it - of 'A'..'Z': add(a, chr(ord(src[result]) - ord('A') + ord('a'))) - else: break - inc(result) - -proc scanWord(src: cstring, a: var StaticStr, start: int): int = - setlen(a) - result = scanAndAppendWord(src, a, start) - -proc scanFilename(src: cstring, a: var StaticStr, start: int): int = - result = start - setLen a - while src[result] in {'\t', ' '}: inc(result) - while src[result] notin {'\t', ' ', '\0'}: - add(a, src[result]) - inc(result) - -proc scanNumber(src: cstring, a: var int, start: int): int = - result = start - a = 0 - while src[result] in {'\t', ' '}: inc(result) - while true: - case src[result] - of '0'..'9': a = a * 10 + ord(src[result]) - ord('0') - of '_': discard # skip underscores (nice for long line numbers) - else: break - inc(result) - -proc dbgHelp() = - debugOut(""" -list of commands (see the manual for further help): - GENERAL -h, help display this help message -q, quit quit the debugger and the program -<ENTER> repeat the previous debugger command - EXECUTING -s, step single step, stepping into routine calls -n, next single step, without stepping into routine calls -f, skipcurrent continue execution until the current routine finishes -c, continue, r, run continue execution until the next breakpoint -i, ignore continue execution, ignore all breakpoints - BREAKPOINTS -b, break [fromline [toline]] [file] - set a new breakpoint for line and file - if line or file are omitted the current one is used -breakpoints display the entire breakpoint list -toggle fromline [file] enable or disable a breakpoint -filenames list all valid filenames - DATA DISPLAY -e, eval <expr> evaluate the expression <expr> -o, out <file> <expr> evaluate <expr> and write it to <file> -w, where display the current execution point -stackframe [file] display current stack frame [and write it to file] -u, up go up in the call stack -d, down go down in the call stack -bt, backtrace display the entire call stack -l, locals display available local variables -g, globals display available global variables -maxdisplay <integer> set the display's recursion maximum -""") - -proc invalidCommand() = - debugOut("[Warning] invalid command ignored (type 'h' for help) ") - -proc hasExt(s: cstring): bool = - # returns true if s has a filename extension - var i = 0 - while s[i] != '\0': - if s[i] == '.': return true - inc i - -proc parseBreakpoint(s: cstring, start: int): Breakpoint = - var dbgTemp: StaticStr - var i = scanNumber(s, result.low, start) - if result.low == 0: result.low = framePtr.line - i = scanNumber(s, result.high, i) - if result.high == 0: result.high = result.low - i = scanFilename(s, dbgTemp, i) - if dbgTemp.len != 0: - if not hasExt(addr dbgTemp.data): add(dbgTemp, ".nim") - result.filename = canonFilename(addr dbgTemp.data) - if result.filename.isNil: - debugOut("[Warning] no breakpoint could be set; unknown filename ") - return - else: - result.filename = framePtr.filename - -proc createBreakPoint(s: cstring, start: int) = - let br = parseBreakpoint(s, start) - if not br.filename.isNil: - if not addBreakpoint(br.filename, br.low, br.high): - debugOut("[Warning] no breakpoint could be set; out of breakpoint space ") - -proc breakpointToggle(s: cstring, start: int) = - var a = parseBreakpoint(s, start) - if not a.filename.isNil: - var b = checkBreakpoints(a.filename, a.low) - if not b.isNil: b.flip - else: debugOut("[Warning] unknown breakpoint ") - -proc dbgEvaluate(stream: CFilePtr, s: cstring, start: int, f: PFrame) = - var dbgTemp: StaticStr - var i = scanWord(s, dbgTemp, start) - while s[i] in {' ', '\t'}: inc(i) - var v: VarSlot - if s[i] == '.': - inc(i) - add(dbgTemp, '.') - i = scanAndAppendWord(s, dbgTemp, i) - for i in 0 .. getGlobalLen()-1: - let v = getGlobal(i) - if c_strcmp(v.name, addr dbgTemp.data) == 0: - writeVariable(stream, v) - else: - for i in 0 .. f.len-1: - let v = getLocal(f, i) - if c_strcmp(v.name, addr dbgTemp.data) == 0: - writeVariable(stream, v) - -proc dbgOut(s: cstring, start: int, currFrame: PFrame) = - var dbgTemp: StaticStr - var i = scanFilename(s, dbgTemp, start) - if dbgTemp.len == 0: - invalidCommand() - return - var stream = openAppend(addr dbgTemp.data) - if stream == nil: - debugOut("[Warning] could not open or create file ") - return - dbgEvaluate(stream, s, i, currFrame) - close(stream) - -proc dbgStackFrame(s: cstring, start: int, currFrame: PFrame) = - var dbgTemp: StaticStr - var i = scanFilename(s, dbgTemp, start) - if dbgTemp.len == 0: - # just write it to cstdout: - listFrame(cstdout, currFrame) - else: - var stream = openAppend(addr dbgTemp.data) - if stream == nil: - debugOut("[Warning] could not open or create file ") - return - listFrame(stream, currFrame) - close(stream) - -proc readLine(f: CFilePtr, line: var StaticStr): bool = - while true: - var c = c_fgetc(f) - if c < 0'i32: - if line.len > 0: break - else: return false - if c == 10'i32: break # LF - if c == 13'i32: # CR - c = c_fgetc(f) # is the next char LF? - if c != 10'i32: discard c_ungetc(c, f) # no, put the character back - break - add line, chr(int(c)) - result = true - -proc listFilenames() = - write(cstdout, EndbBeg) - write(cstdout, "| Files:\n") - var i = 0 - while true: - let x = dbgFilenames[i] - if x.isNil: break - write(cstdout, x) - write(cstdout, "\n") - inc i - write(cstdout, EndbEnd) - -proc dbgWriteStackTrace(f: PFrame) -proc commandPrompt() = - # if we return from this routine, user code executes again - var - again = true - dbgFramePtr = framePtr # for going down and up the stack - dbgDown = 0 # how often we did go down - dbgTemp: StaticStr - - while again: - write(cstdout, "*** endb| >>") - let oldLen = dbgUser.len - dbgUser.len = 0 - if not readLine(cstdin, dbgUser): break - if dbgUser.len == 0: dbgUser.len = oldLen - # now look what we have to do: - var i = scanWord(addr dbgUser.data, dbgTemp, 0) - template `?`(x: untyped): untyped = dbgTemp == cstring(x) - if ?"s" or ?"step": - dbgState = dbStepInto - again = false - elif ?"n" or ?"next": - dbgState = dbStepOver - dbgSkipToFrame = framePtr - again = false - elif ?"f" or ?"skipcurrent": - dbgState = dbSkipCurrent - dbgSkipToFrame = framePtr.prev - again = false - elif ?"c" or ?"continue" or ?"r" or ?"run": - dbgState = dbBreakpoints - again = false - elif ?"i" or ?"ignore": - dbgState = dbOff - again = false - elif ?"h" or ?"help": - dbgHelp() - elif ?"q" or ?"quit": - dbgState = dbQuiting - dbgAborting = true - again = false - quit(1) # BUGFIX: quit with error code > 0 - elif ?"e" or ?"eval": - var - prevState = dbgState - prevSkipFrame = dbgSkipToFrame - dbgState = dbSkipCurrent - dbgEvaluate(cstdout, addr dbgUser.data, i, dbgFramePtr) - dbgState = prevState - dbgSkipToFrame = prevSkipFrame - elif ?"o" or ?"out": - dbgOut(addr dbgUser.data, i, dbgFramePtr) - elif ?"stackframe": - dbgStackFrame(addr dbgUser.data, i, dbgFramePtr) - elif ?"w" or ?"where": - dbgShowExecutionPoint() - elif ?"l" or ?"locals": - var - prevState = dbgState - prevSkipFrame = dbgSkipToFrame - dbgState = dbSkipCurrent - listLocals(cstdout, dbgFramePtr) - dbgState = prevState - dbgSkipToFrame = prevSkipFrame - elif ?"g" or ?"globals": - var - prevState = dbgState - prevSkipFrame = dbgSkipToFrame - dbgState = dbSkipCurrent - listGlobals(cstdout) - dbgState = prevState - dbgSkipToFrame = prevSkipFrame - elif ?"u" or ?"up": - if dbgDown <= 0: - debugOut("[Warning] cannot go up any further ") - else: - dbgFramePtr = framePtr - for j in 0 .. dbgDown-2: # BUGFIX - dbgFramePtr = dbgFramePtr.prev - dec(dbgDown) - dbgShowCurrentProc(dbgFramePtr) - elif ?"d" or ?"down": - if dbgFramePtr != nil: - inc(dbgDown) - dbgFramePtr = dbgFramePtr.prev - dbgShowCurrentProc(dbgFramePtr) - else: - debugOut("[Warning] cannot go down any further ") - elif ?"bt" or ?"backtrace": - dbgWriteStackTrace(framePtr) - elif ?"b" or ?"break": - createBreakPoint(addr dbgUser.data, i) - elif ?"breakpoints": - listBreakPoints() - elif ?"toggle": - breakpointToggle(addr dbgUser.data, i) - elif ?"filenames": - listFilenames() - elif ?"maxdisplay": - var parsed: int - i = scanNumber(addr dbgUser.data, parsed, i) - if dbgUser.data[i-1] in {'0'..'9'}: - if parsed == 0: maxDisplayRecDepth = -1 - else: maxDisplayRecDepth = parsed - else: - invalidCommand() - else: invalidCommand() - -proc endbStep() = - # we get into here if an unhandled exception has been raised - # XXX: do not allow the user to run the program any further? - # XXX: BUG: the frame is lost here! - dbgShowExecutionPoint() - commandPrompt() - -proc dbgWriteStackTrace(f: PFrame) = - const - firstCalls = 32 - var - it = f - i = 0 - total = 0 - tempFrames: array[0..127, PFrame] - # setup long head: - while it != nil and i <= high(tempFrames)-firstCalls: - tempFrames[i] = it - inc(i) - inc(total) - it = it.prev - # go up the stack to count 'total': - var b = it - while it != nil: - inc(total) - it = it.prev - var skipped = 0 - if total > len(tempFrames): - # skip N - skipped = total-i-firstCalls+1 - for j in 1..skipped: - if b != nil: b = b.prev - # create '...' entry: - tempFrames[i] = nil - inc(i) - # setup short tail: - while b != nil and i <= high(tempFrames): - tempFrames[i] = b - inc(i) - b = b.prev - for j in countdown(i-1, 0): - if tempFrames[j] == nil: - write(cstdout, "(") - write(cstdout, skipped) - write(cstdout, " calls omitted) ...") - else: - write(cstdout, tempFrames[j].filename) - if tempFrames[j].line > 0: - write(cstdout, "(") - write(cstdout, tempFrames[j].line) - write(cstdout, ")") - write(cstdout, " ") - write(cstdout, tempFrames[j].procname) - write(cstdout, "\n") - -proc checkForBreakpoint = - let b = checkBreakpoints(framePtr.filename, framePtr.line) - if b != nil: - write(cstdout, "*** endb| reached ") - write(cstdout, framePtr.filename) - write(cstdout, "(") - write(cstdout, framePtr.line) - write(cstdout, ") ") - write(cstdout, framePtr.procname) - write(cstdout, " ***\n") - commandPrompt() - -proc lineHookImpl() {.nimcall.} = - case dbgState - of dbStepInto: - # we really want the command prompt here: - dbgShowExecutionPoint() - commandPrompt() - of dbSkipCurrent, dbStepOver: # skip current routine - if framePtr == dbgSkipToFrame: - dbgShowExecutionPoint() - commandPrompt() - else: - # breakpoints are wanted though (I guess) - checkForBreakpoint() - of dbBreakpoints: - # debugger is only interested in breakpoints - checkForBreakpoint() - else: discard - -proc watchpointHookImpl(name: cstring) {.nimcall.} = - dbgWriteStackTrace(framePtr) - debugOut(name) - -proc initDebugger {.inline.} = - dbgState = dbStepInto - dbgUser.len = 1 - dbgUser.data[0] = 's' - dbgWatchpointHook = watchpointHookImpl - dbgLineHook = lineHookImpl diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 0898ad0fd..1eb4cedc8 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -38,10 +38,7 @@ proc showErrorMessage(data: cstring) {.gcsafe.} = writeToStdErr(data) proc quitOrDebug() {.inline.} = - when defined(endb): - endbStep() # call the debugger - else: - quit(1) + quit(1) proc chckIndx(i, a, b: int): int {.inline, compilerproc, benign.} proc chckRange(i, a, b: int): int {.inline, compilerproc, benign.} @@ -469,10 +466,6 @@ proc nimFrame(s: PFrame) {.compilerRtl, inl.} = framePtr = s if s.calldepth == nimCallDepthLimit: callDepthLimitReached() -when defined(endb): - var - dbgAborting: bool # whether the debugger wants to abort - when defined(cpp) and appType != "lib" and not defined(js) and not defined(nimscript) and hostOS != "standalone" and not defined(noCppExceptions): @@ -515,8 +508,6 @@ when not defined(noSignalHandler) and not defined(useNimRtl): elif s == SIGSEGV: action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n") elif s == SIGABRT: - when defined(endb): - if dbgAborting: return # the debugger wants to abort action("SIGABRT: Abnormal termination.\n") elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n") elif s == SIGILL: action("SIGILL: Illegal operation.\n") @@ -546,7 +537,6 @@ when not defined(noSignalHandler) and not defined(useNimRtl): msg = y processSignal(sign, asgn) showErrorMessage(msg) - when defined(endb): dbgAborting = true quit(1) # always quit when SIGABRT proc registerSignalHandler() = diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index 87d803485..3ce428930 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -511,7 +511,7 @@ when not defined(useNimRtl): gch.tracing = true proc GC_fullCollect() = - var oldThreshold = gch.cycleThreshold + let oldThreshold = gch.cycleThreshold gch.cycleThreshold = 0 # forces cycle collection collectCT(gch, 0) gch.cycleThreshold = oldThreshold diff --git a/lib/system/iterators.nim b/lib/system/iterators.nim index dafd56cb3..549aa5886 100644 --- a/lib/system/iterators.nim +++ b/lib/system/iterators.nim @@ -85,7 +85,7 @@ iterator pairs*[T](a: openArray[T]): tuple[key: int, val: T] {.inline.} = yield (i, a[i]) inc(i) -iterator mpairs*[T](a: var openArray[T]): tuple[key:int, val:var T]{.inline.} = +iterator mpairs*[T](a: var openArray[T]): tuple[key: int, val: var T]{.inline.} = ## Iterates over each item of `a`. Yields ``(index, a[index])`` pairs. ## ``a[index]`` can be modified. var i = 0 @@ -102,7 +102,7 @@ iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} = if i >= high(IX): break inc(i) -iterator mpairs*[IX, T](a:var array[IX, T]):tuple[key:IX,val:var T] {.inline.} = +iterator mpairs*[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inline.} = ## Iterates over each item of `a`. Yields ``(index, a[index])`` pairs. ## ``a[index]`` can be modified. var i = low(IX) @@ -179,7 +179,6 @@ iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} = yield (i, a[i]) inc(i) - iterator items*[T](a: seq[T]): T {.inline.} = ## Iterates over each item of `a`. var i = 0 @@ -224,7 +223,7 @@ iterator fields*[T: tuple|object](x: T): RootObj {. ## **Warning**: This really transforms the 'for' and unrolls the loop. ## The current implementation also has a bug ## that affects symbol binding in the loop body. -iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[a,b: untyped] {. +iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[a, b: RootObj] {. magic: "Fields", noSideEffect.} ## Iterates over every field of `x` and `y`. ## @@ -266,7 +265,7 @@ iterator fieldPairs*[T: tuple|object](x: T): RootObj {. ## loop body. iterator fieldPairs*[S: tuple|object, T: tuple|object](x: S, y: T): tuple[ - a, b: untyped] {. + a, b: RootObj] {. magic: "FieldPairs", noSideEffect.} ## Iterates over every field of `x` and `y`. ## |