diff options
author | Oscar Campbell <oscar@campbell.nu> | 2015-06-10 19:06:46 +0200 |
---|---|---|
committer | Oscar Campbell <oscar@campbell.nu> | 2015-06-10 19:06:46 +0200 |
commit | d892887c937a1e07418afb620098d4cd98275b2a (patch) | |
tree | 8f52707d6856c0caa1ad6117010b02f1434a7a28 | |
parent | 858cdd0b05df4846fb40a3263f05e54438995e99 (diff) | |
parent | 6c256ddcaef0c92b94d1a3e61f4e56cf7d017b50 (diff) | |
download | Nim-d892887c937a1e07418afb620098d4cd98275b2a.tar.gz |
Merge remote-tracking branch 'upstream/devel' into devel
-rw-r--r-- | compiler/ast.nim | 5 | ||||
-rw-r--r-- | compiler/cgen.nim | 11 | ||||
-rw-r--r-- | compiler/commands.nim | 3 | ||||
-rw-r--r-- | compiler/crc.nim | 147 | ||||
-rw-r--r-- | compiler/extccomp.nim | 23 | ||||
-rw-r--r-- | compiler/jsgen.nim | 4 | ||||
-rw-r--r-- | compiler/modules.nim | 10 | ||||
-rw-r--r-- | compiler/msgs.nim | 79 | ||||
-rw-r--r-- | compiler/options.nim | 1 | ||||
-rw-r--r-- | compiler/rodread.nim | 24 | ||||
-rw-r--r-- | compiler/rodwrite.nim | 13 | ||||
-rw-r--r-- | compiler/securehash.nim | 199 | ||||
-rw-r--r-- | doc/manual/generics.txt | 6 | ||||
-rw-r--r-- | lib/impure/db_mysql.nim | 27 | ||||
-rw-r--r-- | lib/impure/db_postgres.nim | 21 | ||||
-rw-r--r-- | lib/impure/db_sqlite.nim | 24 | ||||
-rw-r--r-- | lib/pure/httpclient.nim | 6 | ||||
-rw-r--r-- | lib/pure/pegs.nim | 1 | ||||
-rw-r--r-- | lib/pure/streams.nim | 2 | ||||
-rw-r--r-- | lib/pure/terminal.nim | 103 | ||||
-rw-r--r-- | lib/pure/unicode.nim | 10 | ||||
-rw-r--r-- | lib/system.nim | 3 |
22 files changed, 469 insertions, 253 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index c141352cb..668f20bcd 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -10,7 +10,7 @@ # abstract syntax tree + symbol table import - msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, + msgs, hashes, nversion, options, strutils, securehash, ropes, idents, lists, intsets, idgen type @@ -948,6 +948,9 @@ proc add*(father, son: PNode) = proc `[]`*(n: PNode, i: int): PNode {.inline.} = result = n.sons[i] +template `-|`*(b, s: expr): expr = + (if b >= 0: b else: s.len + b) + # son access operators with support for negative indices template `{}`*(n: PNode, i: int): expr = n[i -| n] template `{}=`*(n: PNode, i: int, s: PNode): stmt = diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 91877833a..390150cf7 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -10,12 +10,11 @@ ## This module implements the C code generator. import - ast, astalgo, hashes, trees, platform, magicsys, extccomp, - options, intsets, - nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, - ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms, - rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings, - semparallel + ast, astalgo, hashes, trees, platform, magicsys, extccomp, options, intsets, + nversion, nimsets, msgs, securehash, bitsets, idents, lists, types, + ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, + condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, + lowerings, semparallel import strutils except `%` # collides with ropes.`%` diff --git a/compiler/commands.nim b/compiler/commands.nim index d30d8326c..285d73e7a 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -532,6 +532,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = of "genscript": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optGenScript) + of "usecolors": + expectNoArg(switch, arg, pass, info) + incl(gGlobalOptions, optUseColors) of "lib": expectArg(switch, arg, pass, info) libpath = processPath(arg, notRelativeToProj=true) diff --git a/compiler/crc.nim b/compiler/crc.nim deleted file mode 100644 index a8b61f2a5..000000000 --- a/compiler/crc.nim +++ /dev/null @@ -1,147 +0,0 @@ -# -# -# The Nim Compiler -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -import - strutils - -type - TCrc32* = int32 - -const - InitCrc32* = TCrc32(- 1) - InitAdler32* = int32(1) - -proc updateCrc32*(val: int8, crc: TCrc32): TCrc32 {.inline.} -proc updateCrc32*(val: char, crc: TCrc32): TCrc32 {.inline.} -proc crcFromBuf*(buf: pointer, length: int): TCrc32 -proc strCrc32*(s: string): TCrc32 -proc crcFromFile*(filename: string): TCrc32 -proc updateAdler32*(adler: int32, buf: pointer, length: int): int32 -# implementation - -type - TCRC_TabEntry = int - -const - crc32table: array[0..255, TCRC_TabEntry] = [0, 1996959894, - 301047508, - - 1727442502, 124634137, 1886057615, - 379345611, - 1637575261, 249268274, - 2044508324, - 522852066, - 1747789432, 162941995, 2125561021, - 407360249, - - 1866523247, 498536548, 1789927666, - 205950648, - 2067906082, 450548861, - 1843258603, - 187386543, - 2083289657, 325883990, 1684777152, - 43845254, - - 1973040660, 335633487, 1661365465, - 99664541, - 1928851979, 997073096, - 1281953886, - 715111964, - 1570279054, 1006888145, 1258607687, - 770865667, - - 1526024853, 901097722, 1119000684, - 608450090, - 1396901568, 853044451, - 1172266101, - 589951537, - 1412350631, 651767980, 1373503546, - 925412992, - - 1076862698, 565507253, 1454621731, - 809855591, - 1195530993, 671266974, - 1594198024, - 972236366, - 1324619484, 795835527, 1483230225, - 1050600021, - - 1234817731, 1994146192, 31158534, - 1731059524, - 271249366, 1907459465, - 112637215, - 1614814043, - 390540237, 2013776290, 251722036, - 1777751922, - - 519137256, 2137656763, 141376813, - 1855689577, - 429695999, 1802195444, - 476864866, - 2056965928, - 228458418, 1812370925, 453092731, - 2113342271, - - 183516073, 1706088902, 314042704, - 1950435094, - 54949764, 1658658271, - 366619977, - 1932296973, - 69972891, 1303535960, 984961486, - 1547960204, - - 725929758, 1256170817, 1037604311, - 1529756563, - 740887301, 1131014506, - 879679996, - 1385723834, - 631195440, 1141124467, 855842277, - 1442165665, - - 586318647, 1342533948, 654459306, - 1106571248, - 921952122, 1466479909, - 544179635, - 1184443383, - 832445281, 1591671054, 702138776, - 1328506846, - - 942167884, 1504918807, 783551873, - 1212326853, - 1061524307, - 306674912, - - 1698712650, 62317068, 1957810842, - 355121351, - 1647151185, 81470997, - 1943803523, - 480048366, - 1805370492, 225274430, 2053790376, - 468791541, - - 1828061283, 167816743, 2097651377, - 267414716, - 2029476910, 503444072, - 1762050814, - 144550051, - 2140837941, 426522225, 1852507879, - 19653770, - - 1982649376, 282753626, 1742555852, - 105259153, - 1900089351, 397917763, - 1622183637, - 690576408, - 1580100738, 953729732, 1340076626, - 776247311, - - 1497606297, 1068828381, 1219638859, - 670225446, - 1358292148, 906185462, - 1090812512, - 547295293, - 1469587627, 829329135, 1181335161, - 882789492, - - 1134132454, 628085408, 1382605366, - 871598187, - 1156888829, 570562233, - 1426400815, - 977650754, - 1296233688, 733239954, 1555261956, - 1026031705, - - 1244606671, 752459403, 1541320221, - 1687895376, - 328994266, 1969922972, - 40735498, - 1677130071, - 351390145, 1913087877, 83908371, - 1782625662, - - 491226604, 2075208622, 213261112, - 1831694693, - 438977011, 2094854071, - 198958881, - 2032938284, - 237706686, 1759359992, 534414190, - 2118248755, - - 155638181, 1873836001, 414664567, - 2012718362, - 15766928, 1711684554, - 285281116, - 1889165569, - 127750551, 1634467795, 376229701, - 1609899400, - - 686959890, 1308918612, 956543938, - 1486412191, - 799009033, 1231636301, - 1047427035, - 1362007478, - 640263460, 1088359270, 936918000, - 1447252397, - - 558129467, 1202900863, 817233897, - 1111625188, - 893730166, 1404277552, - 615818150, - 1160759803, - 841546093, 1423857449, 601450431, - 1285129682, - - 1000256840, 1567103746, 711928724, - 1274298825, - 1022587231, 1510334235, - 755167117] - -proc updateCrc32(val: int8, crc: TCrc32): TCrc32 = - result = TCrc32(crc32table[(int(crc) xor (int(val) and 0x000000FF)) and - 0x000000FF]) xor (crc shr TCrc32(8)) - -proc updateCrc32(val: char, crc: TCrc32): TCrc32 = - result = updateCrc32(toU8(ord(val)), crc) - -proc strCrc32(s: string): TCrc32 = - result = InitCrc32 - for i in countup(0, len(s) - 1): result = updateCrc32(s[i], result) - -proc `><`*(c: TCrc32, s: string): TCrc32 = - result = c - for i in 0..len(s)-1: result = updateCrc32(s[i], result) - -type - TByteArray = array[0..10000000, int8] - PByteArray = ref TByteArray - -proc crcFromBuf(buf: pointer, length: int): TCrc32 = - var p = cast[PByteArray](buf) - result = InitCrc32 - for i in countup(0, length - 1): result = updateCrc32(p[i], result) - -proc crcFromFile(filename: string): TCrc32 = - const - bufSize = 8000 # don't use 8K for the memory allocator! - var - bin: File - result = InitCrc32 - if not open(bin, filename): - return # not equal if file does not exist - var buf = alloc(bufSize) - var p = cast[PByteArray](buf) - while true: - var readBytes = readBuffer(bin, buf, bufSize) - for i in countup(0, readBytes - 1): result = updateCrc32(p[i], result) - if readBytes != bufSize: break - dealloc(buf) - close(bin) - -const - base = int32(65521) # largest prime smaller than 65536 - # NMAX = 5552; original code with unsigned 32 bit integer - # NMAX is the largest n - # such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 - nmax = 3854 # code with signed 32 bit integer - # NMAX is the largest n such that - # 255n(n+1)/2 + (n+1)(BASE-1) <= 2^31-1 - # The penalty is the time loss in the extra MOD-calls. - -proc updateAdler32(adler: int32, buf: pointer, length: int): int32 = - var - s1, s2: int32 - L, k, b: int - s1 = adler and int32(0x0000FFFF) - s2 = (adler shr int32(16)) and int32(0x0000FFFF) - L = length - b = 0 - while (L > 0): - if L < nmax: k = L - else: k = nmax - dec(L, k) - while (k > 0): - s1 = s1 +% int32((cast[cstring](buf))[b]) - s2 = s2 +% s1 - inc(b) - dec(k) - s1 = `%%`(s1, base) - s2 = `%%`(s2, base) - result = (s2 shl int32(16)) or s1 diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 186a3884d..38427b367 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -13,7 +13,8 @@ # nim files. import - lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, crc + lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, + securehash type TSystemCC* = enum @@ -572,26 +573,24 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = "nim", quoteShell(getPrefixDir()), "lib", quoteShell(libpath)]) -proc footprint(filename: string): TCrc32 = - # note, '><' further modifies a crc value with a string. - result = crcFromFile(filename) >< - platform.OS[targetOS].name >< - platform.CPU[targetCPU].name >< - extccomp.CC[extccomp.cCompiler].name >< - getCompileCFileCmd(filename, true) +proc footprint(filename: string): SecureHash = + result = secureHash( + $secureHashFile(filename) & + platform.OS[targetOS].name & + platform.CPU[targetCPU].name & + extccomp.CC[extccomp.cCompiler].name & + getCompileCFileCmd(filename, true)) proc externalFileChanged(filename: string): bool = if gCmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM}: return false var crcFile = toGeneratedFile(filename.withPackageName, "crc") - var currentCrc = int(footprint(filename)) + var currentCrc = footprint(filename) var f: File if open(f, crcFile, fmRead): - var line = newStringOfCap(40) - if not f.readLine(line): line = "0" + let oldCrc = parseSecureHash(f.readLine()) close(f) - var oldCrc = parseInt(line) result = oldCrc != currentCrc else: result = true diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 2fdf14b76..1f82306d2 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -30,8 +30,8 @@ implements the required case distinction. import - ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, - options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os, + ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, + nversion, nimsets, msgs, securehash, bitsets, idents, lists, types, os, times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils, intsets, cgmeth, lowerings diff --git a/compiler/modules.nim b/compiler/modules.nim index 2fa46f356..6cb14c091 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -10,7 +10,7 @@ ## implements the module handling import - ast, astalgo, magicsys, crc, rodread, msgs, cgendata, sigmatch, options, + ast, astalgo, magicsys, securehash, rodread, msgs, cgendata, sigmatch, options, idents, os, lexer, idgen, passes, syntaxes, llstream type @@ -19,7 +19,7 @@ type TModuleInMemory* = object compiledAt*: float - crc*: TCrc32 + crc*: SecureHash deps*: seq[int32] ## XXX: slurped files are currently not tracked needsRecompile*: TNeedRecompile crcStatus*: TCrcStatus @@ -51,19 +51,19 @@ proc crcChanged(fileIdx: int32): bool = of crcNotChanged: result = false of crcCached: - let newCrc = crcFromFile(fileIdx.toFilename) + let newCrc = secureHashFile(fileIdx.toFilename) result = newCrc != gMemCacheData[fileIdx].crc gMemCacheData[fileIdx].crc = newCrc updateStatus() of crcNotTaken: - gMemCacheData[fileIdx].crc = crcFromFile(fileIdx.toFilename) + gMemCacheData[fileIdx].crc = secureHashFile(fileIdx.toFilename) result = true updateStatus() proc doCRC(fileIdx: int32) = if gMemCacheData[fileIdx].crcStatus == crcNotTaken: # echo "FIRST CRC: ", fileIdx.ToFilename - gMemCacheData[fileIdx].crc = crcFromFile(fileIdx.toFilename) + gMemCacheData[fileIdx].crc = secureHashFile(fileIdx.toFilename) proc addDep(x: PSym, dep: int32) = growCache gMemCacheData, dep diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 81a62371e..4df4430d7 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -8,7 +8,7 @@ # import - options, strutils, os, tables, ropes, platform + options, strutils, os, tables, ropes, platform, terminal type TMsgKind* = enum @@ -605,13 +605,13 @@ proc suggestQuit*() = # this format is understood by many text editors: it is the same that # Borland and Freepascal use const - PosErrorFormat* = "$1($2, $3) Error: $4" - PosWarningFormat* = "$1($2, $3) Warning: $4" - PosHintFormat* = "$1($2, $3) Hint: $4" - PosContextFormat = "$1($2, $3) Info: $4" - RawErrorFormat* = "Error: $1" - RawWarningFormat* = "Warning: $1" - RawHintFormat* = "Hint: $1" + PosErrorFormat* = "$1($2, $3) Error: " + PosWarningFormat* = "$1($2, $3) Warning: " + PosHintFormat* = "$1($2, $3) Hint: " + PosContextFormat = "$1($2, $3) Info: " + RawError* = "Error: " + RawWarning* = "Warning: " + RawHint* = "Hint: " proc getInfoContextLen*(): int = return msgContext.len proc setInfoContextLen*(L: int) = setLen(msgContext, L) @@ -686,17 +686,27 @@ proc outWriteln*(s: string) = ## Writes to stdout. Always. if eStdOut in errorOutputs: writeln(stdout, s) -proc msgWriteln*(s: string) = - ## Writes to stdout. If --stdout option is given, writes to stderr instead. +proc msgWriteln*(s: string, color: ForegroundColor = fgWhite, coloredText: string = "") = + ## Writes to stdout. If --stderr option is given, writes to stderr instead. #if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return + var hasColor = optUseColors in gGlobalOptions if not isNil(writelnHook): - writelnHook(s) - elif optStdout in gGlobalOptions: - if eStdErr in errorOutputs: writeln(stderr, s) + writelnHook(coloredText & s) else: - if eStdOut in errorOutputs: writeln(stdout, s) + if optStdout in gGlobalOptions: + if eStdErr in errorOutputs: + if hasColor: setForegroundColor(color) + write(stderr, coloredText) + if hasColor: resetAttributes() + writeln(stderr, s) + else: + if eStdOut in errorOutputs: + if hasColor: setForegroundColor(color) + write(stdout, coloredText) + if hasColor: resetAttributes() + writeln(stdout, s) proc coordToStr(coord: int): string = if coord == -1: result = "???" @@ -718,7 +728,7 @@ proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) = if stackTraceAvailable() and isNil(writelnHook): writeStackTrace() else: - msgWriteln("No stack traceback available\nTo create a stacktrace, rerun compilation with ./koch temp " & options.command & " <file>") + msgWriteln("", fgRed, "No stack traceback available\nTo create a stacktrace, rerun compilation with ./koch temp " & options.command & " <file>") quit 1 if msg >= fatalMin and msg <= fatalMax: @@ -741,34 +751,39 @@ proc writeContext(lastinfo: TLineInfo) = for i in countup(0, len(msgContext) - 1): if msgContext[i] != lastinfo and msgContext[i] != info: msgWriteln(PosContextFormat % [toMsgFilename(msgContext[i]), - coordToStr(msgContext[i].line), - coordToStr(msgContext[i].col+1), - getMessageStr(errInstantiationFrom, "")]) + coordToStr(msgContext[i].line), + coordToStr(msgContext[i].col+1), + getMessageStr(errInstantiationFrom, "")]) info = msgContext[i] proc ignoreMsgBecauseOfIdeTools(msg: TMsgKind): bool = msg >= errGenerated and gCmd == cmdIdeTools and optIdeDebug notin gGlobalOptions proc rawMessage*(msg: TMsgKind, args: openArray[string]) = - var frmt: string + var + frmt: string + color: ForegroundColor case msg of errMin..errMax: writeContext(unknownLineInfo()) - frmt = RawErrorFormat + frmt = RawError + color = fgRed of warnMin..warnMax: if optWarns notin gOptions: return if msg notin gNotes: return writeContext(unknownLineInfo()) - frmt = RawWarningFormat + frmt = RawWarning inc(gWarnCounter) + color = fgYellow of hintMin..hintMax: if optHints notin gOptions: return if msg notin gNotes: return - frmt = RawHintFormat + frmt = RawHint inc(gHintCounter) - let s = `%`(frmt, `%`(msgKindToString(msg), args)) + color = fgGreen + let s = `%`(msgKindToString(msg), args) if not ignoreMsgBecauseOfIdeTools(msg): - msgWriteln(s) + msgWriteln(s, color, frmt) handleError(msg, doAbort, s) proc rawMessage*(msg: TMsgKind, arg: string) = @@ -789,8 +804,10 @@ proc formatMsg*(info: TLineInfo, msg: TMsgKind, arg: string): string = proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, eh: TErrorHandling) = - var frmt: string - var ignoreMsg = false + var + frmt: string + ignoreMsg = false + color: ForegroundColor case msg of errMin..errMax: writeContext(info) @@ -799,22 +816,26 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, # in the same file and line are produced: #ignoreMsg = lastError == info and eh != doAbort lastError = info + color = fgRed of warnMin..warnMax: ignoreMsg = optWarns notin gOptions or msg notin gNotes if not ignoreMsg: writeContext(info) frmt = PosWarningFormat inc(gWarnCounter) + color = fgYellow of hintMin..hintMax: ignoreMsg = optHints notin gOptions or msg notin gNotes frmt = PosHintFormat inc(gHintCounter) + color = fgGreen # NOTE: currently line info line numbers start with 1, # but column numbers start with 0, however most editors expect # first column to be 1, so we need to +1 here - let s = frmt % [toMsgFilename(info), coordToStr(info.line), - coordToStr(info.col+1), getMessageStr(msg, arg)] + let x = frmt % [toMsgFilename(info), coordToStr(info.line), + coordToStr(info.col+1)] + let s = getMessageStr(msg, arg) if not ignoreMsg and not ignoreMsgBecauseOfIdeTools(msg): - msgWriteln(s) + msgWriteln(s, color, x) if optPrintSurroundingSrc and msg in errMin..errMax: info.writeSurroundingSrc handleError(msg, eh, s) diff --git a/compiler/options.nim b/compiler/options.nim index b3060a180..48e2db0c7 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -54,6 +54,7 @@ type # please make sure we have under 32 options optSkipUserConfigFile, # skip the users's config file optSkipParentConfigFiles, # skip parent dir's config files optNoMain, # do not generate a "main" proc + optUseColors, # use colors for hints, warnings, and errors optThreads, # support for multi-threading optStdout, # output to stdout optThreadAnalysis, # thread analysis pass diff --git a/compiler/rodread.nim b/compiler/rodread.nim index e92f7ecfa..dad7d111e 100644 --- a/compiler/rodread.nim +++ b/compiler/rodread.nim @@ -90,7 +90,7 @@ import os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms, - ropes, idents, crc, idgen, types, rodutils, memfiles + ropes, idents, securehash, idgen, types, rodutils, memfiles type TReasonForRecompile* = enum ## all the reasons that can trigger recompilation @@ -538,10 +538,11 @@ proc cmdChangeTriggersRecompilation(old, new: TCommands): bool = # else: trigger recompilation: result = true -proc processRodFile(r: PRodReader, crc: TCrc32) = +proc processRodFile(r: PRodReader, crc: SecureHash) = var w: string - d, inclCrc: int + d: int + var inclCrc: SecureHash while r.s[r.pos] != '\0': var section = rdWord(r) if r.reason != rrNone: @@ -549,7 +550,8 @@ proc processRodFile(r: PRodReader, crc: TCrc32) = case section of "CRC": inc(r.pos) # skip ':' - if int(crc) != decodeVInt(r.s, r.pos): r.reason = rrCrcChange + if crc != parseSecureHash(decodeStr(r.s, r.pos)): + r.reason = rrCrcChange of "ID": inc(r.pos) # skip ':' r.moduleID = decodeVInt(r.s, r.pos) @@ -596,9 +598,9 @@ proc processRodFile(r: PRodReader, crc: TCrc32) = while r.s[r.pos] != ')': w = r.files[decodeVInt(r.s, r.pos)].toFullPath inc(r.pos) # skip ' ' - inclCrc = decodeVInt(r.s, r.pos) + inclCrc = parseSecureHash(decodeStr(r.s, r.pos)) if r.reason == rrNone: - if not existsFile(w) or (inclCrc != int(crcFromFile(w))): + if not existsFile(w) or (inclCrc != secureHashFile(w)): r.reason = rrInclDeps if r.s[r.pos] == '\x0A': inc(r.pos) @@ -649,7 +651,7 @@ proc startsWith(buf: cstring, token: string, pos = 0): bool = while s < token.len and buf[pos+s] == token[s]: inc s result = s == token.len -proc newRodReader(modfilename: string, crc: TCrc32, +proc newRodReader(modfilename: string, crc: SecureHash, readerIndex: int): PRodReader = new(result) try: @@ -701,7 +703,7 @@ type filename*: string reason*: TReasonForRecompile rd*: PRodReader - crc*: TCrc32 + crc*: SecureHash crcDone*: bool TFileModuleMap = seq[TFileModuleRec] @@ -794,13 +796,13 @@ proc loadMethods(r: PRodReader) = r.methods.add(rrGetSym(r, d, unknownLineInfo())) if r.s[r.pos] == ' ': inc(r.pos) -proc getCRC*(fileIdx: int32): TCrc32 = +proc getCRC*(fileIdx: int32): SecureHash = internalAssert fileIdx >= 0 and fileIdx < gMods.len if gMods[fileIdx].crcDone: return gMods[fileIdx].crc - result = crcFromFile(fileIdx.toFilename) + result = secureHashFile(fileIdx.toFilename) gMods[fileIdx].crc = result template growCache*(cache, pos) = @@ -1017,7 +1019,7 @@ proc writeType(f: File; t: PType) = f.write("]\n") proc viewFile(rodfile: string) = - var r = newRodReader(rodfile, 0, 0) + var r = newRodReader(rodfile, secureHash(""), 0) if r == nil: rawMessage(errGenerated, "cannot open file (or maybe wrong version):" & rodfile) diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index e178b7ce6..737387597 100644 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -13,14 +13,15 @@ import intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform, - condsyms, ropes, idents, crc, rodread, passes, importer, idgen, rodutils + condsyms, ropes, idents, securehash, rodread, passes, importer, idgen, + rodutils # implementation type TRodWriter = object of TPassContext module: PSym - crc: TCrc32 + crc: SecureHash options: TOptions defines: string inclDeps: string @@ -38,7 +39,7 @@ type PRodWriter = ref TRodWriter -proc newRodWriter(crc: TCrc32, module: PSym): PRodWriter +proc newRodWriter(crc: SecureHash, module: PSym): PRodWriter proc addModDep(w: PRodWriter, dep: string) proc addInclDep(w: PRodWriter, dep: string) proc addInterfaceSym(w: PRodWriter, s: PSym) @@ -62,7 +63,7 @@ proc fileIdx(w: PRodWriter, filename: string): int = template filename*(w: PRodWriter): string = w.module.filename -proc newRodWriter(crc: TCrc32, module: PSym): PRodWriter = +proc newRodWriter(crc: SecureHash, module: PSym): PRodWriter = new(result) result.sstack = @[] result.tstack = @[] @@ -96,7 +97,7 @@ proc addInclDep(w: PRodWriter, dep: string) = var resolved = dep.findModule(w.module.info.toFullPath) encodeVInt(fileIdx(w, dep), w.inclDeps) add(w.inclDeps, " ") - encodeVInt(crcFromFile(resolved), w.inclDeps) + encodeStr($secureHashFile(resolved), w.inclDeps) add(w.inclDeps, rodNL) proc pushType(w: PRodWriter, t: PType) = @@ -440,7 +441,7 @@ proc writeRod(w: PRodWriter) = f.write(rodNL) var crc = "CRC:" - encodeVInt(w.crc, crc) + encodeStr($w.crc, crc) f.write(crc) f.write(rodNL) diff --git a/compiler/securehash.nim b/compiler/securehash.nim new file mode 100644 index 000000000..8ac6acb0e --- /dev/null +++ b/compiler/securehash.nim @@ -0,0 +1,199 @@ +# +# +# The Nim Compiler +# (c) Copyright 2015 Nim Contributers +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +import + strutils, unsigned + +const Sha1DigestSize = 20 + +type + Sha1Digest = array[0 .. Sha1DigestSize-1, uint8] + SecureHash* = distinct Sha1Digest + +proc sha1(src: string) : Sha1Digest + +proc secureHash*(str: string): SecureHash = SecureHash(sha1(str)) +proc secureHashFile*(filename: string): SecureHash = secureHash(readFile(filename)) +proc `$`*(self: SecureHash): string = + result = "" + for v in Sha1Digest(self): + result.add(toHex(int(v), 2)) + +proc parseSecureHash*(hash: string): SecureHash = + for i in 0.. <Sha1DigestSize: + Sha1Digest(result)[i] = uint8(parseHexInt(hash[i*2] & hash[i*2 + 1])) + +proc `==`*(a, b: SecureHash): bool = + # Not a constant-time comparison, but that's acceptable in this context + Sha1Digest(a) == Sha1Digest(b) + + +when isMainModule: + let hash1 = secureHash("a93tgj0p34jagp9[agjp98ajrhp9aej]") + doAssert hash1 == hash1 + doAssert parseSecureHash($hash1) == hash1 + + +# Copyright (c) 2011, Micael Hildenborg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Micael Hildenborg nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Ported to Nim by Erik O'Leary + +type + Sha1State = array[0 .. 5-1, uint32] + Sha1Buffer = array[0 .. 80-1, uint32] + +template clearBuffer(w: Sha1Buffer, len = 16) = + zeroMem(addr(w), len * sizeof(uint32)) + +proc init(result: var Sha1State) = + result[0] = 0x67452301'u32 + result[1] = 0xefcdab89'u32 + result[2] = 0x98badcfe'u32 + result[3] = 0x10325476'u32 + result[4] = 0xc3d2e1f0'u32 + +proc innerHash(state: var Sha1State, w: var Sha1Buffer) = + var + a = state[0] + b = state[1] + c = state[2] + d = state[3] + e = state[4] + + var round = 0 + + template rot(value, bits: uint32): uint32 {.immediate.} = + (value shl bits) or (value shr (32 - bits)) + + template sha1(fun, val: uint32): stmt = + let t = rot(a, 5) + fun + e + val + w[round] + e = d + d = c + c = rot(b, 30) + b = a + a = t + + template process(body: stmt): stmt = + w[round] = rot(w[round - 3] xor w[round - 8] xor w[round - 14] xor w[round - 16], 1) + body + inc(round) + + template wrap(dest, value: expr): stmt {.immediate.} = + let v = dest + value + dest = v + + while round < 16: + sha1((b and c) or (not b and d), 0x5a827999'u32) + inc(round) + + while round < 20: + process: + sha1((b and c) or (not b and d), 0x5a827999'u32) + + while round < 40: + process: + sha1(b xor c xor d, 0x6ed9eba1'u32) + + while round < 60: + process: + sha1((b and c) or (b and d) or (c and d), 0x8f1bbcdc'u32) + + while round < 80: + process: + sha1(b xor c xor d, 0xca62c1d6'u32) + + wrap state[0], a + wrap state[1], b + wrap state[2], c + wrap state[3], d + wrap state[4], e + +template computeInternal(src: expr): stmt {.immediate.} = + #Initialize state + var state: Sha1State + init(state) + + #Create w buffer + var w: Sha1Buffer + + #Loop through all complete 64byte blocks. + let byteLen = src.len + let endOfFullBlocks = byteLen - 64 + var endCurrentBlock = 0 + var currentBlock = 0 + + while currentBlock <= endOfFullBlocks: + endCurrentBlock = currentBlock + 64 + + var i = 0 + while currentBlock < endCurrentBlock: + w[i] = uint32(src[currentBlock+3]) or + uint32(src[currentBlock+2]) shl 8'u32 or + uint32(src[currentBlock+1]) shl 16'u32 or + uint32(src[currentBlock]) shl 24'u32 + currentBlock += 4 + inc(i) + + innerHash(state, w) + + #Handle last and not full 64 byte block if existing + endCurrentBlock = byteLen - currentBlock + clearBuffer(w) + var lastBlockBytes = 0 + + while lastBlockBytes < endCurrentBlock: + + var value = uint32(src[lastBlockBytes + currentBlock]) shl + ((3'u32 - (lastBlockBytes and 3)) shl 3) + + w[lastBlockBytes shr 2] = w[lastBlockBytes shr 2] or value + inc(lastBlockBytes) + + w[lastBlockBytes shr 2] = w[lastBlockBytes shr 2] or ( + 0x80'u32 shl ((3'u32 - (lastBlockBytes and 3)) shl 3) + ) + + if endCurrentBlock >= 56: + innerHash(state, w) + clearBuffer(w) + + w[15] = uint32(byteLen) shl 3 + innerHash(state, w) + + # Store hash in result pointer, and make sure we get in in the correct order + # on both endian models. + for i in 0 .. Sha1DigestSize-1: + result[i] = uint8((int(state[i shr 2]) shr ((3-(i and 3)) * 8)) and 255) + +proc sha1(src: string) : Sha1Digest = + ## Calculate SHA1 from input string + computeInternal(src) diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt index 2736f88fb..f82cad531 100644 --- a/doc/manual/generics.txt +++ b/doc/manual/generics.txt @@ -164,11 +164,13 @@ Alternatively, the ``distinct`` type modifier can be applied to the type class to allow each param matching the type class to bind to a different type. If a proc param doesn't have a type specified, Nim will use the -``distinct auto`` type class (also known as ``any``): +``distinct auto`` type class (also known as ``any``). Note this behavior is +deprecated for procs; templates, however, support them: .. code-block:: nim # allow any combination of param types - proc concat(a, b): string = $a & $b + proc concat(a, b): string = $a & $b # deprecated + proc concat(a, b: any): string = $a & $b # preferred Procs written with the implicitly generic style will often need to refer to the type parameters of the matched generic type. They can be easily accessed using diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index 619c2a656..7c2901efd 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -16,6 +16,9 @@ type DbConn* = PMySQL ## encapsulates a database connection Row* = seq[string] ## a row of a dataset. NULL database values will be ## transformed always to the empty string. + InstantRow* = tuple[row: cstringArray, len: int] ## a handle that can be + ## used to get a row's + ## column text on demand EDb* = object of IOError ## exception that is raised if a database error occurs SqlQuery* = distinct string ## an SQL query string @@ -127,6 +130,30 @@ iterator fastRows*(db: DbConn, query: SqlQuery, yield result properFreeResult(sqlres, row) +iterator instantRows*(db: DbConn, query: SqlQuery, + args: varargs[string, `$`]): InstantRow + {.tags: [FReadDb].} = + ## same as fastRows but returns a handle that can be used to get column text + ## on demand using []. Returned handle is valid only within interator body. + rawExec(db, query, args) + var sqlres = mysql.useResult(db) + if sqlres != nil: + let L = int(mysql.numFields(sqlres)) + var row: cstringArray + while true: + row = mysql.fetchRow(sqlres) + if row == nil: break + yield (row: row, len: L) + properFreeResult(sqlres, row) + +proc `[]`*(row: InstantRow, col: int): string {.inline.} = + ## returns text for given column of the row + $row.row[col] + +proc len*(row: InstantRow): int {.inline.} = + ## returns number of columns in the row + row.len + proc getRow*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDB].} = ## retrieves a single row. If the query doesn't return any rows, this proc diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index 774cb1510..c88e660f4 100644 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -16,6 +16,9 @@ type DbConn* = PPGconn ## encapsulates a database connection Row* = seq[string] ## a row of a dataset. NULL database values will be ## transformed always to the empty string. + InstantRow* = tuple[res: PPGresult, line: int32] ## a handle that can be + ## used to get a row's + ## column text on demand EDb* = object of IOError ## exception that is raised if a database error occurs SqlQuery* = distinct string ## an SQL query string @@ -159,6 +162,24 @@ iterator fastRows*(db: DbConn, stmtName: SqlPrepared, yield result pqClear(res) +iterator instantRows*(db: DbConn, query: SqlQuery, + args: varargs[string, `$`]): InstantRow + {.tags: [FReadDb].} = + ## same as fastRows but returns a handle that can be used to get column text + ## on demand using []. Returned handle is valid only within interator body. + var res = setupQuery(db, query, args) + for i in 0..pqNtuples(res)-1: + yield (res: res, line: i) + pqClear(res) + +proc `[]`*(row: InstantRow, col: int32): string {.inline.} = + ## returns text for given column of the row + $pqgetvalue(row.res, row.line, col) + +proc len*(row: InstantRow): int32 {.inline.} = + ## returns number of columns in the row + pqNfields(row.res) + proc getRow*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDB].} = ## retrieves a single row. If the query doesn't return any rows, this proc diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index 47e7c1900..1a037becc 100644 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -16,6 +16,8 @@ type DbConn* = PSqlite3 ## encapsulates a database connection Row* = seq[string] ## a row of a dataset. NULL database values will be ## transformed always to the empty string. + InstantRow* = Pstmt ## a handle that can be used to get a row's column + ## text on demand EDb* = object of IOError ## exception that is raised if a database error occurs SqlQuery* = distinct string ## an SQL query string @@ -109,6 +111,24 @@ iterator fastRows*(db: DbConn, query: SqlQuery, yield result if finalize(stmt) != SQLITE_OK: dbError(db) +iterator instantRows*(db: DbConn, query: SqlQuery, + args: varargs[string, `$`]): InstantRow + {.tags: [FReadDb].} = + ## same as fastRows but returns a handle that can be used to get column text + ## on demand using []. Returned handle is valid only within interator body. + var stmt = setupQuery(db, query, args) + while step(stmt) == SQLITE_ROW: + yield stmt + if finalize(stmt) != SQLITE_OK: dbError(db) + +proc `[]`*(row: InstantRow, col: int32): string {.inline.} = + ## returns text for given column of the row + $column_text(row, col) + +proc len*(row: InstantRow): int32 {.inline.} = + ## returns number of columns in the row + column_count(row) + proc getRow*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDb].} = ## retrieves a single row. If the query doesn't return any rows, this proc @@ -216,5 +236,7 @@ when not defined(testing) and isMainModule: #db.query("insert into tbl1 values('goodbye', 20)") for r in db.rows(sql"select * from tbl1", []): echo(r[0], r[1]) - + for r in db.instantRows(sql"select * from tbl1", []): + echo(r[0], r[1]) + db_sqlite.close(db) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index e083d44ea..6a2913713 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -569,7 +569,7 @@ proc downloadFile*(url: string, outputFilename: string, fileError("Unable to open file") proc generateHeaders(r: Uri, httpMethod: string, - headers: StringTableRef): string = + headers: StringTableRef, body: string): string = # TODO: Use this in the blocking HttpClient once it supports proxies. result = substr(httpMethod, len("http")) # TODO: Proxies @@ -582,6 +582,8 @@ proc generateHeaders(r: Uri, httpMethod: string, add(result, "Host: " & r.hostname & "\c\L") add(result, "Connection: Keep-Alive\c\L") + if body.len > 0 and not headers.hasKey("Content-Length"): + add(result, "Content-Length: " & $body.len & "\c\L") for key, val in headers: add(result, key & ": " & val & "\c\L") @@ -786,7 +788,7 @@ proc request*(client: AsyncHttpClient, url: string, httpMethod: string, if not client.headers.hasKey("user-agent") and client.userAgent != "": client.headers["User-Agent"] = client.userAgent - var headers = generateHeaders(r, $httpMethod, client.headers) + var headers = generateHeaders(r, $httpMethod, client.headers, body) await client.socket.send(headers) if body != "": diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index ce837d9d1..e165d7dca 100644 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -1060,7 +1060,6 @@ type lineStart: int ## index of last line start in buffer colOffset: int ## column to add filename: string -{.deprecated: [TTokKind: TokKind, TToken: Token, TModifier: Modifier].} const tokKindToStr: array[TokKind, string] = [ diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index e6004b5d0..50b5c219a 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -279,7 +279,7 @@ proc ssAtEnd(s: Stream): bool = proc ssSetPosition(s: Stream, pos: int) = var s = StringStream(s) - s.pos = clamp(pos, 0, s.data.high) + s.pos = clamp(pos, 0, s.data.len) proc ssGetPosition(s: Stream): int = var s = StringStream(s) diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 1e9c40f06..15e2eefec 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -17,28 +17,87 @@ import macros when defined(windows): - import windows, os + import winlean, os + + const + DUPLICATE_SAME_ACCESS = 2 + FOREGROUND_BLUE = 1 + FOREGROUND_GREEN = 2 + FOREGROUND_RED = 4 + FOREGROUND_INTENSITY = 8 + BACKGROUND_BLUE = 16 + BACKGROUND_GREEN = 32 + BACKGROUND_RED = 64 + BACKGROUND_INTENSITY = 128 + + type + SHORT = int16 + COORD = object + X: SHORT + Y: SHORT + + SMALL_RECT = object + Left: SHORT + Top: SHORT + Right: SHORT + Bottom: SHORT + + CONSOLE_SCREEN_BUFFER_INFO = object + dwSize: COORD + dwCursorPosition: COORD + wAttributes: int16 + srWindow: SMALL_RECT + dwMaximumWindowSize: COORD + + proc duplicateHandle(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, + hTargetProcessHandle: HANDLE, lpTargetHandle: ptr HANDLE, + dwDesiredAccess: DWORD, bInheritHandle: WINBOOL, + dwOptions: DWORD): WINBOOL{.stdcall, dynlib: "kernel32", + importc: "DuplicateHandle".} + proc getCurrentProcess(): HANDLE{.stdcall, dynlib: "kernel32", + importc: "GetCurrentProcess".} + proc getConsoleScreenBufferInfo(hConsoleOutput: HANDLE, + lpConsoleScreenBufferInfo: ptr CONSOLE_SCREEN_BUFFER_INFO): WINBOOL{.stdcall, + dynlib: "kernel32", importc: "GetConsoleScreenBufferInfo".} + + proc setConsoleCursorPosition(hConsoleOutput: HANDLE, + dwCursorPosition: COORD): WINBOOL{. + stdcall, dynlib: "kernel32", importc: "SetConsoleCursorPosition".} + + proc fillConsoleOutputCharacter(hConsoleOutput: Handle, cCharacter: char, + nLength: DWORD, dwWriteCoord: Coord, + lpNumberOfCharsWritten: ptr DWORD): WINBOOL{. + stdcall, dynlib: "kernel32", importc: "FillConsoleOutputCharacterA".} + + proc fillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: int16, + nLength: DWORD, dwWriteCoord: COORD, + lpNumberOfAttrsWritten: ptr DWORD): WINBOOL{. + stdcall, dynlib: "kernel32", importc: "FillConsoleOutputAttribute".} + + proc setConsoleTextAttribute(hConsoleOutput: HANDLE, + wAttributes: int16): WINBOOL{. + stdcall, dynlib: "kernel32", importc: "SetConsoleTextAttribute".} var conHandle: Handle # = createFile("CONOUT$", GENERIC_WRITE, 0, nil, OPEN_ALWAYS, 0, 0) block: - var hTemp = GetStdHandle(STD_OUTPUT_HANDLE) - if DuplicateHandle(GetCurrentProcess(), hTemp, GetCurrentProcess(), + var hTemp = getStdHandle(STD_OUTPUT_HANDLE) + if duplicateHandle(getCurrentProcess(), hTemp, getCurrentProcess(), addr(conHandle), 0, 1, DUPLICATE_SAME_ACCESS) == 0: raiseOSError(osLastError()) proc getCursorPos(): tuple [x,y: int] = var c: CONSOLESCREENBUFFERINFO - if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: + if getConsoleScreenBufferInfo(conHandle, addr(c)) == 0: raiseOSError(osLastError()) return (int(c.dwCursorPosition.X), int(c.dwCursorPosition.Y)) proc getAttributes(): int16 = var c: CONSOLESCREENBUFFERINFO # workaround Windows bugs: try several times - if GetConsoleScreenBufferInfo(conHandle, addr(c)) != 0: + if getConsoleScreenBufferInfo(conHandle, addr(c)) != 0: return c.wAttributes return 0x70'i16 # ERROR: return white background, black text @@ -67,7 +126,7 @@ proc setCursorPos*(x, y: int) = var c: COORD c.X = int16(x) c.Y = int16(y) - if SetConsoleCursorPosition(conHandle, c) == 0: raiseOSError(osLastError()) + if setConsoleCursorPosition(conHandle, c) == 0: raiseOSError(osLastError()) else: stdout.write("\e[" & $y & ';' & $x & 'f') @@ -77,11 +136,11 @@ proc setCursorXPos*(x: int) = when defined(windows): var scrbuf: CONSOLESCREENBUFFERINFO var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: + if getConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) var origin = scrbuf.dwCursorPosition origin.X = int16(x) - if SetConsoleCursorPosition(conHandle, origin) == 0: + if setConsoleCursorPosition(conHandle, origin) == 0: raiseOSError(osLastError()) else: stdout.write("\e[" & $x & 'G') @@ -93,11 +152,11 @@ when defined(windows): when defined(windows): var scrbuf: CONSOLESCREENBUFFERINFO var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: + if getConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) var origin = scrbuf.dwCursorPosition origin.Y = int16(y) - if SetConsoleCursorPosition(conHandle, origin) == 0: + if setConsoleCursorPosition(conHandle, origin) == 0: raiseOSError(osLastError()) else: discard @@ -175,18 +234,18 @@ proc eraseLine* = var scrbuf: CONSOLESCREENBUFFERINFO var numwrote: DWORD var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: + if getConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) var origin = scrbuf.dwCursorPosition origin.X = 0'i16 - if SetConsoleCursorPosition(conHandle, origin) == 0: + if setConsoleCursorPosition(conHandle, origin) == 0: raiseOSError(osLastError()) var ht = scrbuf.dwSize.Y - origin.Y var wt = scrbuf.dwSize.X - origin.X - if FillConsoleOutputCharacter(hStdout,' ', ht*wt, + if fillConsoleOutputCharacter(hStdout,' ', ht*wt, origin, addr(numwrote)) == 0: raiseOSError(osLastError()) - if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, ht * wt, + if fillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, ht * wt, scrbuf.dwCursorPosition, addr(numwrote)) == 0: raiseOSError(osLastError()) else: @@ -201,14 +260,14 @@ proc eraseScreen* = var origin: COORD # is inititalized to 0, 0 var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: + if getConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) let numChars = int32(scrbuf.dwSize.X)*int32(scrbuf.dwSize.Y) - if FillConsoleOutputCharacter(hStdout, ' ', numChars, + if fillConsoleOutputCharacter(hStdout, ' ', numChars, origin, addr(numwrote)) == 0: raiseOSError(osLastError()) - if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, numChars, + if fillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, numChars, origin, addr(numwrote)) == 0: raiseOSError(osLastError()) setCursorXPos(0) @@ -219,7 +278,7 @@ proc resetAttributes* {.noconv.} = ## resets all attributes; it is advisable to register this as a quit proc ## with ``system.addQuitProc(resetAttributes)``. when defined(windows): - discard SetConsoleTextAttribute(conHandle, oldAttr) + discard setConsoleTextAttribute(conHandle, oldAttr) else: stdout.write("\e[0m") @@ -249,7 +308,7 @@ proc setStyle*(style: set[Style]) = if styleBlink in style: a = a or int16(BACKGROUND_INTENSITY) if styleReverse in style: a = a or 0x4000'i16 # COMMON_LVB_REVERSE_VIDEO if styleUnderscore in style: a = a or 0x8000'i16 # COMMON_LVB_UNDERSCORE - discard SetConsoleTextAttribute(conHandle, a) + discard setConsoleTextAttribute(conHandle, a) else: for s in items(style): stdout.write("\e[" & $ord(s) & 'm') @@ -260,7 +319,7 @@ proc writeStyled*(txt: string, style: set[Style] = {styleBright}) = var old = getAttributes() setStyle(style) stdout.write(txt) - discard SetConsoleTextAttribute(conHandle, old) + discard setConsoleTextAttribute(conHandle, old) else: setStyle(style) stdout.write(txt) @@ -309,7 +368,7 @@ proc setForegroundColor*(fg: ForegroundColor, bright=false) = (FOREGROUND_RED or FOREGROUND_BLUE), (FOREGROUND_BLUE or FOREGROUND_GREEN), (FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED)] - discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[fg])) + discard setConsoleTextAttribute(conHandle, toU16(old or lookup[fg])) else: gFG = ord(fg) if bright: inc(gFG, 60) @@ -330,7 +389,7 @@ proc setBackgroundColor*(bg: BackgroundColor, bright=false) = (BACKGROUND_RED or BACKGROUND_BLUE), (BACKGROUND_BLUE or BACKGROUND_GREEN), (BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED)] - discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[bg])) + discard setConsoleTextAttribute(conHandle, toU16(old or lookup[bg])) else: gBG = ord(bg) if bright: inc(gBG, 60) diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 5fd3c2418..4446eaa0c 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -372,11 +372,17 @@ const 0xfe74] # spaceRanges = [ - 0x0009, 0x000a, # tab and newline + 0x0009, 0x000d, # tab and newline 0x0020, 0x0020, # space + 0x0085, 0x0085, # next line 0x00a0, 0x00a0, # - 0x2000, 0x200b, # - + 0x1680, 0x1680, # Ogham space mark + 0x2000, 0x200b, # en dash .. zero-width space + 0x200e, 0x200f, # LTR mark .. RTL mark (pattern whitespace) 0x2028, 0x2029, # - 0x3000, 0x3000, # + 0x202f, 0x202f, # narrow no-break space + 0x205f, 0x205f, # medium mathematical space + 0x3000, 0x3000, # ideographic space 0xfeff, 0xfeff] # toupperRanges = [ diff --git a/lib/system.nim b/lib/system.nim index 90587f306..949443dd9 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2859,9 +2859,6 @@ proc `/`*(x, y: int): float {.inline, noSideEffect.} = ## integer division that results in a float. result = toFloat(x) / toFloat(y) -template `-|`*(b, s: expr): expr = - (if b >= 0: b else: s.len + b) - template spliceImpl(s, a, L, b: expr): stmt {.immediate.} = # make room for additional elements or cut: var slen = s.len |