From fa961f16d0d2078a841fccb93231858e2afae94e Mon Sep 17 00:00:00 2001 From: enurlyx Date: Tue, 22 Apr 2014 19:42:32 +0200 Subject: [PATCH 01/34] 1) export UINT 2) Fixed parameter of FillRect RECT -> var RECT --- lib/windows/windows.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/windows/windows.nim b/lib/windows/windows.nim index dd743ffa4c..41f760130e 100644 --- a/lib/windows/windows.nim +++ b/lib/windows/windows.nim @@ -62,7 +62,7 @@ type # BaseTsd.h -- Type definitions for the basic sized types type # WinDef.h -- Basic Windows Type Definitions # BaseTypes - UINT = int32 + UINT* = int32 ULONG* = int PULONG* = ptr int USHORT* = int16 @@ -19683,7 +19683,7 @@ proc SetSysColors*(cElements: int32, lpaElements: var wINT, dynlib: "user32", importc: "SetSysColors".} proc DrawFocusRect*(hDC: HDC, lprc: var RECT): WINBOOL{.stdcall, dynlib: "user32", importc: "DrawFocusRect".} -proc FillRect*(hDC: HDC, lprc: RECT, hbr: HBRUSH): int32{.stdcall, +proc FillRect*(hDC: HDC, lprc: var RECT, hbr: HBRUSH): int32{.stdcall, dynlib: "user32", importc: "FillRect".} proc FrameRect*(hDC: HDC, lprc: var RECT, hbr: HBRUSH): int32{.stdcall, dynlib: "user32", importc: "FrameRect".} From 9428bedcc84bfc4cffca7014897410025e9fb658 Mon Sep 17 00:00:00 2001 From: Simon Hafner Date: Sat, 3 May 2014 13:25:41 -0500 Subject: [PATCH 02/34] Fixes #1168 --- lib/system/ansi_c.nim | 3 +++ lib/system/excpt.nim | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 2d33965e3d..5111bc3cf5 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -57,6 +57,7 @@ when not defined(SIGINT): SIGINT = cint(2) SIGSEGV = cint(11) SIGTERM = cint(15) + SIGPIPE = cint(13) else: {.error: "SIGABRT not ported to your platform".} else: @@ -66,6 +67,8 @@ when not defined(SIGINT): SIGABRT {.importc: "SIGABRT", nodecl.}: cint SIGFPE {.importc: "SIGFPE", nodecl.}: cint SIGILL {.importc: "SIGILL", nodecl.}: cint + when defined(macosx) or defined(linux): + var SIGPIPE {.importc: "SIGPIPE", nodecl.}: cint when defined(macosx): when NoFakeVars: diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 2dc134eaf4..63a61183f6 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -298,7 +298,13 @@ when not defined(noSignalHandler): elif s == SIGILL: action("SIGILL: Illegal operation.\n") elif s == SIGBUS: action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n") - else: action("unknown signal\n") + else: + block platformSpecificSignal: + when defined(SIGPIPE): + if s == SIGPIPE: + action("SIGPIPE: Pipe closed.\n") + break platformSpecificSignal + action("unknown signal\n") # print stack trace and quit when hasSomeStackTrace: @@ -323,6 +329,8 @@ when not defined(noSignalHandler): c_signal(SIGFPE, signalHandler) c_signal(SIGILL, signalHandler) c_signal(SIGBUS, signalHandler) + when defined(SIGPIPE): + c_signal(SIGPIPE, signalHandler) registerSignalHandler() # call it in initialization section From a2692f984d93fd1a9bb17e7199f039d116f876bb Mon Sep 17 00:00:00 2001 From: enurlyx Date: Sun, 4 May 2014 12:49:05 +0200 Subject: [PATCH 03/34] Changed COLORREF from int to DWORD (32 bit long), so that it works also on 64bit Windows --- lib/windows/windows.nim | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/windows/windows.nim b/lib/windows/windows.nim index 41f760130e..7070833ce7 100644 --- a/lib/windows/windows.nim +++ b/lib/windows/windows.nim @@ -137,7 +137,7 @@ type # WinDef.h -- Basic Windows Type Definitions HFILE* = HANDLE HCURSOR* = HANDLE # = HICON - COLORREF* = int + COLORREF* = DWORD LPCOLORREF* = ptr COLORREF POINT* {.final, pure.} = object @@ -238,7 +238,7 @@ type CALTYPE* = int CALID* = int CCHAR* = char - TCOLORREF* = int + TCOLORREF* = COLORREF WINT* = int32 PINTEGER* = ptr int32 PBOOL* = ptr WINBOOL @@ -22758,12 +22758,12 @@ proc LocalDiscard*(hlocMem: HLOCAL): HLOCAL = # WinGDI.h -proc GetGValue*(rgb: int32): int8 = - result = toU8(rgb shr 8'i32) +discard """proc GetGValue*(rgb: int32): int8 = + result = toU8(rgb shr 8'i32)""" proc RGB*(r, g, b: int): COLORREF = result = toU32(r) or (toU32(g) shl 8) or (toU32(b) shl 16) proc RGB*(r, g, b: range[0 .. 255]): COLORREF = - result = r or g shl 8 or b shl 16 + result = toU32(r) or (toU32(g) shl 8) or (toU32(b) shl 16) proc PALETTERGB*(r, g, b: range[0..255]): COLORREF = result = 0x02000000 or RGB(r, g, b) From 3070264525b2324b4b371b2751c6a49abce79b51 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Sun, 4 May 2014 23:48:38 -0400 Subject: [PATCH 04/34] Added define check for openBSD around fmtmsg.h stuff, OpenBSD does not actually include this header --- lib/posix/posix.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index e206447cc5..cdca826ca1 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -846,7 +846,7 @@ var FE_UPWARD* {.importc, header: "".}: cint FE_DFL_ENV* {.importc, header: "".}: cint -when not defined(haiku): +when not defined(haiku) and not defined(OpenBSD): var MM_HARD* {.importc, header: "".}: cint ## Source of the condition is hardware. @@ -1816,7 +1816,7 @@ proc feholdexcept*(a1: ptr Tfenv): cint {.importc, header: "".} proc fesetenv*(a1: ptr Tfenv): cint {.importc, header: "".} proc feupdateenv*(a1: ptr Tfenv): cint {.importc, header: "".} -when not defined(haiku): +when not defined(haiku) and not defined(OpenBSD): proc fmtmsg*(a1: int, a2: cstring, a3: cint, a4, a5, a6: cstring): cint {.importc, header: "".} From c210e1255cc902130ba76d4d1f014ac0f724d145 Mon Sep 17 00:00:00 2001 From: boydgreenfield Date: Mon, 5 May 2014 14:56:14 -0700 Subject: [PATCH 05/34] Clarify newFileSize & mappedSize params in memfiles.open() docs --- lib/pure/memfiles.nim | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 807f3da433..97220b90b3 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -74,9 +74,22 @@ proc unmapMem*(f: var TMemFile, p: pointer, size: int) = proc open*(filename: string, mode: TFileMode = fmRead, mappedSize = -1, offset = 0, newFileSize = -1): TMemFile = ## opens a memory mapped file. If this fails, ``EOS`` is raised. - ## `newFileSize` can only be set if the file is not opened with ``fmRead`` - ## access. `mappedSize` and `offset` can be used to map only a slice of - ## the file. + ## `newFileSize` can only be set if the file does not exist and is opened + ## with write access (e.g., with fmReadWrite). `mappedSize` and `offset` + ## can be used to map only a slice of the file. Example: + ## + ## .. code-block:: nimrod + ## var + ## mm, mm_full, mm_half: TMemFile + ## + ## mm = memfiles.open("/tmp/test.mmap", mode = fmWrite, newFileSize = 1024) # Create a new file + ## mm.close() + ## + ## # Read the whole file, would fail if newFileSize was set + ## mm_full = memfiles.open("/tmp/test.mmap", mode = fmReadWrite, mappedSize = -1) + ## + ## # Read the first 512 bytes + ## mm_half = memfiles.open("/tmp/test.mmap", mode = fmReadWrite, mappedSize = 512) # The file can be resized only when write mode is used: assert newFileSize == -1 or mode != fmRead From a309a5f38abd7c6d57f1e80a3aef81c3c3501f65 Mon Sep 17 00:00:00 2001 From: boydgreenfield Date: Mon, 5 May 2014 16:42:30 -0700 Subject: [PATCH 06/34] Update posix open() call to incl. permissions This explicitly grants user read/write access to newly-created mmap files. Previously, on some systems files would be created but could not be re-opened as the user lacked sufficient permissions. --- lib/pure/memfiles.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 97220b90b3..31fefc6c82 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -178,8 +178,11 @@ proc open*(filename: string, mode: TFileMode = fmRead, if newFileSize != -1: flags = flags or O_CREAT or O_TRUNC + var permissions_mode = S_IRUSR or S_IWUSR + result.handle = open(filename, flags, permissions_mode) + else: + result.handle = open(filename, flags) - result.handle = open(filename, flags) if result.handle == -1: # XXX: errno is supposed to be set here # Is there an exception that wraps it? From ae6dac6b63821e70677003114c96c12d156cc64f Mon Sep 17 00:00:00 2001 From: Charlie Date: Tue, 6 May 2014 14:19:03 -0400 Subject: [PATCH 07/34] added .ilk files to the koch clean list, these are incremental link information files for MSVC --- koch.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/koch.nim b/koch.nim index 79acc77915..c203e0fd09 100644 --- a/koch.nim +++ b/koch.nim @@ -167,7 +167,7 @@ const cleanExt = [ ".ppu", ".o", ".obj", ".dcu", ".~pas", ".~inc", ".~dsk", ".~dpr", ".map", ".tds", ".err", ".bak", ".pyc", ".exe", ".rod", ".pdb", ".idb", - ".idx" + ".idx", ".ilk" ] ignore = [ ".bzrignore", "nimrod", "nimrod.exe", "koch", "koch.exe", ".gitignore" From 809390ef46b766ddb19cd31477f268f9f6dd0b7b Mon Sep 17 00:00:00 2001 From: Patrick Pelletier Date: Wed, 7 May 2014 17:31:06 -0700 Subject: [PATCH 08/34] fix some typos --- doc/lib.txt | 2 +- doc/manual.txt | 12 ++++++------ doc/nimrodc.txt | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/lib.txt b/doc/lib.txt index 3ca519c9ed..2da753007b 100644 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -535,7 +535,7 @@ Database support * `odbcsql `_ interface to the ODBC driver. * `sphinx `_ - Nimrod wrapper for ``shpinx``. + Nimrod wrapper for ``sphinx``. XML Processing diff --git a/doc/manual.txt b/doc/manual.txt index 39e2bad2aa..d3a330e3a2 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -123,7 +123,7 @@ This means that all the control structures are recognized by indentation. Indentation consists only of spaces; tabulators are not allowed. The indentation handling is implemented as follows: The lexer annotates the -following token with the preceeding number of spaces; indentation is not +following token with the preceding number of spaces; indentation is not a separate token. This trick allows parsing of Nimrod with only 1 token of lookahead. @@ -617,7 +617,7 @@ Ordinal types Integers, bool, characters and enumeration types (and subranges of these types) belong to ordinal types. For reasons of simplicity of implementation -the types ``uint`` and ``uint64`` are no ordinal types. +the types ``uint`` and ``uint64`` are not ordinal types. Pre-defined integer types @@ -686,7 +686,7 @@ kinds of integer types are used: the smaller type is converted to the larger. A `narrowing type conversion`:idx: converts a larger to a smaller type (for example ``int32 -> int16``. A `widening type conversion`:idx: converts a smaller type to a larger type (for example ``int16 -> int32``). In Nimrod only -widening type conversion are *implicit*: +widening type conversions are *implicit*: .. code-block:: nimrod var myInt16 = 5i16 @@ -1519,7 +1519,7 @@ Most calling conventions exist only for the Windows 32-bit platform. Assigning/passing a procedure to a procedural variable is only allowed if one of the following conditions hold: -1) The procedure that is accessed resists in the current module. +1) The procedure that is accessed resides in the current module. 2) The procedure is marked with the ``procvar`` pragma (see `procvar pragma`_). 3) The procedure has a calling convention that differs from ``nimcall``. 4) The procedure is anonymous. @@ -1527,8 +1527,8 @@ of the following conditions hold: The rules' purpose is to prevent the case that extending a non-``procvar`` procedure with default parameters breaks client code. -The default calling convention is ``nimcall``, unless it is an inner proc ( -a proc inside of a proc). For an inner proc an analysis is performed whether it +The default calling convention is ``nimcall``, unless it is an inner proc (a +proc inside of a proc). For an inner proc an analysis is performed whether it accesses its environment. If it does so, it has the calling convention ``closure``, otherwise it has the calling convention ``nimcall``. diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 52e0a6eaf4..d1925547e9 100644 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -167,7 +167,7 @@ might contain some cruft even when dead code elimination is turned on. So the final release build should be done with ``--symbolFiles:off``. Due to the aggregation of C code it is also recommended that each project -resists in its own directory so that the generated ``nimcache`` directory +resides in its own directory so that the generated ``nimcache`` directory is not shared between different projects. From 7754bc73b484804c57268a20d27bbe9ac9e34ab3 Mon Sep 17 00:00:00 2001 From: EXetoC Date: Fri, 9 May 2014 23:22:43 +0200 Subject: [PATCH 09/34] gpp -> gcc --- compiler/main.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/main.nim b/compiler/main.nim index f833394f72..b4af49248f 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -310,7 +310,7 @@ proc mainCommand* = of "cpp", "compiletocpp": extccomp.cExt = ".cpp" gCmd = cmdCompileToCpp - if cCompiler == ccGcc: setCC("gpp") + if cCompiler == ccGcc: setCC("gcc") wantMainModule() defineSymbol("cpp") commandCompileToC() From 46d4e5d052f43a1e2d7e93ef2cf431b0a0201ee5 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Sat, 10 May 2014 18:54:30 -0400 Subject: [PATCH 10/34] changed openssl to import CRYPTO_mem_set_functions from libcrypto and made sockets.nim exclude the sslv2 code on BSD --- lib/pure/sockets.nim | 2 +- lib/wrappers/openssl.nim | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 8d96cbaaff..7b8b3d5577 100644 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -295,7 +295,7 @@ when defined(ssl): of protSSLv23: newCTX = SSL_CTX_new(SSLv23_method()) # SSlv2,3 and TLS1 support. of protSSLv2: - when not defined(linux): + when not defined(linux) and not defined(OpenBSD): newCTX = SSL_CTX_new(SSLv2_method()) else: SSLError() diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim index 90c398dceb..bbcb2175e9 100644 --- a/lib/wrappers/openssl.nim +++ b/lib/wrappers/openssl.nim @@ -270,7 +270,7 @@ proc OPENSSL_config*(configName: cstring){.cdecl, dynlib: DLLSSLName, importc.} when not defined(windows): proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, - dynlib: DLLSSLName, importc.} + dynlib: DLLUtilName, importc.} proc CRYPTO_malloc_init*() = when not defined(windows): From a16f762ce267d9aaa871f6a594f63ae6642f35a8 Mon Sep 17 00:00:00 2001 From: Grzegorz Adam Hankiewicz Date: Sun, 11 May 2014 09:58:44 +0200 Subject: [PATCH 11/34] Moves abstypes content into manual. --- doc/abstypes.txt | 152 ----------------------------------------------- doc/manual.txt | 65 ++++++++++++++++++++ 2 files changed, 65 insertions(+), 152 deletions(-) delete mode 100644 doc/abstypes.txt diff --git a/doc/abstypes.txt b/doc/abstypes.txt deleted file mode 100644 index c5827745ab..0000000000 --- a/doc/abstypes.txt +++ /dev/null @@ -1,152 +0,0 @@ -============== -Abstract types -============== - -.. contents:: - -Abstract types in Nimrod provide a means to model different `units`:idx: of -a `base type`:idx:. - - -Use case 1: SQL strings ------------------------ -An SQL statement that is passed from Nimrod to an SQL database might be -modelled as a string. However, using string templates and filling in the -values is vulnerable to the famous `SQL injection attack`:idx:\: - -.. code-block:: nimrod - proc query(db: TDbHandle, statement: TSQL) = ... - - var - username: string - - db.query("SELECT FROM users WHERE name = '$1'" % username) - # Horrible security hole, but the compiler does not mind! - -This can be avoided by distinguishing strings that contain SQL from strings -that don't. Abstract types provide a means to introduce a new string type -``TSQL`` that is incompatible with ``string``: - -.. code-block:: nimrod - type - TSQL = abstract string - - proc query(db: TDbHandle, statement: TSQL) = ... - - var - username: string - - db.query("SELECT FROM users WHERE name = '$1'" % username) - # Error at compile time: `query` expects an SQL string! - - -It is an essential property of abstract types that they **do not** imply a -subtype relation between the abtract type and its base type. Explict type -conversions from ``string`` to ``TSQL`` are allowed: - -.. code-block:: nimrod - proc properQuote(s: string): TSQL = - # quotes a string properly for an SQL statement - ... - - proc `%` (frmt: TSQL, values: openarray[string]): TSQL = - # quote each argument: - var v = values.each(properQuote) - # we need a temporary type for the type conversion :-( - type TStrSeq = seq[string] - # call strutils.`%`: - result = TSQL(string(frmt) % TStrSeq(v)) - - db.query("SELECT FROM users WHERE name = $1".TSQL % username) - -Now we have compile-time checking against SQL injection attacks. -Since ``"".TSQL`` is transformed to ``TSQL("")`` no new syntax is needed -for nice looking ``TSQL`` string literals. - - - -Use case 2: Money ------------------ -Different currencies should not be mixed in monetary calculations. Abstract -types are a perfect tool to model different currencies: - -.. code-block:: nimrod - type - TDollar = abstract int - TEuro = abstract int - - var - d: TDollar - e: TEuro - - echo d + 12 - # Error: cannot add a number with no unit with a ``TDollar`` - -Unfortunetaly, ``d + 12.TDollar`` is not allowed either, -because ``+`` is defined for ``int`` (among others), not for ``TDollar``. So -we define our own ``+`` for dollars: - -.. code-block:: - proc `+` (x, y: TDollar): TDollar = - result = TDollar(int(x) + int(y)) - -It does not make sense to multiply a dollar with a dollar, but with a -number without unit; and the same holds for division: - -.. code-block:: - proc `*` (x: TDollar, y: int): TDollar = - result = TDollar(int(x) * y) - - proc `*` (x: int, y: TDollar): TDollar = - result = TDollar(x * int(y)) - - proc `div` ... - -This quickly gets tedious. The implementations are trivial and the compiler -should not generate all this code only to optimize it away later - after all -``+`` for dollars should produce the same binary code as ``+`` for ints. -The pragma ``borrow`` has been designed to solve this problem; in principle -it generates the trivial implementation for us: - -.. code-block:: nimrod - proc `*` (x: TDollar, y: int): TDollar {.borrow.} - proc `*` (x: int, y: TDollar): TDollar {.borrow.} - proc `div` (x: TDollar, y: int): TDollar {.borrow.} - -The ``borrow`` pragma makes the compiler to use the same implementation as -the proc that deals with the abstract type's base type, so no code is -generated. - -But it seems we still have to repeat all this boilerplate code for -the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism: - -.. code-block:: nimrod - template Additive(typ: typeDesc): stmt = - proc `+` *(x, y: typ): typ {.borrow.} - proc `-` *(x, y: typ): typ {.borrow.} - - # unary operators: - proc `+` *(x: typ): typ {.borrow.} - proc `-` *(x: typ): typ {.borrow.} - - template Multiplicative(typ, base: typeDesc): stmt = - proc `*` *(x: typ, y: base): typ {.borrow.} - proc `*` *(x: base, y: typ): typ {.borrow.} - proc `div` *(x: typ, y: base): typ {.borrow.} - proc `mod` *(x: typ, y: base): typ {.borrow.} - - template Comparable(typ: typeDesc): stmt = - proc `<` * (x, y: typ): bool {.borrow.} - proc `<=` * (x, y: typ): bool {.borrow.} - proc `==` * (x, y: typ): bool {.borrow.} - - template DefineCurrency(typ, base: expr): stmt = - type - typ* = abstract base - Additive(typ) - Multiplicative(typ, base) - Comparable(typ) - - DefineCurrency(TDollar, int) - DefineCurrency(TEuro, int) - diff --git a/doc/manual.txt b/doc/manual.txt index d3a330e3a2..4f0cf1d688 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -1542,6 +1542,10 @@ of a distinct type that it **does not** imply a subtype relation between it and its base type. Explicit type conversions from a distinct type to its base type and vice versa are allowed. + +Modelling currencies +~~~~~~~~~~~~~~~~~~~~ + A distinct type can be used to model different physical `units`:idx: with a numerical base type, for example. The following example models currencies. @@ -1649,6 +1653,67 @@ certain builtin operations to be lifted: Currently only the dot accessor can be borrowed in this way. +Avoiding SQL injection attacks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An SQL statement that is passed from Nimrod to an SQL database might be +modelled as a string. However, using string templates and filling in the +values is vulnerable to the famous `SQL injection attack`:idx:\: + +.. code-block:: nimrod + import strutils + + proc query(db: TDbHandle, statement: string) = ... + + var + username: string + + db.query("SELECT FROM users WHERE name = '$1'" % username) + # Horrible security hole, but the compiler does not mind! + +This can be avoided by distinguishing strings that contain SQL from strings +that don't. Distinct types provide a means to introduce a new string type +``TSQL`` that is incompatible with ``string``: + +.. code-block:: nimrod + type + TSQL = distinct string + + proc query(db: TDbHandle, statement: TSQL) = ... + + var + username: string + + db.query("SELECT FROM users WHERE name = '$1'" % username) + # Error at compile time: `query` expects an SQL string! + + +It is an essential property of abstract types that they **do not** imply a +subtype relation between the abtract type and its base type. Explict type +conversions from ``string`` to ``TSQL`` are allowed: + +.. code-block:: nimrod + import strutils, sequtils + + proc properQuote(s: string): TSQL = + # quotes a string properly for an SQL statement + return TSQL(s) + + proc `%` (frmt: TSQL, values: openarray[string]): TSQL = + # quote each argument: + let v = values.mapIt(TSQL, properQuote(it)) + # we need a temporary type for the type conversion :-( + type TStrSeq = seq[string] + # call strutils.`%`: + result = TSQL(string(frmt) % TStrSeq(v)) + + db.query("SELECT FROM users WHERE name = '$1'".TSQL % [username]) + +Now we have compile-time checking against SQL injection attacks. Since +``"".TSQL`` is transformed to ``TSQL("")`` no new syntax is needed for nice +looking ``TSQL`` string literals. The hypothetical ``TSQL`` type actually +exists in the library as the `TSqlQuery type `_ of +modules like `db_sqlite `_. Void type From 502f7bffa35d25593ec822ddf8d8c7b7210b30dc Mon Sep 17 00:00:00 2001 From: EXetoC Date: Tue, 13 May 2014 15:03:58 +0200 Subject: [PATCH 12/34] Resolve type mismatches. --- compiler/ccgexprs.nim | 2 +- koch.nim | 4 ++-- lib/system/sets.nim | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 94a6f4781b..39333a80d3 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -484,7 +484,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = opr: array[mUnaryMinusI..mAbsI64, string] = [ mUnaryMinusI: "((NI$2)-($1))", mUnaryMinusI64: "-($1)", - mAbsI: "(NI$2)abs($1)", + mAbsI: "($1 > 0? ($1) : -($1))", mAbsI64: "($1 > 0? ($1) : -($1))"] var a: TLoc diff --git a/koch.nim b/koch.nim index c203e0fd09..58c746ee83 100644 --- a/koch.nim +++ b/koch.nim @@ -152,7 +152,7 @@ proc boot(args: string) = copyExe(findStartNimrod(), 0.thVersion) for i in 0..2: echo "iteration: ", i+1 - exec i.thVersion & " cc $# $# compiler" / "nimrod.nim" % [bootOptions, args] + exec i.thVersion & " cpp $# $# compiler" / "nimrod.nim" % [bootOptions, args] if sameFileContent(output, i.thVersion): copyExe(output, finalDest) echo "executables are equal: SUCCESS!" @@ -282,7 +282,7 @@ proc tests(args: string) = proc temp(args: string) = var output = "compiler" / "nimrod".exe var finalDest = "bin" / "nimrod_temp".exe - exec("nimrod c compiler" / "nimrod") + exec("nimrod cpp compiler" / "nimrod") copyExe(output, finalDest) if args.len > 0: exec(finalDest & " " & args) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index 043d375335..794c65cb8e 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -10,7 +10,7 @@ # set handling type - TNimSet = array [0..4*2048-1, int8] + TNimSet = array [0..4*2048-1, uint8] proc countBits32(n: int32): int {.compilerproc.} = var v = n @@ -25,4 +25,4 @@ proc countBits64(n: int64): int {.compilerproc.} = proc cardSet(s: TNimSet, len: int): int {.compilerproc.} = result = 0 for i in countup(0, len-1): - inc(result, countBits32(int32(ze(s[i])))) + inc(result, countBits32(int32(s[i]))) From f66f43bca031375339f7e232a6ae62107e476c64 Mon Sep 17 00:00:00 2001 From: EXetoC Date: Wed, 14 May 2014 18:12:47 +0200 Subject: [PATCH 13/34] Fix more 'undeclared identifier' errors. --- compiler/cgen.nim | 3 ++- compiler/rodutils.nim | 2 +- lib/pure/oids.nim | 4 ++-- lib/pure/osproc.nim | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 8d66d7a3b1..198b1187d8 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -503,7 +503,8 @@ proc assignLocalVar(p: BProc, s: PSym) = if sfRegister in s.flags: app(decl, " register") #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds: # app(decl, " GC_GUARD") - if sfVolatile in s.flags or p.nestedTryStmts.len > 0: + if sfVolatile in s.flags or (p.nestedTryStmts.len > 0 and + gCmd != cmdCompileToCpp): app(decl, " volatile") appf(decl, " $1;$n", [s.loc.r]) else: diff --git a/compiler/rodutils.nim b/compiler/rodutils.nim index 4433ed4abd..09b92cd8ad 100644 --- a/compiler/rodutils.nim +++ b/compiler/rodutils.nim @@ -10,7 +10,7 @@ ## Serialization utilities for the compiler. import strutils -proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", nodecl, varargs.} +proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", header: "", nodecl, varargs.} proc toStrMaxPrecision*(f: BiggestFloat): string = if f != f: diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index b3e74d2a1a..2843e6c656 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -62,9 +62,9 @@ var proc genOid*(): TOid = ## generates a new OID. - proc rand(): cint {.importc: "rand", nodecl.} + proc rand(): cint {.importc: "rand", header: "", nodecl.} proc gettime(dummy: ptr cint): cint {.importc: "time", header: "".} - proc srand(seed: cint) {.importc: "srand", nodecl.} + proc srand(seed: cint) {.importc: "srand", header: "", nodecl.} var t = gettime(nil) diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 6e250f9d54..d2ada70148 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -903,7 +903,7 @@ elif not defined(useNimRtl): createStream(p.errStream, p.errHandle, fmRead) return p.errStream - proc csystem(cmd: cstring): cint {.nodecl, importc: "system".} + proc csystem(cmd: cstring): cint {.nodecl, importc: "system", header: "".} proc execCmd(command: string): int = when defined(linux): From 444e8dd8bf3ff29556a5683fd1b16ef7ce1fa3e2 Mon Sep 17 00:00:00 2001 From: EXetoC Date: Wed, 14 May 2014 18:13:15 +0200 Subject: [PATCH 14/34] Revert changes to koch. --- koch.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/koch.nim b/koch.nim index 58c746ee83..4d0ac0254d 100644 --- a/koch.nim +++ b/koch.nim @@ -152,7 +152,7 @@ proc boot(args: string) = copyExe(findStartNimrod(), 0.thVersion) for i in 0..2: echo "iteration: ", i+1 - exec i.thVersion & " cpp $# $# compiler" / "nimrod.nim" % [bootOptions, args] + exec i.thVersion & " c $# $# compiler" / "nimrod.nim" % [bootOptions, args] if sameFileContent(output, i.thVersion): copyExe(output, finalDest) echo "executables are equal: SUCCESS!" @@ -282,7 +282,7 @@ proc tests(args: string) = proc temp(args: string) = var output = "compiler" / "nimrod".exe var finalDest = "bin" / "nimrod_temp".exe - exec("nimrod cpp compiler" / "nimrod") + exec("nimrod c compiler" / "nimrod") copyExe(output, finalDest) if args.len > 0: exec(finalDest & " " & args) From e54ab22bf9a67353e5a70f56e7801624d68ca4f5 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Wed, 14 May 2014 23:35:46 +0100 Subject: [PATCH 15/34] Fixes #1197. --- lib/pure/selectors.nim | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index f630ba2351..498f41e830 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -49,9 +49,10 @@ when defined(linux) or defined(nimdoc): ## Registers file descriptor ``fd`` to selector ``s`` with a set of TEvent ## ``events``. var event = createEventStruct(events, fd) - if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0: - OSError(OSLastError()) - + if events != {}: + if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0: + OSError(OSLastError()) + var key = PSelectorKey(fd: fd, events: events, data: data) s.fds[fd] = key @@ -61,11 +62,27 @@ when defined(linux) or defined(nimdoc): events: set[TEvent]): PSelectorKey {.discardable.} = ## Updates the events which ``fd`` wants notifications for. if s.fds[fd].events != events: - var event = createEventStruct(events, fd) + if events == {}: + # This fd is idle -- it should not be registered to epoll. + # But it should remain a part of this selector instance. + # This is to prevent epoll_wait from returning immediately + # because its got fds which are waiting for no events and + # are therefore constantly ready. (leading to 100% CPU usage). + if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0: + OSError(OSLastError()) + s.fds[fd].events = events + else: + var event = createEventStruct(events, fd) + if s.fds[fd].events == {}: + # This fd is idle. It's not a member of this epoll instance and must + # be re-registered. + if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0: + OSError(OSLastError()) + else: + if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0: + OSError(OSLastError()) + s.fds[fd].events = events - s.fds[fd].events = events - if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0: - OSError(OSLastError()) result = s.fds[fd] proc unregister*(s: PSelector, fd: TSocketHandle): PSelectorKey {.discardable.} = @@ -123,7 +140,10 @@ when defined(linux) or defined(nimdoc): ## Determines whether selector contains a file descriptor. if s.fds.hasKey(fd): # Ensure the underlying epoll instance still contains this fd. - result = epollHasFd(s, fd) + if s.fds[fd].events != {}: + result = epollHasFd(s, fd) + else: + result = true else: return false From a568c6102fdc29074ddd7309544c0487dfecb25c Mon Sep 17 00:00:00 2001 From: flaviut Date: Fri, 16 May 2014 17:47:39 -0400 Subject: [PATCH 16/34] Make codegen for `1` and similar valid --- compiler/ccgtypes.nim | 47 ++++--------------------------------------- compiler/ccgutils.nim | 21 +++++++++++++++++++ compiler/jsgen.nim | 12 ----------- 3 files changed, 25 insertions(+), 55 deletions(-) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index f51e66897d..7c11d3e9af 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -11,49 +11,10 @@ # ------------------------- Name Mangling -------------------------------- -proc mangleField(name: string): string = - case name[0] - of 'a'..'z': - result = "" - add(result, chr(ord(name[0]) - ord('a') + ord('A'))) - of '0'..'9', 'A'..'Z': - result = "" - add(result, name[0]) - else: result = "HEX" & toHex(ord(name[0]), 2) - for i in countup(1, len(name) - 1): - case name[i] - of 'A'..'Z': - add(result, chr(ord(name[i]) - ord('A') + ord('a'))) - of '_': - discard - of 'a'..'z', '0'..'9': - add(result, name[i]) - else: - add(result, "HEX") - add(result, toHex(ord(name[i]), 2)) - -proc mangle(name: string): string = - when false: - case name[0] - of 'a'..'z': - result = "" - add(result, chr(ord(name[0]) - ord('a') + ord('A'))) - of '0'..'9', 'A'..'Z': - result = "" - add(result, name[0]) - else: result = "HEX" & toHex(ord(name[0]), 2) - result = "" - for i in countup(0, len(name) - 1): - case name[i] - of 'A'..'Z': - add(result, chr(ord(name[i]) - ord('A') + ord('a'))) - of '_': - discard - of 'a'..'z', '0'..'9': - add(result, name[i]) - else: - add(result, "HEX") - add(result, toHex(ord(name[i]), 2)) +proc mangleField(name: string): string = + result = mangle(name) + if name[0] in 'a'..'z': + result[0] = name[0].toUpper proc isKeyword(w: PIdent): bool = # nimrod and C++ share some keywords diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 1d8f0158b0..9beb08a219 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -161,6 +161,27 @@ proc makeSingleLineCString*(s: string): string = result.add(c.toCChar) result.add('\"') +proc mangle*(name: string): string = + result = "" + case name[0] + of Letters: + result.add(name[0].toLower) + of Digits: + result.add("N" & name[0]) + else: + result = "HEX" & toHex(ord(name[0]), 2) + for i in 1..(name.len-1): + let c = name[i] + case c + of 'A'..'Z': + add(result, c.toLower) + of '_': + discard + of 'a'..'z', '0'..'9': + add(result, c) + else: + add(result, "HEX" & toHex(ord(c), 2)) + proc makeLLVMString*(s: string): PRope = const MaxLineLength = 64 result = nil diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 373a11e9ac..6687e2e8ec 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -136,18 +136,6 @@ proc mapType(typ: PType): TJSTypeKind = of tyProc: result = etyProc of tyCString: result = etyString -proc mangle(name: string): string = - result = "" - for i in countup(0, len(name) - 1): - case name[i] - of 'A'..'Z': - add(result, chr(ord(name[i]) - ord('A') + ord('a'))) - of '_': - discard - of 'a'..'z', '0'..'9': - add(result, name[i]) - else: add(result, 'X' & toHex(ord(name[i]), 2)) - proc mangleName(s: PSym): PRope = result = s.loc.r if result == nil: From 2026137fc1a4d46207ced53a6c1efc0988775cb9 Mon Sep 17 00:00:00 2001 From: flaviut Date: Fri, 16 May 2014 19:27:15 -0400 Subject: [PATCH 17/34] Add test for #1081 --- tests/ccgbugs/tbug1081.nim | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/ccgbugs/tbug1081.nim diff --git a/tests/ccgbugs/tbug1081.nim b/tests/ccgbugs/tbug1081.nim new file mode 100644 index 0000000000..71628feece --- /dev/null +++ b/tests/ccgbugs/tbug1081.nim @@ -0,0 +1,17 @@ +discard """ + output: '''1 +0 +0 +0''' +""" + +proc `1/1`() = echo(1 div 1) +template `1/2`() = echo(1 div 2) +var `1/3` = 1 div 4 +`1/3` = 1 div 3 # oops, 1/3!=1/4 +let `1/4` = 1 div 4 + +`1/1`() +`1/2`() +echo `1/3` +echo `1/4` From 8a183dac78a5076d421dcbff263c6d163fe2a7fc Mon Sep 17 00:00:00 2001 From: Charlie Date: Sun, 18 May 2014 15:13:37 -0400 Subject: [PATCH 18/34] added random(max: float): float support to windows --- lib/pure/math.nim | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index e4aecd2726..24a2ec7fa7 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -135,12 +135,11 @@ proc random*(max: int): int {.gcsafe.} ## which initializes the random number generator with a "random" ## number, i.e. a tickcount. -when not defined(windows): - proc random*(max: float): float {.gcsafe.} - ## returns a random number in the range 0..".} proc random(max: float): float = result = drand48() * max - + when defined(windows): + proc random(max: float): float = + # we are hardcodeing this because + # importcing macros is extremely problematic + # and because the value is publicly documented + # on MSDN and very unlikely to change + const rand_max = 32767 + result = (float(rand()) / float(rand_max)) * max proc randomize() = randomize(cast[int](epochTime())) From d32b4272c3eb7cb1356fad6279bd3b7b27158508 Mon Sep 17 00:00:00 2001 From: Charlie Date: Sun, 18 May 2014 15:16:35 -0400 Subject: [PATCH 19/34] added a note about random(max: float): float's resolution on windows --- lib/pure/math.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 24a2ec7fa7..78ea02cbfc 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -139,7 +139,8 @@ proc random*(max: float): float {.gcsafe.} ## returns a random number in the range 0.. Date: Sun, 18 May 2014 18:48:12 -0400 Subject: [PATCH 20/34] added note about `$` for cstrings to the manual --- doc/manual.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/manual.txt b/doc/manual.txt index d3a330e3a2..fe4f0c0383 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -965,6 +965,14 @@ stack roots conservatively. One can use the builtin procs ``GC_ref`` and ``GC_unref`` to keep the string data alive for the rare cases where it does not work. +A `$` proc is defined for cstrings that returns a string. Thus to get a nimrod +string from a cstring: + +.. code-block:: nimrod + var str: string = "Hello!" + var cstr: cstring = s + var newstr: string = $cstr + Structured types ---------------- From 657a00056e382b02c4803dad50310d736cbb4544 Mon Sep 17 00:00:00 2001 From: Billingsly Wetherfordshire Date: Mon, 19 May 2014 19:05:57 -0500 Subject: [PATCH 21/34] `=>` macro tripped on generic return types example fail `(a:int,b:int) -> Foo[int] => Foo[int](x: a + b)` --- lib/pure/future.nim | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/pure/future.nim b/lib/pure/future.nim index e0e4c4176b..b7df05207d 100644 --- a/lib/pure/future.nim +++ b/lib/pure/future.nim @@ -18,7 +18,6 @@ proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} = result = newNimNode(nnkProcTy) var formalParams = newNimNode(nnkFormalParams) - expectKind(b, nnkIdent) formalParams.add b case p.kind From 876cad3a914a42ab5ead3d5c9a610bb10790276c Mon Sep 17 00:00:00 2001 From: boydgreenfield Date: Tue, 20 May 2014 16:57:33 -0400 Subject: [PATCH 22/34] Fix missing import in nimprof.nim when --threads:on --- lib/pure/nimprof.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim index 3d0cc21541..132ea9462e 100644 --- a/lib/pure/nimprof.nim +++ b/lib/pure/nimprof.nim @@ -60,6 +60,7 @@ when not defined(memProfiler): else: interval = intervalInUs * 1000 - tickCountCorrection when withThreads: + import locks var profilingLock: TLock From fd352cc0b541074d845e1ad275b8568ed460e24f Mon Sep 17 00:00:00 2001 From: boydgreenfield Date: Tue, 20 May 2014 17:02:51 -0400 Subject: [PATCH 23/34] Revert 876cad3a - making nimprof fix on a new branch --- lib/pure/nimprof.nim | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim index 132ea9462e..3d0cc21541 100644 --- a/lib/pure/nimprof.nim +++ b/lib/pure/nimprof.nim @@ -60,7 +60,6 @@ when not defined(memProfiler): else: interval = intervalInUs * 1000 - tickCountCorrection when withThreads: - import locks var profilingLock: TLock From 35e603b89c11c41094119d7013fb5a64f0a58791 Mon Sep 17 00:00:00 2001 From: Nick Greenfield Date: Tue, 20 May 2014 17:07:20 -0400 Subject: [PATCH 24/34] Fix nimprof import error when --threads:on. --- lib/pure/nimprof.nim | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim index 3d0cc21541..ab7cd1944d 100644 --- a/lib/pure/nimprof.nim +++ b/lib/pure/nimprof.nim @@ -58,8 +58,9 @@ when not defined(memProfiler): ## instruction count measure instead then. if intervalInUs <= 0: interval = 0 else: interval = intervalInUs * 1000 - tickCountCorrection - + when withThreads: + import locks var profilingLock: TLock @@ -72,7 +73,7 @@ proc hookAux(st: TStackTrace, costs: int) = var last = high(st) while last > 0 and isNil(st[last]): dec last var h = hash(pointer(st[last])) and high(profileData) - + # we use probing for maxChainLen entries and replace the encountered entry # with the minimal 'total' value: if emptySlots == 0: @@ -133,7 +134,7 @@ else: hookAux(st, 1) elif getticks() - t0 > interval: hookAux(st, 1) - t0 = getticks() + t0 = getticks() proc getTotal(x: ptr TProfileEntry): int = result = if isNil(x): 0 else: x.total @@ -145,7 +146,7 @@ proc `//`(a, b: int): string = result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2)) proc writeProfile() {.noconv.} = - when defined(system.TStackTrace): + when defined(system.TStackTrace): system.profilerHook = nil const filename = "profile_results.txt" echo "writing " & filename & "..." @@ -156,7 +157,7 @@ proc writeProfile() {.noconv.} = var entries = 0 for i in 0..high(profileData): if profileData[i] != nil: inc entries - + var perProc = initCountTable[string]() for i in 0..entries-1: var dups = initSet[string]() @@ -166,7 +167,7 @@ proc writeProfile() {.noconv.} = let p = $procname if not containsOrIncl(dups, p): perProc.inc(p, profileData[i].total) - + var sum = 0 # only write the first 100 entries: for i in 0..min(100, entries-1): From 6a38d36239b9c9acd205b0ad3c7dd3cdbed91364 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 23 May 2014 13:14:28 +0100 Subject: [PATCH 25/34] Rename asyncdispatch.close to asyncdispatch.closeSocket. --- lib/pure/asyncdispatch.nim | 4 ++-- lib/pure/asyncnet.nim | 2 +- tests/async/tasyncawait.nim | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index fcf9478317..f429454605 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -532,7 +532,7 @@ when defined(windows) or defined(nimdoc): result.TSocketHandle.setBlocking(false) register(result) - proc close*(socket: TAsyncFD) = + proc closeSocket*(socket: TAsyncFD) = ## Closes a socket and ensures that it is unregistered. socket.TSocketHandle.close() getGlobalDispatcher().handles.excl(socket) @@ -581,7 +581,7 @@ else: result.TSocketHandle.setBlocking(false) register(result) - proc close*(sock: TAsyncFD) = + proc closeSocket*(sock: TAsyncFD) = let disp = getGlobalDispatcher() sock.TSocketHandle.close() disp.selector.unregister(sock.TSocketHandle) diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 9394078c83..d16c85c58e 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -220,7 +220,7 @@ proc listen*(socket: PAsyncSocket, backlog = SOMAXCONN) = proc close*(socket: PAsyncSocket) = ## Closes the socket. - socket.fd.TAsyncFD.close() + socket.fd.TAsyncFD.closeSocket() # TODO SSL when isMainModule: diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim index ffceeaee68..da49526776 100644 --- a/tests/async/tasyncawait.nim +++ b/tests/async/tasyncawait.nim @@ -23,19 +23,19 @@ proc launchSwarm(port: TPort) {.async.} = await connect(sock, "localhost", port) when true: await sendMessages(sock) - close(sock) + closeSocket(sock) else: # Issue #932: https://github.com/Araq/Nimrod/issues/932 var msgFut = sendMessages(sock) msgFut.callback = proc () = - close(sock) + closeSocket(sock) proc readMessages(client: TAsyncFD) {.async.} = while true: var line = await recvLine(client) if line == "": - close(client) + closeSocket(client) clientCount.inc break else: From 05953381e93aff2d3ae1b5b3c59e3625f2bf7763 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Sat, 24 May 2014 08:41:12 -0400 Subject: [PATCH 26/34] Fix assertion in queues.dequeue --- lib/pure/collections/queues.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/collections/queues.nim b/lib/pure/collections/queues.nim index 5481272f04..db1d505694 100644 --- a/lib/pure/collections/queues.nim +++ b/lib/pure/collections/queues.nim @@ -59,7 +59,7 @@ proc enqueue*[T](q: var TQueue[T], item: T) = proc dequeue*[T](q: var TQueue[T]): T = ## removes and returns the first element of the queue `q`. - assert q.count > 0 + assert q.len > 0 dec q.count result = q.data[q.rd] q.rd = (q.rd + 1) and q.mask From d43c06d4c5bc723e182cf6448bd592685330feab Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Sat, 24 May 2014 08:58:40 -0400 Subject: [PATCH 27/34] Manual merge of pull request #1138 --- lib/windows/windows.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/windows/windows.nim b/lib/windows/windows.nim index 7070833ce7..df6ad954bc 100644 --- a/lib/windows/windows.nim +++ b/lib/windows/windows.nim @@ -62,7 +62,7 @@ type # BaseTsd.h -- Type definitions for the basic sized types type # WinDef.h -- Basic Windows Type Definitions # BaseTypes - UINT* = int32 + WINUINT* = int32 ULONG* = int PULONG* = ptr int USHORT* = int16 @@ -23481,7 +23481,7 @@ proc ListView_EnsureVisible(hwndLV: HWND, i, fPartialOK: int32): LRESULT = MAKELPARAM(fPartialOK, 0)) proc ListView_FindItem(wnd: HWND, iStart: int32, lvfi: var LV_FINDINFO): int32 = - result = SendMessage(wnd, LVM_FINDITEM, WPARAM(iStart), + result = SendMessage(wnd, LVM_FINDITEM, WPARAM(iStart), cast[LPARAM](addr(lvfi))).int32 proc ListView_GetBkColor(wnd: HWND): LRESULT = From 0dc770332eded939d953397a8725bbc9274dd35e Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Sat, 24 May 2014 09:12:07 -0400 Subject: [PATCH 28/34] Fix issue #1134 Adds the necessary imports for selectors under MacOSX --- lib/pure/selectors.nim | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 498f41e830..8564626317 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -11,9 +11,12 @@ import tables, os, unsigned, hashes -when defined(linux): import posix, epoll -elif defined(windows): import winlean -else: import posix +when defined(linux) or defined(macosx): + import posix, epoll +elif defined(windows): + import winlean +else: + import posix proc hash*(x: TSocketHandle): THash {.borrow.} proc `$`*(x: TSocketHandle): string {.borrow.} From b386d382089c31f76ab75d26fffc3a9ea4475b4a Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 23 May 2014 13:53:27 +0100 Subject: [PATCH 29/34] Add asyncdispatch.unregister. --- lib/pure/asyncdispatch.nim | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index f429454605..d972592a5c 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -537,6 +537,10 @@ when defined(windows) or defined(nimdoc): socket.TSocketHandle.close() getGlobalDispatcher().handles.excl(socket) + proc unregister*(fd: TAsyncFD) = + ## Unregisters ``fd``. + getGlobalDispatcher().handles.excl(fd) + initAll() else: import selectors @@ -586,6 +590,9 @@ else: sock.TSocketHandle.close() disp.selector.unregister(sock.TSocketHandle) + proc unregister*(fd: TAsyncFD) = + getGlobalDispatcher().selector.unregister(fd.TSocketHandle) + proc addRead(sock: TAsyncFD, cb: TCallback) = let p = getGlobalDispatcher() if sock.TSocketHandle notin p.selector: From d54b902441e6ac6919c0f882b7172b1d36de5a99 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 24 May 2014 15:51:41 +0100 Subject: [PATCH 30/34] Modified future behaviour when completing with an exception. Futures will now raise the exception if they did not have a callback associated with them. --- lib/pure/asyncdispatch.nim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index d972592a5c..9f1711f088 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -71,6 +71,11 @@ proc fail*[T](future: PFuture[T], error: ref EBase) = future.error = error if future.cb != nil: future.cb() + else: + # This is to prevent exceptions from being silently ignored when a future + # is discarded. + # TODO: This may turn out to be a bad idea. + raise error proc `callback=`*(future: PFutureBase, cb: proc () {.closure,gcsafe.}) = ## Sets the callback proc to be called when the future completes. From b4366366d1aa235bdf24ac3b739652960f5161d0 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 25 May 2014 13:09:18 +0100 Subject: [PATCH 31/34] Clean createVar template. --- lib/pure/asyncdispatch.nim | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 9f1711f088..87ee83ad9c 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -813,8 +813,9 @@ proc generateExceptionCheck(futSym, elseNode[0].add rootReceiver result.add elseNode -template createVar(futSymName: string, asyncProc: PNimrodNode, - valueReceiver, rootReceiver: expr) {.immediate, dirty.} = +template createVar(result: var PNimrodNode, futSymName: string, + asyncProc: PNimrodNode, + valueReceiver, rootReceiver: expr) = result = newNimNode(nnkStmtList) var futSym = genSym(nskVar, "future") result.add newVarStmt(futSym, asyncProc) # -> var future = y @@ -851,7 +852,7 @@ proc processBody(node, retFutureSym: PNimrodNode, of nnkCall: # await foo(p, x) var futureValue: PNimrodNode - createVar("future" & $node[1][0].toStrLit, node[1], futureValue, + result.createVar("future" & $node[1][0].toStrLit, node[1], futureValue, futureValue) else: error("Invalid node kind in 'await', got: " & $node[1].kind) @@ -859,7 +860,7 @@ proc processBody(node, retFutureSym: PNimrodNode, node[1][0].ident == !"await": # foo await x var newCommand = node - createVar("future" & $node[0].toStrLit, node[1][1], newCommand[1], + result.createVar("future" & $node[0].toStrLit, node[1][1], newCommand[1], newCommand) of nnkVarSection, nnkLetSection: @@ -868,7 +869,7 @@ proc processBody(node, retFutureSym: PNimrodNode, if node[0][2][0].ident == !"await": # var x = await y var newVarSection = node # TODO: Should this use copyNimNode? - createVar("future" & $node[0][0].ident, node[0][2][1], + result.createVar("future" & $node[0][0].ident, node[0][2][1], newVarSection[0][2], newVarSection) else: discard of nnkAsgn: @@ -877,14 +878,14 @@ proc processBody(node, retFutureSym: PNimrodNode, if node[1][0].ident == !"await": # x = await y var newAsgn = node - createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn) + result.createVar("future" & $node[0].toStrLit, node[1][1], newAsgn[1], newAsgn) else: discard of nnkDiscardStmt: # discard await x if node[0].kind != nnkEmpty and node[0][0].kind == nnkIdent and node[0][0].ident == !"await": var newDiscard = node - createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1], + result.createVar("futureDiscard_" & $toStrLit(node[0][1]), node[0][1], newDiscard[0], newDiscard) of nnkTryStmt: # try: await x; except: ... From 225d4f410d8b8637ae0cf157a7d29e403860fe10 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sun, 25 May 2014 13:54:46 +0100 Subject: [PATCH 32/34] Added powerpc to the list of CPUs that C sources are built for. --- compiler/nimrod.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 0dc44a7c99..8b2353aaba 100644 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -3,7 +3,7 @@ Name: "Nimrod" Version: "$version" Platforms: """ windows: i386;amd64 - linux: i386;amd64;powerpc64;arm;sparc;mips + linux: i386;amd64;powerpc64;arm;sparc;mips;powerpc macosx: i386;amd64;powerpc64 solaris: i386;amd64;sparc freebsd: i386;amd64 From f10f9c4b7ed2dff82b62f15d4f77f049edd0f2fd Mon Sep 17 00:00:00 2001 From: Varriount Date: Sun, 25 May 2014 11:35:10 -0400 Subject: [PATCH 33/34] Update selectors.nim Fixed selectors.nim on macosx --- lib/pure/selectors.nim | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 8564626317..bea1a3dd4c 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -11,7 +11,7 @@ import tables, os, unsigned, hashes -when defined(linux) or defined(macosx): +when defined(linux): import posix, epoll elif defined(windows): import winlean @@ -32,7 +32,36 @@ type TReadyInfo* = tuple[key: PSelectorKey, events: set[TEvent]] -when defined(linux) or defined(nimdoc): +when defined(nimdoc): + type + PSelector* = ref object + ## An object which holds file descripters to be checked for read/write + ## status. + fds: TTable[TSocketHandle, PSelectorKey] + + proc register*(s: PSelector, fd: TSocketHandle, events: set[TEvent], + data: PObject): PSelectorKey {.discardable.} = + ## Registers file descriptor ``fd`` to selector ``s`` with a set of TEvent + ## ``events``. + + proc update*(s: PSelector, fd: TSocketHandle, + events: set[TEvent]): PSelectorKey {.discardable.} = + ## Updates the events which ``fd`` wants notifications for. + + proc select*(s: PSelector, timeout: int): seq[TReadyInfo] = + ## The ``events`` field of the returned ``key`` contains the original events + ## for which the ``fd`` was bound. This is contrary to the ``events`` field + ## of the ``TReadyInfo`` tuple which determines which events are ready + ## on the ``fd``. + + proc contains*(s: PSelector, fd: TSocketHandle): bool = + ## Determines whether selector contains a file descriptor. + + proc `[]`*(s: PSelector, fd: TSocketHandle): PSelectorKey = + ## Retrieves the selector key for ``fd``. + + +elif defined(linux): type PSelector* = ref object epollFD: cint @@ -154,7 +183,7 @@ when defined(linux) or defined(nimdoc): ## Retrieves the selector key for ``fd``. return s.fds[fd] -else: +elif defined(openbsd) or defined(macosx): # TODO: kqueue for bsd/mac os x. type PSelector* = ref object @@ -253,7 +282,7 @@ proc contains*(s: PSelector, key: PSelectorKey): bool = ## the new one may have the same value. return key.fd in s and s.fds[key.fd] == key -when isMainModule: +when isMainModule and not defined(nimdoc): # Select() import sockets type From 1d6c05edc399e31919114f2b07519ae79ae1b804 Mon Sep 17 00:00:00 2001 From: Varriount Date: Sun, 25 May 2014 12:20:24 -0400 Subject: [PATCH 34/34] Update selectors.nim --- lib/pure/selectors.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index bea1a3dd4c..3af5f699cf 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -183,7 +183,7 @@ elif defined(linux): ## Retrieves the selector key for ``fd``. return s.fds[fd] -elif defined(openbsd) or defined(macosx): +elif not defined(nimdoc): # TODO: kqueue for bsd/mac os x. type PSelector* = ref object