From 6cf8a72d498f5cb8a532c2ff3259bc7aecf474ef Mon Sep 17 00:00:00 2001 From: Dmitry Atamanov Date: Fri, 5 Jan 2018 19:32:05 +0300 Subject: [PATCH 1/4] Windows: fixes getch bug; fixes #6966 (#7031) --- lib/pure/terminal.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index ef5a95ed24..f15cee66ac 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -634,7 +634,10 @@ proc getch*(): char = doAssert(readConsoleInput(fd, addr(keyEvent), 1, addr(numRead)) != 0) if numRead == 0 or keyEvent.eventType != 1 or keyEvent.bKeyDown == 0: continue - return char(keyEvent.uChar) + if keyEvent.uChar == 0: + return char(keyEvent.wVirtualKeyCode) + else: + return char(keyEvent.uChar) else: let fd = getFileHandle(stdin) var oldMode: Termios From 6ca563dd2e6380e4e2062b9129f582a4910baf68 Mon Sep 17 00:00:00 2001 From: Dmitry Atamanov Date: Fri, 5 Jan 2018 19:36:56 +0300 Subject: [PATCH 2/4] Add a more number parsers to the scanf macro (#6985) --- lib/pure/parseutils.nim | 17 +++++++++++++++++ lib/pure/strscans.nim | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index a602b0e1be..57387e62ed 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -87,6 +87,23 @@ proc parseOct*(s: string, number: var int, start = 0): int {. inc(i) if foundDigit: result = i-start +proc parseBin*(s: string, number: var int, start = 0): int {. + rtl, extern: "npuParseBin", noSideEffect.} = + ## parses an binary number and stores its value in ``number``. Returns + ## the number of the parsed characters or 0 in case of an error. + var i = start + var foundDigit = false + if s[i] == '0' and (s[i+1] == 'b' or s[i+1] == 'B'): inc(i, 2) + while true: + case s[i] + of '_': discard + of '0'..'1': + number = number shl 1 or (ord(s[i]) - ord('0')) + foundDigit = true + else: break + inc(i) + if foundDigit: result = i-start + proc parseIdent*(s: string, ident: var string, start = 0): int = ## parses an identifier and stores it in ``ident``. Returns ## the number of the parsed characters or 0 in case of an error. diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim index f33e7451fc..42bb281eb1 100644 --- a/lib/pure/strscans.nim +++ b/lib/pure/strscans.nim @@ -31,7 +31,10 @@ As can be seen from the examples, strings are matched verbatim except for substrings starting with ``$``. These constructions are available: ================= ======================================================== -``$i`` Matches an integer. This uses ``parseutils.parseInt``. +``$b`` Matches an decimal integer. This uses ``parseutils.parseBin``. +``$o`` Matches an octal integer. This uses ``parseutils.parseOct``. +``$i`` Matches an decimal integer. This uses ``parseutils.parseInt``. +``$h`` Matches an hex integer. This uses ``parseutils.parseHex``. ``$f`` Matches a floating pointer number. Uses ``parseFloat``. ``$w`` Matches an ASCII identifier: ``[A-Z-a-z_][A-Za-z_0-9]*``. ``$s`` Skips optional whitespace. @@ -335,11 +338,29 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b else: error("no string var given for $w") inc i + of 'b': + if i < results.len or getType(results[i]).typeKind != ntyInt: + matchBind "parseBin" + else: + error("no int var given for $b") + inc i + of 'o': + if i < results.len or getType(results[i]).typeKind != ntyInt: + matchBind "parseOct" + else: + error("no int var given for $o") + inc i of 'i': if i < results.len or getType(results[i]).typeKind != ntyInt: matchBind "parseInt" else: - error("no int var given for $d") + error("no int var given for $i") + inc i + of 'h': + if i < results.len or getType(results[i]).typeKind != ntyInt: + matchBind "parseHex" + else: + error("no int var given for $h") inc i of 'f': if i < results.len or getType(results[i]).typeKind != ntyFloat: @@ -645,6 +666,14 @@ when isMainModule: doAssert intval == 89 doAssert floatVal == 33.25 + var binval: int + var octval: int + var hexval: int + doAssert scanf("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binval, octval, hexval) + doAssert binval == 0b0101 + doAssert octval == 0o1234 + doAssert hexval == 0xabcd + let xx = scanf("$abc", "$$$i", intval) doAssert xx == false From 9bc263839904787e68602dc55ddbd9832c1066b6 Mon Sep 17 00:00:00 2001 From: Mathias Stearn Date: Sat, 6 Jan 2018 09:08:58 -0500 Subject: [PATCH 3/4] Fix typos in scanf docs (#7035) --- lib/pure/strscans.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim index 42bb281eb1..83a82dd0bf 100644 --- a/lib/pure/strscans.nim +++ b/lib/pure/strscans.nim @@ -31,10 +31,10 @@ As can be seen from the examples, strings are matched verbatim except for substrings starting with ``$``. These constructions are available: ================= ======================================================== -``$b`` Matches an decimal integer. This uses ``parseutils.parseBin``. +``$b`` Matches a binary integer. This uses ``parseutils.parseBin``. ``$o`` Matches an octal integer. This uses ``parseutils.parseOct``. -``$i`` Matches an decimal integer. This uses ``parseutils.parseInt``. -``$h`` Matches an hex integer. This uses ``parseutils.parseHex``. +``$i`` Matches a decimal integer. This uses ``parseutils.parseInt``. +``$h`` Matches a hex integer. This uses ``parseutils.parseHex``. ``$f`` Matches a floating pointer number. Uses ``parseFloat``. ``$w`` Matches an ASCII identifier: ``[A-Z-a-z_][A-Za-z_0-9]*``. ``$s`` Skips optional whitespace. From 06e68feadb4becb653e5e55fd2ef85e1eafd9ba4 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 6 Jan 2018 17:27:19 +0100 Subject: [PATCH 4/4] strscans: fix the type checking logic; improve the documentation --- lib/pure/strscans.nim | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim index 83a82dd0bf..2bd87837ff 100644 --- a/lib/pure/strscans.nim +++ b/lib/pure/strscans.nim @@ -333,37 +333,37 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b conds.add resLen.notZero conds.add resLen of 'w': - if i < results.len or getType(results[i]).typeKind != ntyString: + if i < results.len and getType(results[i]).typeKind == ntyString: matchBind "parseIdent" else: error("no string var given for $w") inc i of 'b': - if i < results.len or getType(results[i]).typeKind != ntyInt: + if i < results.len and getType(results[i]).typeKind == ntyInt: matchBind "parseBin" else: error("no int var given for $b") inc i of 'o': - if i < results.len or getType(results[i]).typeKind != ntyInt: + if i < results.len and getType(results[i]).typeKind == ntyInt: matchBind "parseOct" else: error("no int var given for $o") inc i of 'i': - if i < results.len or getType(results[i]).typeKind != ntyInt: + if i < results.len and getType(results[i]).typeKind == ntyInt: matchBind "parseInt" else: error("no int var given for $i") inc i of 'h': - if i < results.len or getType(results[i]).typeKind != ntyInt: + if i < results.len and getType(results[i]).typeKind == ntyInt: matchBind "parseHex" else: error("no int var given for $h") inc i of 'f': - if i < results.len or getType(results[i]).typeKind != ntyFloat: + if i < results.len and getType(results[i]).typeKind == ntyFloat: matchBind "parseFloat" else: error("no float var given for $f") @@ -378,7 +378,7 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b else: error("invalid format string") of '*', '+': - if i < results.len or getType(results[i]).typeKind != ntyString: + if i < results.len and getType(results[i]).typeKind == ntyString: var min = ord(pattern[p] == '+') var q=p+1 var token = "" @@ -462,7 +462,7 @@ template success*(x: int): bool = x != 0 template nxt*(input: string; idx, step: int = 1) = inc(idx, step) macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool = - ## See top level documentation of his module of how ``scanp`` works. + ## ``scanp`` is currently undocumented. type StmtTriple = tuple[init, cond, action: NimNode] template interf(x): untyped = bindSym(x, brForceOpen)