Merge branch 'devel' into araq-overloading-symmetry
This commit is contained in:
commit
4e0b3fefa3
21 changed files with 301 additions and 244 deletions
|
|
@ -10,7 +10,7 @@
|
||||||
# abstract syntax tree + symbol table
|
# abstract syntax tree + symbol table
|
||||||
|
|
||||||
import
|
import
|
||||||
msgs, hashes, nversion, options, strutils, securehash, ropes, idents,
|
msgs, hashes, nversion, options, strutils, sha1, ropes, idents,
|
||||||
intsets, idgen
|
intsets, idgen
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, hashes, trees, platform, magicsys, extccomp, options, intsets,
|
ast, astalgo, hashes, trees, platform, magicsys, extccomp, options, intsets,
|
||||||
nversion, nimsets, msgs, securehash, bitsets, idents, types,
|
nversion, nimsets, msgs, sha1, bitsets, idents, types,
|
||||||
ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
||||||
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
|
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
|
||||||
lowerings, semparallel, tables, sets, ndi
|
lowerings, semparallel, tables, sets, ndi
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
ropes, os, strutils, osproc, platform, condsyms, options, msgs,
|
ropes, os, strutils, osproc, platform, condsyms, options, msgs,
|
||||||
securehash, streams
|
sha1, streams
|
||||||
|
|
||||||
#from debuginfo import writeDebugInfo
|
#from debuginfo import writeDebugInfo
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
## Module that implements ``gorge`` for the compiler.
|
## Module that implements ``gorge`` for the compiler.
|
||||||
|
|
||||||
import msgs, securehash, os, osproc, streams, strutils, options
|
import msgs, sha1, os, osproc, streams, strutils, options
|
||||||
|
|
||||||
proc readOutput(p: Process): (string, int) =
|
proc readOutput(p: Process): (string, int) =
|
||||||
result[0] = ""
|
result[0] = ""
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
intsets, strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups,
|
intsets, strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups,
|
||||||
semdata, passes, renderer, modulepaths
|
semdata, passes, renderer, modulepaths, sigmatch
|
||||||
|
|
||||||
proc evalImport*(c: PContext, n: PNode): PNode
|
proc evalImport*(c: PContext, n: PNode): PNode
|
||||||
proc evalFrom*(c: PContext, n: PNode): PNode
|
proc evalFrom*(c: PContext, n: PNode): PNode
|
||||||
|
|
@ -149,7 +149,7 @@ proc myImportModule(c: PContext, n: PNode): PSym =
|
||||||
localError(n.info, errGenerated, "A module cannot import itself")
|
localError(n.info, errGenerated, "A module cannot import itself")
|
||||||
if sfDeprecated in result.flags:
|
if sfDeprecated in result.flags:
|
||||||
message(n.info, warnDeprecated, result.name.s)
|
message(n.info, warnDeprecated, result.name.s)
|
||||||
#suggestSym(n.info, result, false)
|
suggestSym(n.info, result, c.graph.usageSym, false)
|
||||||
|
|
||||||
proc impMod(c: PContext; it: PNode) =
|
proc impMod(c: PContext; it: PNode) =
|
||||||
let m = myImportModule(c, it)
|
let m = myImportModule(c, it)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ implements the required case distinction.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options,
|
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options,
|
||||||
nversion, nimsets, msgs, securehash, bitsets, idents, types, os,
|
nversion, nimsets, msgs, sha1, bitsets, idents, types, os,
|
||||||
times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils,
|
times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils,
|
||||||
intsets, cgmeth, lowerings
|
intsets, cgmeth, lowerings
|
||||||
|
|
||||||
|
|
@ -2284,11 +2284,17 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
of nkFloatLit..nkFloat64Lit:
|
of nkFloatLit..nkFloat64Lit:
|
||||||
let f = n.floatVal
|
let f = n.floatVal
|
||||||
if f != f: r.res = rope"NaN"
|
case classify(f)
|
||||||
elif f == 0.0: r.res = rope"0.0"
|
of fcNaN:
|
||||||
elif f == 0.5 * f:
|
r.res = rope"NaN"
|
||||||
if f > 0.0: r.res = rope"Infinity"
|
of fcNegZero:
|
||||||
else: r.res = rope"-Infinity"
|
r.res = rope"-0.0"
|
||||||
|
of fcZero:
|
||||||
|
r.res = rope"0.0"
|
||||||
|
of fcInf:
|
||||||
|
r.res = rope"Infinity"
|
||||||
|
of fcNegInf:
|
||||||
|
r.res = rope"-Infinity"
|
||||||
else: r.res = rope(f.toStrMaxPrecision)
|
else: r.res = rope(f.toStrMaxPrecision)
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
## Implements the module handling, including the caching of modules.
|
## Implements the module handling, including the caching of modules.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, magicsys, securehash, rodread, msgs, cgendata, sigmatch, options,
|
ast, astalgo, magicsys, sha1, rodread, msgs, cgendata, sigmatch, options,
|
||||||
idents, os, lexer, idgen, passes, syntaxes, llstream, modulegraphs
|
idents, os, lexer, idgen, passes, syntaxes, llstream, modulegraphs
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
|
os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
|
||||||
ropes, idents, securehash, idgen, types, rodutils, memfiles, tables
|
ropes, idents, sha1, idgen, types, rodutils, memfiles, tables
|
||||||
|
|
||||||
type
|
type
|
||||||
TReasonForRecompile* = enum ## all the reasons that can trigger recompilation
|
TReasonForRecompile* = enum ## all the reasons that can trigger recompilation
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,22 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
## Serialization utilities for the compiler.
|
## Serialization utilities for the compiler.
|
||||||
import strutils
|
import strutils, math
|
||||||
|
|
||||||
proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf", header: "<stdio.h>", nodecl, varargs.}
|
proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf", header: "<stdio.h>", nodecl, varargs.}
|
||||||
|
|
||||||
proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
|
proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
|
||||||
if f != f:
|
case classify(f)
|
||||||
|
of fcNaN:
|
||||||
result = "NAN"
|
result = "NAN"
|
||||||
elif f == 0.0:
|
of fcNegZero:
|
||||||
|
result = "-0.0" & literalPostfix
|
||||||
|
of fcZero:
|
||||||
result = "0.0" & literalPostfix
|
result = "0.0" & literalPostfix
|
||||||
elif f == 0.5 * f:
|
of fcInf:
|
||||||
if f > 0.0: result = "INF"
|
result = "INF"
|
||||||
else: result = "-INF"
|
of fcNegInf:
|
||||||
|
result = "-INF"
|
||||||
else:
|
else:
|
||||||
when defined(nimNoArrayToCstringConversion):
|
when defined(nimNoArrayToCstringConversion):
|
||||||
result = newString(81)
|
result = newString(81)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform,
|
intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform,
|
||||||
condsyms, ropes, idents, securehash, rodread, passes, idgen,
|
condsyms, ropes, idents, sha1, rodread, passes, idgen,
|
||||||
rodutils, modulepaths
|
rodutils, modulepaths
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||||
of mDivF64:
|
of mDivF64:
|
||||||
if getFloat(b) == 0.0:
|
if getFloat(b) == 0.0:
|
||||||
if getFloat(a) == 0.0: result = newFloatNodeT(NaN, n)
|
if getFloat(a) == 0.0: result = newFloatNodeT(NaN, n)
|
||||||
|
elif getFloat(b).classify == fcNegZero: result = newFloatNodeT(-Inf, n)
|
||||||
else: result = newFloatNodeT(Inf, n)
|
else: result = newFloatNodeT(Inf, n)
|
||||||
else:
|
else:
|
||||||
result = newFloatNodeT(getFloat(a) / getFloat(b), n)
|
result = newFloatNodeT(getFloat(a) / getFloat(b), n)
|
||||||
|
|
|
||||||
|
|
@ -593,17 +593,14 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
|
||||||
notNilCheck(tracked, n, paramType)
|
notNilCheck(tracked, n, paramType)
|
||||||
|
|
||||||
proc breaksBlock(n: PNode): bool =
|
proc breaksBlock(n: PNode): bool =
|
||||||
case n.kind
|
# sematic check doesn't allow statements after raise, break, return or
|
||||||
of nkStmtList, nkStmtListExpr:
|
# call to noreturn proc, so it is safe to check just the last statements
|
||||||
for c in n:
|
var it = n
|
||||||
if breaksBlock(c): return true
|
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
|
||||||
of nkBreakStmt, nkReturnStmt, nkRaiseStmt:
|
it = it.lastSon
|
||||||
return true
|
|
||||||
of nkCallKinds:
|
result = it.kind in {nkBreakStmt, nkReturnStmt, nkRaiseStmt} or
|
||||||
if n.sons[0].kind == nkSym and sfNoReturn in n.sons[0].sym.flags:
|
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
|
||||||
return true
|
|
||||||
else:
|
|
||||||
discard
|
|
||||||
|
|
||||||
proc trackCase(tracked: PEffects, n: PNode) =
|
proc trackCase(tracked: PEffects, n: PNode) =
|
||||||
track(tracked, n.sons[0])
|
track(tracked, n.sons[0])
|
||||||
|
|
|
||||||
|
|
@ -181,11 +181,11 @@ Nim exceptions: `FloatInvalidOpError`:idx:, `FloatDivByZeroError`:idx:,
|
||||||
and `FloatInexactError`:idx:.
|
and `FloatInexactError`:idx:.
|
||||||
These exceptions inherit from the `FloatingPointError`:idx: base class.
|
These exceptions inherit from the `FloatingPointError`:idx: base class.
|
||||||
|
|
||||||
Nim provides the pragmas `NaNChecks`:idx: and `InfChecks`:idx: to control
|
Nim provides the pragmas `nanChecks`:idx: and `infChecks`:idx: to control
|
||||||
whether the IEEE exceptions are ignored or trap a Nim exception:
|
whether the IEEE exceptions are ignored or trap a Nim exception:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
{.NanChecks: on, InfChecks: on.}
|
{.nanChecks: on, infChecks: on.}
|
||||||
var a = 1.0
|
var a = 1.0
|
||||||
var b = 0.0
|
var b = 0.0
|
||||||
echo b / b # raises FloatInvalidOpError
|
echo b / b # raises FloatInvalidOpError
|
||||||
|
|
@ -195,7 +195,7 @@ In the current implementation ``FloatDivByZeroError`` and ``FloatInexactError``
|
||||||
are never raised. ``FloatOverflowError`` is raised instead of
|
are never raised. ``FloatOverflowError`` is raised instead of
|
||||||
``FloatDivByZeroError``.
|
``FloatDivByZeroError``.
|
||||||
There is also a `floatChecks`:idx: pragma that is a short-cut for the
|
There is also a `floatChecks`:idx: pragma that is a short-cut for the
|
||||||
combination of ``NaNChecks`` and ``InfChecks`` pragmas. ``floatChecks`` are
|
combination of ``nanChecks`` and ``infChecks`` pragmas. ``floatChecks`` are
|
||||||
turned off as default.
|
turned off as default.
|
||||||
|
|
||||||
The only operations that are affected by the ``floatChecks`` pragma are
|
The only operations that are affected by the ``floatChecks`` pragma are
|
||||||
|
|
|
||||||
|
|
@ -139,10 +139,15 @@ proc findExe*(exe: string, followSymlinks: bool = true;
|
||||||
## is added the `ExeExts <#ExeExts>`_ file extensions if it has none.
|
## is added the `ExeExts <#ExeExts>`_ file extensions if it has none.
|
||||||
## If the system supports symlinks it also resolves them until it
|
## If the system supports symlinks it also resolves them until it
|
||||||
## meets the actual file. This behavior can be disabled if desired.
|
## meets the actual file. This behavior can be disabled if desired.
|
||||||
for ext in extensions:
|
template checkCurrentDir() =
|
||||||
result = addFileExt(exe, ext)
|
for ext in extensions:
|
||||||
if existsFile(result): return
|
result = addFileExt(exe, ext)
|
||||||
var path = string(getEnv("PATH"))
|
if existsFile(result): return
|
||||||
|
when defined(posix):
|
||||||
|
if '/' in exe: checkCurrentDir()
|
||||||
|
else:
|
||||||
|
checkCurrentDir()
|
||||||
|
let path = string(getEnv("PATH"))
|
||||||
for candidate in split(path, PathSep):
|
for candidate in split(path, PathSep):
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
var x = (if candidate[0] == '"' and candidate[^1] == '"':
|
var x = (if candidate[0] == '"' and candidate[^1] == '"':
|
||||||
|
|
|
||||||
|
|
@ -1,195 +1,6 @@
|
||||||
#
|
|
||||||
#
|
|
||||||
# The Nim Compiler
|
|
||||||
# (c) Copyright 2015 Nim Contributors
|
|
||||||
#
|
|
||||||
# See the file "copying.txt", included in this
|
|
||||||
# distribution, for details about the copyright.
|
|
||||||
#
|
|
||||||
|
|
||||||
import strutils
|
|
||||||
|
|
||||||
const Sha1DigestSize = 20
|
|
||||||
|
|
||||||
type
|
|
||||||
Sha1Digest = array[0 .. Sha1DigestSize-1, uint8]
|
|
||||||
SecureHash* = distinct Sha1Digest
|
|
||||||
|
|
||||||
# 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 =
|
|
||||||
(value shl bits) or (value shr (32u32 - bits))
|
|
||||||
|
|
||||||
template sha1(fun, val: uint32) =
|
|
||||||
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: untyped) =
|
|
||||||
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: untyped) =
|
|
||||||
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
|
|
||||||
|
|
||||||
proc sha1(src: cstring; len: int): Sha1Digest =
|
|
||||||
#Initialize state
|
|
||||||
var state: Sha1State
|
|
||||||
init(state)
|
|
||||||
|
|
||||||
#Create w buffer
|
|
||||||
var w: Sha1Buffer
|
|
||||||
|
|
||||||
#Loop through all complete 64byte blocks.
|
|
||||||
let byteLen = 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 - uint32(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 - uint32(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
|
|
||||||
sha1(src, src.len)
|
|
||||||
|
|
||||||
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:
|
## This module is a deprecated alias for the ``sha1`` module.
|
||||||
let hash1 = secureHash("a93tgj0p34jagp9[agjp98ajrhp9aej]")
|
{.deprecated.}
|
||||||
doAssert hash1 == hash1
|
|
||||||
doAssert parseSecureHash($hash1) == hash1
|
include sha1
|
||||||
|
|
|
||||||
195
lib/pure/sha1.nim
Normal file
195
lib/pure/sha1.nim
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The Nim Compiler
|
||||||
|
# (c) Copyright 2015 Nim Contributors
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
import strutils
|
||||||
|
|
||||||
|
const Sha1DigestSize = 20
|
||||||
|
|
||||||
|
type
|
||||||
|
Sha1Digest = array[0 .. Sha1DigestSize-1, uint8]
|
||||||
|
SecureHash* = distinct Sha1Digest
|
||||||
|
|
||||||
|
# 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 =
|
||||||
|
(value shl bits) or (value shr (32u32 - bits))
|
||||||
|
|
||||||
|
template sha1(fun, val: uint32) =
|
||||||
|
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: untyped) =
|
||||||
|
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: untyped) =
|
||||||
|
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
|
||||||
|
|
||||||
|
proc sha1(src: cstring; len: int): Sha1Digest =
|
||||||
|
#Initialize state
|
||||||
|
var state: Sha1State
|
||||||
|
init(state)
|
||||||
|
|
||||||
|
#Create w buffer
|
||||||
|
var w: Sha1Buffer
|
||||||
|
|
||||||
|
#Loop through all complete 64byte blocks.
|
||||||
|
let byteLen = 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 - uint32(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 - uint32(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
|
||||||
|
sha1(src, src.len)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
@ -47,10 +47,16 @@ when not declared(c_fwrite):
|
||||||
# C routine that is used here:
|
# C routine that is used here:
|
||||||
proc c_fread(buf: pointer, size, n: csize, f: File): csize {.
|
proc c_fread(buf: pointer, size, n: csize, f: File): csize {.
|
||||||
importc: "fread", header: "<stdio.h>", tags: [ReadIOEffect].}
|
importc: "fread", header: "<stdio.h>", tags: [ReadIOEffect].}
|
||||||
proc c_fseek(f: File, offset: clong, whence: cint): cint {.
|
when defined(windows):
|
||||||
importc: "fseek", header: "<stdio.h>", tags: [].}
|
proc c_fseek(f: File, offset: int64, whence: cint): cint {.
|
||||||
proc c_ftell(f: File): clong {.
|
importc: "_fseeki64", header: "<stdio.h>", tags: [].}
|
||||||
importc: "ftell", header: "<stdio.h>", tags: [].}
|
proc c_ftell(f: File): int64 {.
|
||||||
|
importc: "_ftelli64", header: "<stdio.h>", tags: [].}
|
||||||
|
else:
|
||||||
|
proc c_fseek(f: File, offset: int64, whence: cint): cint {.
|
||||||
|
importc: "fseeko", header: "<stdio.h>", tags: [].}
|
||||||
|
proc c_ftell(f: File): int64 {.
|
||||||
|
importc: "ftello", header: "<stdio.h>", tags: [].}
|
||||||
proc c_ferror(f: File): cint {.
|
proc c_ferror(f: File): cint {.
|
||||||
importc: "ferror", header: "<stdio.h>", tags: [].}
|
importc: "ferror", header: "<stdio.h>", tags: [].}
|
||||||
proc c_setvbuf(f: File, buf: pointer, mode: cint, size: csize): cint {.
|
proc c_setvbuf(f: File, buf: pointer, mode: cint, size: csize): cint {.
|
||||||
|
|
@ -210,12 +216,12 @@ proc readAllBuffer(file: File): string =
|
||||||
result.add(buffer)
|
result.add(buffer)
|
||||||
break
|
break
|
||||||
|
|
||||||
proc rawFileSize(file: File): int =
|
proc rawFileSize(file: File): int64 =
|
||||||
# this does not raise an error opposed to `getFileSize`
|
# this does not raise an error opposed to `getFileSize`
|
||||||
var oldPos = c_ftell(file)
|
var oldPos = c_ftell(file)
|
||||||
discard c_fseek(file, 0, 2) # seek the end of the file
|
discard c_fseek(file, 0, 2) # seek the end of the file
|
||||||
result = c_ftell(file)
|
result = c_ftell(file)
|
||||||
discard c_fseek(file, clong(oldPos), 0)
|
discard c_fseek(file, oldPos, 0)
|
||||||
|
|
||||||
proc endOfFile(f: File): bool =
|
proc endOfFile(f: File): bool =
|
||||||
var c = c_fgetc(f)
|
var c = c_fgetc(f)
|
||||||
|
|
@ -223,7 +229,7 @@ proc endOfFile(f: File): bool =
|
||||||
return c < 0'i32
|
return c < 0'i32
|
||||||
#result = c_feof(f) != 0
|
#result = c_feof(f) != 0
|
||||||
|
|
||||||
proc readAllFile(file: File, len: int): string =
|
proc readAllFile(file: File, len: int64): string =
|
||||||
# We acquire the filesize beforehand and hope it doesn't change.
|
# We acquire the filesize beforehand and hope it doesn't change.
|
||||||
# Speeds things up.
|
# Speeds things up.
|
||||||
result = newString(len)
|
result = newString(len)
|
||||||
|
|
@ -363,7 +369,7 @@ proc open(f: var File, filehandle: FileHandle, mode: FileMode): bool =
|
||||||
result = f != nil
|
result = f != nil
|
||||||
|
|
||||||
proc setFilePos(f: File, pos: int64, relativeTo: FileSeekPos = fspSet) =
|
proc setFilePos(f: File, pos: int64, relativeTo: FileSeekPos = fspSet) =
|
||||||
if c_fseek(f, clong(pos), cint(relativeTo)) != 0:
|
if c_fseek(f, pos, cint(relativeTo)) != 0:
|
||||||
raiseEIO("cannot set file position")
|
raiseEIO("cannot set file position")
|
||||||
|
|
||||||
proc getFilePos(f: File): int64 =
|
proc getFilePos(f: File): int64 =
|
||||||
|
|
|
||||||
9
tests/ccgbugs/t7079.nim
Normal file
9
tests/ccgbugs/t7079.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
discard """
|
||||||
|
action: run
|
||||||
|
targets: '''c js'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import math
|
||||||
|
let x = -0.0
|
||||||
|
doAssert classify(x) == fcNegZero
|
||||||
|
doAssert classify(1 / -0.0) == fcNegInf
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import
|
import
|
||||||
unittest, osproc, streams, os
|
unittest, osproc, streams, os, strformat
|
||||||
const STRING_DATA = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
|
const STRING_DATA = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
|
||||||
const TEST_FILE = "tests/testdata/string.txt"
|
const TEST_FILE = "tests/testdata/string.txt"
|
||||||
|
|
||||||
|
|
@ -23,3 +23,26 @@ suite "io":
|
||||||
test "file":
|
test "file":
|
||||||
check:
|
check:
|
||||||
readFile(TEST_FILE) == STRING_DATA
|
readFile(TEST_FILE) == STRING_DATA
|
||||||
|
|
||||||
|
|
||||||
|
proc verifyFileSize(sz: int64) =
|
||||||
|
# issue 7121, large file size (2-4GB and >4Gb)
|
||||||
|
const fn = "tmpfile112358"
|
||||||
|
let size_in_mb = sz div 1_000_000
|
||||||
|
|
||||||
|
when defined(windows):
|
||||||
|
discard execProcess(&"fsutil file createnew {fn} {sz}" )
|
||||||
|
else:
|
||||||
|
discard execProcess(&"dd if=/dev/zero of={fn} bs=1000000 count={size_in_mb}")
|
||||||
|
|
||||||
|
doAssert os.getFileSize(fn) == sz # Verify OS filesize by string
|
||||||
|
|
||||||
|
var f = open(fn)
|
||||||
|
doAssert f.getFileSize() == sz # Verify file handle filesize
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
os.removeFile(fn)
|
||||||
|
|
||||||
|
#disable tests for automatic testers
|
||||||
|
#for s in [50_000_000'i64, 3_000_000_000, 5_000_000_000]:
|
||||||
|
# verifyFileSize(s)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ when haveZipLib:
|
||||||
|
|
||||||
import
|
import
|
||||||
os, osproc, strutils, parseopt, parsecfg, strtabs, streams, debcreation,
|
os, osproc, strutils, parseopt, parsecfg, strtabs, streams, debcreation,
|
||||||
securehash
|
sha1
|
||||||
|
|
||||||
const
|
const
|
||||||
maxOS = 20 # max number of OSes
|
maxOS = 20 # max number of OSes
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ srcdoc2: "pure/asyncfile;pure/asyncftpclient;pure/lenientops"
|
||||||
srcdoc2: "pure/md5;pure/rationals"
|
srcdoc2: "pure/md5;pure/rationals"
|
||||||
srcdoc2: "posix/posix;pure/distros;pure/oswalkdir"
|
srcdoc2: "posix/posix;pure/distros;pure/oswalkdir"
|
||||||
srcdoc2: "pure/collections/heapqueue"
|
srcdoc2: "pure/collections/heapqueue"
|
||||||
srcdoc2: "pure/fenv;pure/securehash;impure/rdstdin;pure/strformat"
|
srcdoc2: "pure/fenv;pure/sha1;impure/rdstdin;pure/strformat"
|
||||||
srcdoc2: "pure/segfaults"
|
srcdoc2: "pure/segfaults"
|
||||||
srcdoc2: "pure/basic2d;pure/basic3d;pure/mersenne;pure/coro;pure/httpcore"
|
srcdoc2: "pure/basic2d;pure/basic3d;pure/mersenne;pure/coro;pure/httpcore"
|
||||||
srcdoc2: "pure/bitops;pure/nimtracker;pure/punycode;pure/volatile;js/asyncjs"
|
srcdoc2: "pure/bitops;pure/nimtracker;pure/punycode;pure/volatile;js/asyncjs"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue