Merge branch 'devel' of https://github.com/Araq/Nimrod into devel
This commit is contained in:
commit
820fdd6348
91 changed files with 1372 additions and 1370 deletions
|
|
@ -294,19 +294,6 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst".}
|
|||
## if not `ex`:
|
||||
## echo `info` & ": Check failed: " & `expString`
|
||||
|
||||
when not defined(booting):
|
||||
template emit*(e: static[string]): stmt =
|
||||
## accepts a single string argument and treats it as nimrod code
|
||||
## that should be inserted verbatim in the program
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## emit("echo " & '"' & "hello world".toUpper & '"')
|
||||
##
|
||||
macro payload: stmt {.gensym.} =
|
||||
result = e.parseStmt
|
||||
payload()
|
||||
|
||||
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
||||
## checks that `n` is of kind `k`. If this is not the case,
|
||||
## compilation aborts with an error message. This is useful for writing
|
||||
|
|
@ -421,7 +408,8 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
|
|||
of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
|
||||
of nnkStrLit..nnkTripleStrLit: add(result, $n.strVal)
|
||||
of nnkIdent: add(result, "!\"" & $n.ident & '"')
|
||||
of nnkSym, nnkNone: assert false
|
||||
of nnkSym: add(result, $n.symbol)
|
||||
of nnkNone: assert false
|
||||
else:
|
||||
add(result, lispRepr(n[0]))
|
||||
for j in 1..n.len-1:
|
||||
|
|
@ -745,3 +733,15 @@ proc addIdentIfAbsent*(dest: PNimrodNode, ident: string) {.compiletime.} =
|
|||
else: discard
|
||||
dest.add(ident(ident))
|
||||
|
||||
when not defined(booting):
|
||||
template emit*(e: static[string]): stmt =
|
||||
## accepts a single string argument and treats it as nimrod code
|
||||
## that should be inserted verbatim in the program
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## emit("echo " & '"' & "hello world".toUpper & '"')
|
||||
##
|
||||
macro payload: stmt {.gensym.} =
|
||||
result = parseStmt(e)
|
||||
payload()
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ proc open*(host: string = defaultHost, port: int = defaultPort): TDbConn {.
|
|||
## be established.
|
||||
init(result)
|
||||
|
||||
let x = connect(result, host, port.cint)
|
||||
let x = client(result, host, port.cint)
|
||||
if x != 0'i32:
|
||||
dbError(result, "cannot open: " & host)
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ proc insertId*(db: var TDbConn, namespace: string, data: PJsonNode): TOid {.
|
|||
## the generated OID for the ``_id`` field.
|
||||
result = genOid()
|
||||
var x = jsonToBSon(data, result)
|
||||
insert(db, namespace, x)
|
||||
insert(db, namespace, x, nil)
|
||||
destroy(x)
|
||||
|
||||
proc insert*(db: var TDbConn, namespace: string, data: PJsonNode) {.
|
||||
|
|
|
|||
|
|
@ -148,7 +148,8 @@ proc getValue*(db: TDbConn, query: TSqlQuery,
|
|||
if finalize(stmt) != SQLITE_OK: dbError(db)
|
||||
|
||||
proc tryInsertID*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
|
||||
args: varargs[string, `$`]): int64
|
||||
{.tags: [FWriteDb], raises: [].} =
|
||||
## executes the query (typically "INSERT") and returns the
|
||||
## generated ID for the row or -1 in case of an error.
|
||||
var q = dbFormat(query, args)
|
||||
|
|
@ -157,7 +158,8 @@ proc tryInsertID*(db: TDbConn, query: TSqlQuery,
|
|||
if prepare_v2(db, q, q.len.cint, stmt, nil) == SQLITE_OK:
|
||||
if step(stmt) == SQLITE_DONE:
|
||||
result = last_insert_rowid(db)
|
||||
if finalize(stmt) != SQLITE_OK: dbError(db)
|
||||
if finalize(stmt) != SQLITE_OK:
|
||||
result = -1
|
||||
|
||||
proc insertID*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type
|
|||
gtEof, gtNone, gtWhitespace, gtDecNumber, gtBinNumber, gtHexNumber,
|
||||
gtOctNumber, gtFloatNumber, gtIdentifier, gtKeyword, gtStringLit,
|
||||
gtLongStringLit, gtCharLit, gtEscapeSequence, # escape sequence like \xff
|
||||
gtOperator, gtPunctation, gtComment, gtLongComment, gtRegularExpression,
|
||||
gtOperator, gtPunctuation, gtComment, gtLongComment, gtRegularExpression,
|
||||
gtTagStart, gtTagEnd, gtKey, gtValue, gtRawData, gtAssembler,
|
||||
gtPreprocessor, gtDirective, gtCommand, gtRule, gtHyperlink, gtLabel,
|
||||
gtReference, gtOther
|
||||
|
|
@ -39,7 +39,7 @@ const
|
|||
tokenClassToStr*: array[TTokenClass, string] = ["Eof", "None", "Whitespace",
|
||||
"DecNumber", "BinNumber", "HexNumber", "OctNumber", "FloatNumber",
|
||||
"Identifier", "Keyword", "StringLit", "LongStringLit", "CharLit",
|
||||
"EscapeSequence", "Operator", "Punctation", "Comment", "LongComment",
|
||||
"EscapeSequence", "Operator", "Punctuation", "Comment", "LongComment",
|
||||
"RegularExpression", "TagStart", "TagEnd", "Key", "Value", "RawData",
|
||||
"Assembler", "Preprocessor", "Directive", "Command", "Rule", "Hyperlink",
|
||||
"Label", "Reference", "Other"]
|
||||
|
|
@ -258,7 +258,7 @@ proc nimNextToken(g: var TGeneralTokenizer) =
|
|||
else: inc(pos)
|
||||
of '(', ')', '[', ']', '{', '}', '`', ':', ',', ';':
|
||||
inc(pos)
|
||||
g.kind = gtPunctation
|
||||
g.kind = gtPunctuation
|
||||
of '\0':
|
||||
g.kind = gtEof
|
||||
else:
|
||||
|
|
@ -473,7 +473,7 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openArray[string],
|
|||
else: inc(pos)
|
||||
of '(', ')', '[', ']', '{', '}', ':', ',', ';', '.':
|
||||
inc(pos)
|
||||
g.kind = gtPunctation
|
||||
g.kind = gtPunctuation
|
||||
of '\0':
|
||||
g.kind = gtEof
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -2566,3 +2566,15 @@ proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {.
|
|||
|
||||
proc realpath*(name, resolved: cstring): cstring {.
|
||||
importc: "realpath", header: "<stdlib.h>".}
|
||||
|
||||
proc utimes*(path: cstring, times: ptr array [2, Ttimeval]): int {.
|
||||
importc: "utimes", header: "<sys/time.h>".}
|
||||
## Sets file access and modification times.
|
||||
##
|
||||
## Pass the filename and an array of times to set the access and modification
|
||||
## times respectively. If you pass nil as the array both attributes will be
|
||||
## set to the current time.
|
||||
##
|
||||
## Returns zero on success.
|
||||
##
|
||||
## For more information read http://www.unix.com/man-page/posix/3/utimes/.
|
||||
|
|
|
|||
|
|
@ -131,3 +131,36 @@ proc sort*[T](a: var openArray[T],
|
|||
dec(m, s*2)
|
||||
s = s*2
|
||||
|
||||
proc product*[T](x: openarray[seq[T]]): seq[seq[T]] =
|
||||
## produces the Cartesian product of the array. Warning: complexity
|
||||
## may explode.
|
||||
result = @[]
|
||||
if x.len == 0:
|
||||
return
|
||||
if x.len == 1:
|
||||
result = @x
|
||||
return
|
||||
var
|
||||
indexes = newSeq[int](x.len)
|
||||
initial = newSeq[int](x.len)
|
||||
index = 0
|
||||
# replace with newSeq as soon as #853 is fixed
|
||||
var next: seq[T] = @[]
|
||||
next.setLen(x.len)
|
||||
for i in 0..(x.len-1):
|
||||
if len(x[i]) == 0: return
|
||||
initial[i] = len(x[i])-1
|
||||
indexes = initial
|
||||
while true:
|
||||
while indexes[index] == -1:
|
||||
indexes[index] = initial[index]
|
||||
index +=1
|
||||
if index == x.len: return
|
||||
indexes[index] -=1
|
||||
for ni, i in indexes:
|
||||
next[ni] = x[ni][i]
|
||||
var res: seq[T]
|
||||
shallowCopy(res, next)
|
||||
result.add(res)
|
||||
index = 0
|
||||
indexes[index] -=1
|
||||
|
|
|
|||
|
|
@ -689,5 +689,5 @@ when isMainModule:
|
|||
server.listen()
|
||||
d.register(server)
|
||||
|
||||
while d.poll(-1): nil
|
||||
while d.poll(-1): discard
|
||||
|
||||
|
|
|
|||
|
|
@ -276,6 +276,38 @@ template foldr*(sequence, operation: expr): expr =
|
|||
result = operation
|
||||
result
|
||||
|
||||
template mapIt*(seq1, typ, pred: expr): expr =
|
||||
## Convenience template around the ``map`` proc to reduce typing.
|
||||
##
|
||||
## The template injects the ``it`` variable which you can use directly in an
|
||||
## expression. You also need to pass as `typ` the type of the expression,
|
||||
## since the new returned sequence can have a different type than the
|
||||
## original. Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## let
|
||||
## nums = @[1, 2, 3, 4]
|
||||
## strings = nums.mapIt(string, $(4 * it))
|
||||
var result {.gensym.}: seq[typ] = @[]
|
||||
for it {.inject.} in items(seq1):
|
||||
result.add(pred)
|
||||
result
|
||||
|
||||
template mapIt*(varSeq, pred: expr) =
|
||||
## Convenience template around the mutable ``map`` proc to reduce typing.
|
||||
##
|
||||
## The template injects the ``it`` variable which you can use directly in an
|
||||
## expression. The expression has to return the same type as the sequence you
|
||||
## are mutating. Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## var nums = @[1, 2, 3, 4]
|
||||
## nums.mapIt(it * 3)
|
||||
## assert nums[0] + nums[3] == 15
|
||||
for i in 0 .. <len(varSeq):
|
||||
let it {.inject.} = varSeq[i]
|
||||
varSeq[i] = pred
|
||||
|
||||
when isMainModule:
|
||||
import strutils
|
||||
block: # concat test
|
||||
|
|
@ -381,4 +413,11 @@ when isMainModule:
|
|||
Inserting [2,2,2,2,2,2] into [1,1,1,1,1,1,1,1]
|
||||
at 3 is [1,1,1,2,2,2,2,2,2,1,1,1,1,1]"""
|
||||
|
||||
block: # mapIt tests
|
||||
var
|
||||
nums = @[1, 2, 3, 4]
|
||||
strings = nums.mapIt(string, $(4 * it))
|
||||
nums.mapIt(it * 3)
|
||||
assert nums[0] + nums[3] == 15
|
||||
|
||||
echo "Finished doc tests"
|
||||
|
|
|
|||
|
|
@ -224,3 +224,20 @@ proc toOrderedSet*[A](keys: openArray[A]): TOrderedSet[A] =
|
|||
proc `$`*[A](s: TOrderedSet[A]): string =
|
||||
## The `$` operator for ordered hash sets.
|
||||
dollarImpl()
|
||||
|
||||
proc `<`*[A](s, t: TSet[A]): bool =
|
||||
## Is s a strict subset of t?
|
||||
s.counter != t.counter and s <= t
|
||||
|
||||
proc `<=`*[A](s, t: TSet[A]): bool =
|
||||
## Is s a subset of t?
|
||||
result = false
|
||||
if s.counter > t.counter: return
|
||||
result = true
|
||||
for item in s:
|
||||
if not(t.contains(item)):
|
||||
result = false
|
||||
return
|
||||
|
||||
proc `==`*[A](s, t: TSet[A]): bool =
|
||||
s.counter == t.counter and s <= t
|
||||
|
|
|
|||
|
|
@ -189,6 +189,16 @@ template dollarImpl(): stmt {.dirty.} =
|
|||
proc `$`*[A, B](t: TTable[A, B]): string =
|
||||
## The `$` operator for hash tables.
|
||||
dollarImpl()
|
||||
|
||||
proc `==`*[A, B](s, t: TTable[A, B]): bool =
|
||||
s.counter == t.counter and s.data == t.data
|
||||
|
||||
proc indexBy*[A, B, C](collection: A, index: proc(x: B): C): TTable[C, B] =
|
||||
## Index the collection with the proc provided.
|
||||
# TODO: As soon as supported, change collection: A to collection: A[B]
|
||||
result = initTable[C, B]()
|
||||
for item in collection:
|
||||
result[index(item)] = item
|
||||
|
||||
# ------------------------------ ordered table ------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -14,15 +14,15 @@
|
|||
type
|
||||
TLibHandle* = pointer ## a handle to a dynamically loaded library
|
||||
|
||||
proc LoadLib*(path: string): TLibHandle
|
||||
proc loadLib*(path: string): TLibHandle
|
||||
## loads a library from `path`. Returns nil if the library could not
|
||||
## be loaded.
|
||||
|
||||
proc LoadLib*(): TLibHandle
|
||||
proc loadLib*(): TLibHandle
|
||||
## gets the handle from the current executable. Returns nil if the
|
||||
## library could not be loaded.
|
||||
|
||||
proc UnloadLib*(lib: TLibHandle)
|
||||
proc unloadLib*(lib: TLibHandle)
|
||||
## unloads the library `lib`
|
||||
|
||||
proc raiseInvalidLibrary*(name: cstring) {.noinline, noreturn.} =
|
||||
|
|
@ -60,9 +60,9 @@ when defined(posix):
|
|||
proc dlsym(lib: TLibHandle, name: cstring): pointer {.
|
||||
importc, header: "<dlfcn.h>".}
|
||||
|
||||
proc LoadLib(path: string): TLibHandle = return dlopen(path, RTLD_NOW)
|
||||
proc LoadLib(): TLibHandle = return dlopen(nil, RTLD_NOW)
|
||||
proc UnloadLib(lib: TLibHandle) = dlclose(lib)
|
||||
proc loadLib(path: string): TLibHandle = return dlopen(path, RTLD_NOW)
|
||||
proc loadLib(): TLibHandle = return dlopen(nil, RTLD_NOW)
|
||||
proc unloadLib(lib: TLibHandle) = dlclose(lib)
|
||||
proc symAddr(lib: TLibHandle, name: cstring): pointer =
|
||||
return dlsym(lib, name)
|
||||
|
||||
|
|
@ -78,14 +78,14 @@ elif defined(windows) or defined(dos):
|
|||
proc FreeLibrary(lib: THINSTANCE) {.importc, header: "<windows.h>", stdcall.}
|
||||
proc winLoadLibrary(path: cstring): THINSTANCE {.
|
||||
importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
|
||||
proc GetProcAddress(lib: THINSTANCE, name: cstring): pointer {.
|
||||
proc getProcAddress(lib: THINSTANCE, name: cstring): pointer {.
|
||||
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
|
||||
|
||||
proc LoadLib(path: string): TLibHandle =
|
||||
proc loadLib(path: string): TLibHandle =
|
||||
result = cast[TLibHandle](winLoadLibrary(path))
|
||||
proc LoadLib(): TLibHandle =
|
||||
proc loadLib(): TLibHandle =
|
||||
result = cast[TLibHandle](winLoadLibrary(nil))
|
||||
proc UnloadLib(lib: TLibHandle) = FreeLibrary(cast[THINSTANCE](lib))
|
||||
proc unloadLib(lib: TLibHandle) = FreeLibrary(cast[THINSTANCE](lib))
|
||||
|
||||
proc symAddr(lib: TLibHandle, name: cstring): pointer =
|
||||
result = GetProcAddress(cast[THINSTANCE](lib), name)
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ proc untilElementEnd(x: var TXmlParser, result: PXmlNode,
|
|||
if htmlTag(x.elemName) in {tagOption, tagOptgroup}:
|
||||
errors.add(expected(x, result))
|
||||
break
|
||||
else: nil
|
||||
else: discard
|
||||
result.addNode(parse(x, errors))
|
||||
of xmlElementEnd:
|
||||
if cmpIgnoreCase(x.elemName, result.tag) == 0:
|
||||
|
|
@ -547,7 +547,7 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode =
|
|||
var u = entityToUtf8(x.rawData)
|
||||
if u.len != 0: result = newText(u)
|
||||
next(x)
|
||||
of xmlEof: nil
|
||||
of xmlEof: discard
|
||||
|
||||
proc parseHtml*(s: PStream, filename: string,
|
||||
errors: var seq[string]): PXmlNode =
|
||||
|
|
|
|||
|
|
@ -476,12 +476,12 @@ when isMainModule:
|
|||
var client = irc("amber.tenthbit.net", nick="TestBot1234",
|
||||
joinChans = @["#flood"])
|
||||
client.connect()
|
||||
while True:
|
||||
while true:
|
||||
var event: TIRCEvent
|
||||
if client.poll(event):
|
||||
case event.typ
|
||||
of EvConnected:
|
||||
nil
|
||||
discard
|
||||
of EvDisconnected:
|
||||
break
|
||||
of EvMsg:
|
||||
|
|
|
|||
267
lib/pure/logging.nim
Normal file
267
lib/pure/logging.nim
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2014 Andreas Rumpf, Dominik Picheta
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements a simple logger. It has been designed to be as simple
|
||||
## as possible to avoid bloat, if this library does not fullfill your needs,
|
||||
## write your own.
|
||||
##
|
||||
## Format strings support the following variables which must be prefixed with
|
||||
## the dollar operator (``$``):
|
||||
##
|
||||
## ============ =======================
|
||||
## Operator Output
|
||||
## ============ =======================
|
||||
## $date Current date
|
||||
## $time Current time
|
||||
## $app ``os.getAppFilename()``
|
||||
## ============ =======================
|
||||
##
|
||||
##
|
||||
## The following example demonstrates logging to three different handlers
|
||||
## simultaneously:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
##
|
||||
## var L = newConsoleLogger()
|
||||
## var fL = newFileLogger("test.log", fmtStr = verboseFmtStr)
|
||||
## var rL = newRollingFileLogger("rolling.log", fmtStr = verboseFmtStr)
|
||||
## handlers.add(L)
|
||||
## handlers.add(fL)
|
||||
## handlers.add(rL)
|
||||
## info("920410:52 accepted")
|
||||
## warn("4 8 15 16 23 4-- Error")
|
||||
## error("922044:16 SYSTEM FAILURE")
|
||||
## fatal("SYSTEM FAILURE SYSTEM FAILURE")
|
||||
|
||||
import strutils, os, times
|
||||
|
||||
type
|
||||
TLevel* = enum ## logging level
|
||||
lvlAll, ## all levels active
|
||||
lvlDebug, ## debug level (and any above) active
|
||||
lvlInfo, ## info level (and any above) active
|
||||
lvlWarn, ## warn level (and any above) active
|
||||
lvlError, ## error level (and any above) active
|
||||
lvlFatal, ## fatal level (and any above) active
|
||||
lvlNone ## no levels active
|
||||
|
||||
const
|
||||
LevelNames*: array [TLevel, string] = [
|
||||
"DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE"
|
||||
]
|
||||
|
||||
defaultFmtStr* = "" ## default string between log level and message per logger
|
||||
verboseFmtStr* = "$date $time "
|
||||
|
||||
type
|
||||
PLogger* = ref object of PObject ## abstract logger; the base type of all loggers
|
||||
levelThreshold*: TLevel ## only messages of level >= levelThreshold
|
||||
## should be processed
|
||||
fmtStr: string ## = defaultFmtStr by default, see substituteLog for $date etc.
|
||||
|
||||
PConsoleLogger* = ref object of PLogger ## logger that writes the messages to the
|
||||
## console
|
||||
|
||||
PFileLogger* = ref object of PLogger ## logger that writes the messages to a file
|
||||
f: TFile
|
||||
|
||||
PRollingFileLogger* = ref object of PFileLogger ## logger that writes the
|
||||
## messages to a file and
|
||||
## performs log rotation
|
||||
maxLines: int # maximum number of lines
|
||||
curLine : int
|
||||
baseName: string # initial filename
|
||||
baseMode: TFileMode # initial file mode
|
||||
logFiles: int # how many log files already created, e.g. basename.1, basename.2...
|
||||
|
||||
proc substituteLog(frmt: string): string =
|
||||
## converts $date to the current date
|
||||
## converts $time to the current time
|
||||
## converts $app to getAppFilename()
|
||||
## converts
|
||||
result = newStringOfCap(frmt.len + 20)
|
||||
var i = 0
|
||||
while i < frmt.len:
|
||||
if frmt[i] != '$':
|
||||
result.add(frmt[i])
|
||||
inc(i)
|
||||
else:
|
||||
inc(i)
|
||||
var v = ""
|
||||
var app = getAppFilename()
|
||||
while frmt[i] in IdentChars:
|
||||
v.add(toLower(frmt[i]))
|
||||
inc(i)
|
||||
case v
|
||||
of "date": result.add(getDateStr())
|
||||
of "time": result.add(getClockStr())
|
||||
of "app": result.add(app)
|
||||
of "appdir": result.add(app.splitFile.dir)
|
||||
of "appname": result.add(app.splitFile.name)
|
||||
|
||||
method log*(logger: PLogger, level: TLevel,
|
||||
frmt: string, args: varargs[string, `$`]) {.raises: [EBase], tags: [FTime, FWriteIO, FReadIO].} =
|
||||
## Override this method in custom loggers. Default implementation does
|
||||
## nothing.
|
||||
discard
|
||||
|
||||
method log*(logger: PConsoleLogger, level: TLevel,
|
||||
frmt: string, args: varargs[string, `$`]) =
|
||||
## Logs to the console using ``logger`` only.
|
||||
if level >= logger.levelThreshold:
|
||||
writeln(stdout, LevelNames[level], " ", substituteLog(logger.fmtStr),
|
||||
frmt % args)
|
||||
|
||||
method log*(logger: PFileLogger, level: TLevel,
|
||||
frmt: string, args: varargs[string, `$`]) =
|
||||
## Logs to a file using ``logger`` only.
|
||||
if level >= logger.levelThreshold:
|
||||
writeln(logger.f, LevelNames[level], " ",
|
||||
substituteLog(logger.fmtStr), frmt % args)
|
||||
|
||||
proc defaultFilename*(): string =
|
||||
## Returns the default filename for a logger.
|
||||
var (path, name, ext) = splitFile(getAppFilename())
|
||||
result = changeFileExt(path / name, "log")
|
||||
|
||||
proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr): PConsoleLogger =
|
||||
## Creates a new console logger. This logger logs to the console.
|
||||
new result
|
||||
result.fmtStr = fmtStr
|
||||
result.levelThreshold = levelThreshold
|
||||
|
||||
proc newFileLogger*(filename = defaultFilename(),
|
||||
mode: TFileMode = fmAppend,
|
||||
levelThreshold = lvlAll,
|
||||
fmtStr = defaultFmtStr): PFileLogger =
|
||||
## Creates a new file logger. This logger logs to a file.
|
||||
new(result)
|
||||
result.levelThreshold = levelThreshold
|
||||
result.f = open(filename, mode)
|
||||
result.fmtStr = fmtStr
|
||||
|
||||
# ------
|
||||
|
||||
proc countLogLines(logger: PRollingFileLogger): int =
|
||||
result = 0
|
||||
for line in logger.f.lines():
|
||||
result.inc()
|
||||
|
||||
proc countFiles(filename: string): int =
|
||||
# Example: file.log.1
|
||||
result = 0
|
||||
let (dir, name, ext) = splitFile(filename)
|
||||
for kind, path in walkDir(dir):
|
||||
if kind == pcFile:
|
||||
let llfn = name & ext & ExtSep
|
||||
if path.extractFilename.startsWith(llfn):
|
||||
let numS = path.extractFilename[llfn.len .. -1]
|
||||
try:
|
||||
let num = parseInt(numS)
|
||||
if num > result:
|
||||
result = num
|
||||
except EInvalidValue: discard
|
||||
|
||||
proc newRollingFileLogger*(filename = defaultFilename(),
|
||||
mode: TFileMode = fmReadWrite,
|
||||
levelThreshold = lvlAll,
|
||||
fmtStr = defaultFmtStr,
|
||||
maxLines = 1000): PRollingFileLogger =
|
||||
## Creates a new rolling file logger. Once a file reaches ``maxLines`` lines
|
||||
## a new log file will be started and the old will be renamed.
|
||||
new(result)
|
||||
result.levelThreshold = levelThreshold
|
||||
result.fmtStr = defaultFmtStr
|
||||
result.maxLines = maxLines
|
||||
result.f = open(filename, mode)
|
||||
result.curLine = 0
|
||||
result.baseName = filename
|
||||
result.baseMode = mode
|
||||
|
||||
result.logFiles = countFiles(filename)
|
||||
|
||||
if mode == fmAppend:
|
||||
# We need to get a line count because we will be appending to the file.
|
||||
result.curLine = countLogLines(result)
|
||||
|
||||
proc rotate(logger: PRollingFileLogger) =
|
||||
let (dir, name, ext) = splitFile(logger.baseName)
|
||||
for i in countdown(logger.logFiles, 0):
|
||||
let srcSuff = if i != 0: ExtSep & $i else: ""
|
||||
moveFile(dir / (name & ext & srcSuff),
|
||||
dir / (name & ext & ExtSep & $(i+1)))
|
||||
|
||||
method log*(logger: PRollingFileLogger, level: TLevel,
|
||||
frmt: string, args: varargs[string, `$`]) =
|
||||
## Logs to a file using rolling ``logger`` only.
|
||||
if level >= logger.levelThreshold:
|
||||
if logger.curLine >= logger.maxLines:
|
||||
logger.f.close()
|
||||
rotate(logger)
|
||||
logger.logFiles.inc
|
||||
logger.curLine = 0
|
||||
logger.f = open(logger.baseName, logger.baseMode)
|
||||
|
||||
writeln(logger.f, LevelNames[level], " ", frmt % args)
|
||||
logger.curLine.inc
|
||||
|
||||
# --------
|
||||
|
||||
var
|
||||
level* = lvlAll ## global log filter
|
||||
handlers*: seq[PLogger] = @[] ## handlers with their own log levels
|
||||
|
||||
proc logLoop(level: TLevel, frmt: string, args: varargs[string, `$`]) =
|
||||
for logger in items(handlers):
|
||||
if level >= logger.levelThreshold:
|
||||
log(logger, level, frmt, args)
|
||||
|
||||
template log*(level: TLevel, frmt: string, args: varargs[string, `$`]) =
|
||||
## Logs a message to all registered handlers at the given level.
|
||||
bind logLoop
|
||||
bind `%`
|
||||
bind logging.Level
|
||||
|
||||
if level >= logging.Level:
|
||||
logLoop(level, frmt, args)
|
||||
|
||||
template debug*(frmt: string, args: varargs[string, `$`]) =
|
||||
## Logs a debug message to all registered handlers.
|
||||
log(lvlDebug, frmt, args)
|
||||
|
||||
template info*(frmt: string, args: varargs[string, `$`]) =
|
||||
## Logs an info message to all registered handlers.
|
||||
log(lvlInfo, frmt, args)
|
||||
|
||||
template warn*(frmt: string, args: varargs[string, `$`]) =
|
||||
## Logs a warning message to all registered handlers.
|
||||
log(lvlWarn, frmt, args)
|
||||
|
||||
template error*(frmt: string, args: varargs[string, `$`]) =
|
||||
## Logs an error message to all registered handlers.
|
||||
log(lvlError, frmt, args)
|
||||
|
||||
template fatal*(frmt: string, args: varargs[string, `$`]) =
|
||||
## Logs a fatal error message to all registered handlers.
|
||||
log(lvlFatal, frmt, args)
|
||||
|
||||
|
||||
# --------------
|
||||
|
||||
when isMainModule:
|
||||
var L = newConsoleLogger()
|
||||
var fL = newFileLogger("test.log", fmtStr = verboseFmtStr)
|
||||
var rL = newRollingFileLogger("rolling.log", fmtStr = verboseFmtStr)
|
||||
handlers.add(L)
|
||||
handlers.add(fL)
|
||||
handlers.add(rL)
|
||||
for i in 0 .. 25:
|
||||
info("hello" & $i, [])
|
||||
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ proc parseInt*(s: string, value: var int, validRange: TSlice[int]) {.
|
|||
try:
|
||||
discard parseutils.parseInt(s, x, 0)
|
||||
except EOverflow:
|
||||
nil
|
||||
discard
|
||||
if x in validRange: value = x
|
||||
|
||||
when isMainModule:
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ proc hexbyte*(hex: char): int =
|
|||
of '0'..'9': result = (ord(hex) - ord('0'))
|
||||
of 'a'..'f': result = (ord(hex) - ord('a') + 10)
|
||||
of 'A'..'F': result = (ord(hex) - ord('A') + 10)
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
proc parseOid*(str: cstring): TOid =
|
||||
## parses an OID.
|
||||
|
|
|
|||
|
|
@ -287,12 +287,18 @@ proc osLastError*(): TOSErrorCode =
|
|||
result = TOSErrorCode(errno)
|
||||
{.pop.}
|
||||
|
||||
proc unixToNativePath*(path: string): string {.
|
||||
proc unixToNativePath*(path: string, drive=""): string {.
|
||||
noSideEffect, rtl, extern: "nos$1".} =
|
||||
## Converts an UNIX-like path to a native one.
|
||||
##
|
||||
## On an UNIX system this does nothing. Else it converts
|
||||
## '/', '.', '..' to the appropriate things.
|
||||
##
|
||||
## On systems with a concept of "drives", `drive` is used to determine
|
||||
## which drive label to use during absolute path conversion.
|
||||
## `drive` defaults to the drive of the current working directory, and is
|
||||
## ignored on systems that do not have a concept of "drives".
|
||||
|
||||
when defined(unix):
|
||||
result = path
|
||||
else:
|
||||
|
|
@ -300,7 +306,10 @@ proc unixToNativePath*(path: string): string {.
|
|||
if path[0] == '/':
|
||||
# an absolute path
|
||||
when doslike:
|
||||
result = r"C:\"
|
||||
if drive != "":
|
||||
result = drive & ":" & DirSep
|
||||
else:
|
||||
result = $DirSep
|
||||
elif defined(macos):
|
||||
result = "" # must not start with ':'
|
||||
else:
|
||||
|
|
@ -387,6 +396,21 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} =
|
|||
var res: TStat
|
||||
return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
|
||||
|
||||
proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
|
||||
tags: [FReadDir].} =
|
||||
## Returns true iff the symlink `link` exists. Will return true
|
||||
## regardless of whether the link points to a directory or file.
|
||||
when defined(windows):
|
||||
when useWinUnicode:
|
||||
wrapUnary(a, getFileAttributesW, link)
|
||||
else:
|
||||
var a = getFileAttributesA(link)
|
||||
if a != -1'i32:
|
||||
result = (a and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32
|
||||
else:
|
||||
var res: TStat
|
||||
return lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode)
|
||||
|
||||
proc fileExists*(filename: string): bool {.inline.} =
|
||||
## Synonym for existsFile
|
||||
existsFile(filename)
|
||||
|
|
@ -1013,7 +1037,7 @@ proc execShellCmd*(command: string): int {.rtl, extern: "nos$1",
|
|||
## the process has finished. To execute a program without having a
|
||||
## shell involved, use the `execProcess` proc of the `osproc`
|
||||
## module.
|
||||
result = c_system(command)
|
||||
result = c_system(command) shr 8
|
||||
|
||||
# Environment handling cannot be put into RTL, because the ``envPairs``
|
||||
# iterator depends on ``environment``.
|
||||
|
|
@ -1054,9 +1078,9 @@ when defined(windows):
|
|||
while true:
|
||||
var eend = strEnd(e)
|
||||
add(environment, $e)
|
||||
e = cast[CString](cast[TAddress](eend)+1)
|
||||
e = cast[cstring](cast[TAddress](eend)+1)
|
||||
if eend[1] == '\0': break
|
||||
discard FreeEnvironmentStringsA(env)
|
||||
discard freeEnvironmentStringsA(env)
|
||||
envComputed = true
|
||||
|
||||
else:
|
||||
|
|
@ -1221,6 +1245,8 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {.
|
|||
if not skipFindData(f):
|
||||
if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32:
|
||||
k = pcDir
|
||||
if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
|
||||
k = succ(k)
|
||||
yield (k, dir / extractFilename(getFilename(f)))
|
||||
if findNextFile(h, f) == 0'i32: break
|
||||
findClose(h)
|
||||
|
|
@ -1245,6 +1271,10 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
|
|||
tags: [FReadDir].} =
|
||||
## walks over the directory `dir` and yields for each file in `dir`. The
|
||||
## full path for each file is returned.
|
||||
## **Warning**:
|
||||
## Modifying the directory structure while the iterator
|
||||
## is traversing may result in undefined behavior!
|
||||
##
|
||||
## Walking is recursive. `filter` controls the behaviour of the iterator:
|
||||
##
|
||||
## --------------------- ---------------------------------------------
|
||||
|
|
@ -1336,6 +1366,46 @@ proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
|
|||
copyDir(path, dest / noSource)
|
||||
else: discard
|
||||
|
||||
proc createSymlink*(src, dest: string) =
|
||||
## Create a symbolic link at `dest` which points to the item specified
|
||||
## by `src`. On most operating systems, will fail if a lonk
|
||||
##
|
||||
## **Warning**:
|
||||
## Some OS's (such as Microsoft Windows) restrict the creation
|
||||
## of symlinks to root users (administrators).
|
||||
when defined(Windows):
|
||||
let flag = dirExists(src).int32
|
||||
when useWinUnicode:
|
||||
var wSrc = newWideCString(src)
|
||||
var wDst = newWideCString(dest)
|
||||
if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0:
|
||||
osError(osLastError())
|
||||
else:
|
||||
if createSymbolicLinkA(dest, src, flag) == 0 or getLastError() != 0:
|
||||
osError(osLastError())
|
||||
else:
|
||||
if symlink(src, dest) != 0:
|
||||
osError(osLastError())
|
||||
|
||||
proc createHardlink*(src, dest: string) =
|
||||
## Create a hard link at `dest` which points to the item specified
|
||||
## by `src`.
|
||||
##
|
||||
## **Warning**: Most OS's restrict the creation of hard links to
|
||||
## root users (administrators) .
|
||||
when defined(Windows):
|
||||
when useWinUnicode:
|
||||
var wSrc = newWideCString(src)
|
||||
var wDst = newWideCString(dest)
|
||||
if createHardLinkW(wDst, wSrc, nil) == 0:
|
||||
osError(osLastError())
|
||||
else:
|
||||
if createHardLinkA(dest, src, nil) == 0:
|
||||
osError(osLastError())
|
||||
else:
|
||||
if link(src, dest) != 0:
|
||||
osError(osLastError())
|
||||
|
||||
proc parseCmdLine*(c: string): seq[string] {.
|
||||
noSideEffect, rtl, extern: "nos$1".} =
|
||||
## Splits a command line into several components;
|
||||
|
|
|
|||
|
|
@ -455,7 +455,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
ee, wwd, si, procInfo)
|
||||
else:
|
||||
success = winlean.createProcessA(nil,
|
||||
cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo)
|
||||
cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, si, procInfo)
|
||||
let lastError = osLastError()
|
||||
|
||||
if poParentStreams notin options:
|
||||
|
|
@ -534,7 +534,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
|
||||
else:
|
||||
var res = winlean.createProcessA(nil, command, nil, nil, 0,
|
||||
NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo)
|
||||
NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
|
||||
if res == 0:
|
||||
osError(osLastError())
|
||||
else:
|
||||
|
|
@ -791,7 +791,7 @@ elif not defined(useNimRtl):
|
|||
proc csystem(cmd: cstring): cint {.nodecl, importc: "system".}
|
||||
|
||||
proc execCmd(command: string): int =
|
||||
result = csystem(command)
|
||||
result = csystem(command) shr 8
|
||||
|
||||
proc createFdSet(fd: var TFdSet, s: seq[PProcess], m: var int) =
|
||||
FD_ZERO(fd)
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ proc readRow*(my: var TCsvParser, columns = 0): bool =
|
|||
of '\c': my.bufpos = handleCR(my, my.bufpos)
|
||||
of '\l': my.bufpos = handleLF(my, my.bufpos)
|
||||
else: break
|
||||
of '\0': nil
|
||||
of '\0': discard
|
||||
else: error(my, my.bufpos, my.sep & " expected")
|
||||
break
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ proc handleHexChar(c: var TSqlLexer, xi: var int) =
|
|||
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
|
||||
inc(c.bufpos)
|
||||
else:
|
||||
nil
|
||||
discard
|
||||
|
||||
proc handleOctChar(c: var TSqlLexer, xi: var int) =
|
||||
if c.buf[c.bufpos] in {'0'..'7'}:
|
||||
|
|
@ -373,7 +373,7 @@ proc getOperator(c: var TSqlLexer, tok: var TToken) =
|
|||
of '+':
|
||||
if not trailingPlusMinus and buf[pos+1] notin operators and
|
||||
tok.literal.len > 0: break
|
||||
of '*', '<', '>', '=': nil
|
||||
of '*', '<', '>', '=': discard
|
||||
else: break
|
||||
add(tok.literal, buf[pos])
|
||||
inc(pos)
|
||||
|
|
@ -1120,7 +1120,7 @@ proc rs(n: PSqlNode, s: var string, indent: int,
|
|||
proc ra(n: PSqlNode, s: var string, indent: int) =
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkNone: nil
|
||||
of nkNone: discard
|
||||
of nkIdent:
|
||||
if allCharsInSet(n.strVal, {'\33'..'\127'}):
|
||||
s.add(n.strVal)
|
||||
|
|
|
|||
|
|
@ -66,13 +66,15 @@ proc checkReply(smtp: var TSMTP, reply: string) =
|
|||
if not line.string.startswith(reply):
|
||||
quitExcpt(smtp, "Expected " & reply & " reply, got: " & line.string)
|
||||
|
||||
const compiledWithSsl = defined(ssl)
|
||||
|
||||
proc connect*(address: string, port = 25,
|
||||
ssl = false, debug = false): TSMTP =
|
||||
## Establishes a connection with a SMTP server.
|
||||
## May fail with EInvalidReply or with a socket error.
|
||||
result.sock = socket()
|
||||
if ssl:
|
||||
when defined(ssl):
|
||||
when compiledWithSsl:
|
||||
let ctx = newContext(verifyMode = CVerifyNone)
|
||||
ctx.wrapSocket(result.sock)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -311,7 +311,8 @@ when defined(ssl):
|
|||
newCTX.SSLCTXSetVerify(SSLVerifyNone, nil)
|
||||
if newCTX == nil:
|
||||
SSLError()
|
||||
|
||||
|
||||
discard newCTX.SSLCTXSetMode(SSL_MODE_AUTO_RETRY)
|
||||
newCTX.loadCertificates(certFile, keyFile)
|
||||
return PSSLContext(newCTX)
|
||||
|
||||
|
|
@ -1291,14 +1292,14 @@ proc readLine*(socket: TSocket, line: var TaintedString, timeout = -1) {.
|
|||
var c: char
|
||||
discard waitFor(socket, waited, timeout, 1, "readLine")
|
||||
var n = recv(socket, addr(c), 1)
|
||||
if n < 0: osError(osLastError())
|
||||
if n < 0: socket.socketError()
|
||||
elif n == 0: return
|
||||
if c == '\r':
|
||||
discard waitFor(socket, waited, timeout, 1, "readLine")
|
||||
n = peekChar(socket, c)
|
||||
if n > 0 and c == '\L':
|
||||
discard recv(socket, addr(c), 1)
|
||||
elif n <= 0: osError(osLastError())
|
||||
elif n <= 0: socket.socketError()
|
||||
addNLIfEmpty()
|
||||
return
|
||||
elif c == '\L':
|
||||
|
|
|
|||
|
|
@ -45,6 +45,16 @@ const
|
|||
NewLines* = {'\13', '\10'}
|
||||
## the set of characters a newline terminator can start with
|
||||
|
||||
AllChars* = {'\x00'..'\xFF'}
|
||||
## A set with all the possible characters. Not very useful by its own, you
|
||||
## can use it to create *inverted* sets to make the ``find()`` proc find
|
||||
## **invalid** characters in strings. Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## let invalid = AllChars - Digits
|
||||
## doAssert "01234".find(invalid) == -1
|
||||
## doAssert "01A34".find(invalid) == 2
|
||||
|
||||
proc toLower*(c: char): char {.noSideEffect, procvar,
|
||||
rtl, extern: "nsuToLowerChar".} =
|
||||
## Converts `c` into lower case. This works only for the letters A-Z.
|
||||
|
|
|
|||
|
|
@ -211,7 +211,9 @@ proc initInterval*(miliseconds, seconds, minutes, hours, days, months,
|
|||
result.months = months
|
||||
result.years = years
|
||||
|
||||
proc isLeapYear(year: int): bool =
|
||||
proc isLeapYear*(year: int): bool =
|
||||
## returns true if ``year`` is a leap year
|
||||
|
||||
if year mod 400 == 0:
|
||||
return true
|
||||
elif year mod 100 == 0:
|
||||
|
|
@ -221,7 +223,9 @@ proc isLeapYear(year: int): bool =
|
|||
else:
|
||||
return false
|
||||
|
||||
proc getDaysInMonth(month: TMonth, year: int): int =
|
||||
proc getDaysInMonth*(month: TMonth, year: int): int =
|
||||
## gets the amount of days in a ``month`` of a ``year``
|
||||
|
||||
# http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month
|
||||
case month
|
||||
of mFeb: result = if isLeapYear(year): 29 else: 28
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode =
|
|||
## &entity;
|
||||
errors.add(errorMsg(x, "unknown entity: " & x.entityName))
|
||||
next(x)
|
||||
of xmlEof: nil
|
||||
of xmlEof: discard
|
||||
|
||||
proc parseXml*(s: PStream, filename: string,
|
||||
errors: var seq[string]): PXmlNode =
|
||||
|
|
@ -110,7 +110,7 @@ proc parseXml*(s: PStream, filename: string,
|
|||
of xmlElementOpen, xmlElementStart:
|
||||
result = parse(x, errors)
|
||||
break
|
||||
of xmlComment, xmlWhitespace, xmlSpecial, xmlPI: nil # just skip it
|
||||
of xmlComment, xmlWhitespace, xmlSpecial, xmlPI: discard # just skip it
|
||||
of xmlError:
|
||||
errors.add(errorMsg(x))
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -2333,29 +2333,29 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
|
||||
elif defined(JS):
|
||||
# Stubs:
|
||||
proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = nil
|
||||
proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = discard
|
||||
|
||||
proc GC_disable() = nil
|
||||
proc GC_enable() = nil
|
||||
proc GC_fullCollect() = nil
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = nil
|
||||
proc GC_enableMarkAndSweep() = nil
|
||||
proc GC_disableMarkAndSweep() = nil
|
||||
proc GC_disable() = discard
|
||||
proc GC_enable() = discard
|
||||
proc GC_fullCollect() = discard
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
||||
proc GC_enableMarkAndSweep() = discard
|
||||
proc GC_disableMarkAndSweep() = discard
|
||||
proc GC_getStatistics(): string = return ""
|
||||
|
||||
proc getOccupiedMem(): int = return -1
|
||||
proc getFreeMem(): int = return -1
|
||||
proc getTotalMem(): int = return -1
|
||||
|
||||
proc dealloc(p: pointer) = nil
|
||||
proc alloc(size: int): pointer = nil
|
||||
proc alloc0(size: int): pointer = nil
|
||||
proc realloc(p: Pointer, newsize: int): pointer = nil
|
||||
proc dealloc(p: pointer) = discard
|
||||
proc alloc(size: int): pointer = discard
|
||||
proc alloc0(size: int): pointer = discard
|
||||
proc realloc(p: Pointer, newsize: int): pointer = discard
|
||||
|
||||
proc allocShared(size: int): pointer = nil
|
||||
proc allocShared0(size: int): pointer = nil
|
||||
proc deallocShared(p: pointer) = nil
|
||||
proc reallocShared(p: pointer, newsize: int): pointer = nil
|
||||
proc allocShared(size: int): pointer = discard
|
||||
proc allocShared0(size: int): pointer = discard
|
||||
proc deallocShared(p: pointer) = discard
|
||||
proc reallocShared(p: pointer, newsize: int): pointer = discard
|
||||
|
||||
when defined(JS):
|
||||
include "system/jssys"
|
||||
|
|
@ -2490,11 +2490,11 @@ proc staticRead*(filename: string): string {.magic: "Slurp".}
|
|||
## ``slurp`` is an alias for ``staticRead``.
|
||||
|
||||
proc gorge*(command: string, input = ""): string {.
|
||||
magic: "StaticExec".} = nil
|
||||
magic: "StaticExec".} = discard
|
||||
## This is an alias for ``staticExec``.
|
||||
|
||||
proc staticExec*(command: string, input = ""): string {.
|
||||
magic: "StaticExec".} = nil
|
||||
magic: "StaticExec".} = discard
|
||||
## Executes an external process at compile-time.
|
||||
## if `input` is not an empty string, it will be passed as a standard input
|
||||
## to the executed program.
|
||||
|
|
@ -2561,7 +2561,7 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[
|
|||
## $pos.line, astToStr(code)]
|
||||
## assert false, "A test expecting failure succeeded?"
|
||||
## except exception:
|
||||
## nil
|
||||
## discard
|
||||
##
|
||||
## proc tester(pos: int): int =
|
||||
## let
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ else:
|
|||
proc MessageBoxA(hWnd: cint, lpText, lpCaption: cstring, uType: int): int32 {.
|
||||
header: "<windows.h>", nodecl.}
|
||||
|
||||
proc writeToStdErr(msg: CString) =
|
||||
proc writeToStdErr(msg: cstring) =
|
||||
discard MessageBoxA(0, msg, nil, 0)
|
||||
|
||||
proc showErrorMessage(data: cstring) =
|
||||
|
|
|
|||
|
|
@ -802,7 +802,7 @@ when defined(sparc): # For SPARC architecture.
|
|||
# Addresses decrease as the stack grows.
|
||||
while sp <= max:
|
||||
gcMark(gch, sp[])
|
||||
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
|
||||
sp = cast[PPointer](cast[TAddress](sp) +% sizeof(pointer))
|
||||
|
||||
elif defined(ELATE):
|
||||
{.error: "stack marking code is to be written for this architecture".}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
# (c) Copyright 2014 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -59,11 +59,11 @@ var
|
|||
gch {.rtlThreadVar.}: TGcHeap
|
||||
|
||||
when not defined(useNimRtl):
|
||||
InstantiateForRegion(gch.region)
|
||||
instantiateForRegion(gch.region)
|
||||
|
||||
template acquire(gch: TGcHeap) =
|
||||
when hasThreadSupport and hasSharedHeap:
|
||||
AcquireSys(HeapLock)
|
||||
acquireSys(HeapLock)
|
||||
|
||||
template release(gch: TGcHeap) =
|
||||
when hasThreadSupport and hasSharedHeap:
|
||||
|
|
@ -90,7 +90,7 @@ proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
|
|||
# used for code generation concerning debugging
|
||||
result = usrToCell(c).typ
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.inline.} =
|
||||
proc unsureAsgnRef(dest: PPointer, src: pointer) {.inline.} =
|
||||
dest[] = src
|
||||
|
||||
proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
|
||||
|
|
@ -114,10 +114,10 @@ when BitsPerPage mod (sizeof(int)*8) != 0:
|
|||
|
||||
# forward declarations:
|
||||
proc collectCT(gch: var TGcHeap)
|
||||
proc IsOnStack*(p: pointer): bool {.noinline.}
|
||||
proc isOnStack*(p: pointer): bool {.noinline.}
|
||||
proc forAllChildren(cell: PCell, op: TWalkOp)
|
||||
proc doOperation(p: pointer, op: TWalkOp)
|
||||
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp)
|
||||
proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp)
|
||||
# we need the prototype here for debugging purposes
|
||||
|
||||
proc prepareDealloc(cell: PCell) =
|
||||
|
|
@ -162,19 +162,19 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
|
|||
if m != nil: forAllSlotsAux(dest, m, op)
|
||||
of nkNone: sysAssert(false, "forAllSlotsAux")
|
||||
|
||||
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
|
||||
proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
|
||||
var d = cast[TAddress](dest)
|
||||
if dest == nil: return # nothing to do
|
||||
if ntfNoRefs notin mt.flags:
|
||||
case mt.Kind
|
||||
case mt.kind
|
||||
of tyRef, tyString, tySequence: # leaf:
|
||||
doOperation(cast[ppointer](d)[], op)
|
||||
doOperation(cast[PPointer](d)[], op)
|
||||
of tyObject, tyTuple:
|
||||
forAllSlotsAux(dest, mt.node, op)
|
||||
of tyArray, tyArrayConstr, tyOpenArray:
|
||||
for i in 0..(mt.size div mt.base.size)-1:
|
||||
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
proc forAllChildren(cell: PCell, op: TWalkOp) =
|
||||
gcAssert(cell != nil, "forAllChildren: 1")
|
||||
|
|
@ -184,7 +184,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
|
|||
if marker != nil:
|
||||
marker(cellToUsr(cell), op.int)
|
||||
else:
|
||||
case cell.typ.Kind
|
||||
case cell.typ.kind
|
||||
of tyRef: # common case
|
||||
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
|
||||
of tySequence:
|
||||
|
|
@ -194,7 +194,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
|
|||
for i in 0..s.len-1:
|
||||
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
|
||||
GenericSeqSize), cell.typ.base, op)
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
|
||||
# generates a new object and sets its reference counter to 0
|
||||
|
|
@ -466,7 +466,7 @@ else:
|
|||
sp = sp +% sizeof(pointer)*8
|
||||
# last few entries:
|
||||
while sp <=% max:
|
||||
gcMark(gch, cast[ppointer](sp)[])
|
||||
gcMark(gch, cast[PPointer](sp)[])
|
||||
sp = sp +% sizeof(pointer)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
|
@ -505,7 +505,7 @@ when not defined(useNimRtl):
|
|||
else:
|
||||
dec(gch.recGcLock)
|
||||
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = nil
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
||||
|
||||
proc GC_enableMarkAndSweep() =
|
||||
gch.cycleThreshold = InitialThreshold
|
||||
|
|
|
|||
|
|
@ -195,16 +195,31 @@ else:
|
|||
importc: "GetCurrentDirectoryA", dynlib: "kernel32", stdcall.}
|
||||
proc setCurrentDirectoryA*(lpPathName: cstring): int32 {.
|
||||
importc: "SetCurrentDirectoryA", dynlib: "kernel32", stdcall.}
|
||||
proc createDirectoryA*(pathName: cstring, security: Pointer=nil): int32 {.
|
||||
proc createDirectoryA*(pathName: cstring, security: pointer=nil): int32 {.
|
||||
importc: "CreateDirectoryA", dynlib: "kernel32", stdcall.}
|
||||
proc removeDirectoryA*(lpPathName: cstring): int32 {.
|
||||
importc: "RemoveDirectoryA", dynlib: "kernel32", stdcall.}
|
||||
proc setEnvironmentVariableA*(lpName, lpValue: cstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableA".}
|
||||
|
||||
proc getModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {.
|
||||
proc getModuleFileNameA*(handle: THandle, buf: cstring, size: int32): int32 {.
|
||||
importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.}
|
||||
|
||||
|
||||
when useWinUnicode:
|
||||
proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: WideCString,
|
||||
flags: DWORD): int32 {.
|
||||
importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall.}
|
||||
proc createHardLinkW*(lpFileName, lpExistingFileName: WideCString,
|
||||
security: pointer=nil): int32 {.
|
||||
importc:"CreateHardLinkW", dynlib: "kernel32", stdcall.}
|
||||
else:
|
||||
proc createSymbolicLinkA*(lpSymlinkFileName, lpTargetFileName: cstring,
|
||||
flags: DWORD): int32 {.
|
||||
importc:"CreateSymbolicLinkA", dynlib: "kernel32", stdcall.}
|
||||
proc createHardLinkA*(lpFileName, lpExistingFileName: cstring,
|
||||
security: pointer=nil): int32 {.
|
||||
importc:"CreateHardLinkA", dynlib: "kernel32", stdcall.}
|
||||
|
||||
const
|
||||
FILE_ATTRIBUTE_ARCHIVE* = 32'i32
|
||||
FILE_ATTRIBUTE_COMPRESSED* = 2048'i32
|
||||
|
|
@ -212,6 +227,7 @@ const
|
|||
FILE_ATTRIBUTE_DIRECTORY* = 16'i32
|
||||
FILE_ATTRIBUTE_HIDDEN* = 2'i32
|
||||
FILE_ATTRIBUTE_READONLY* = 1'i32
|
||||
FILE_ATTRIBUTE_REPARSE_POINT* = 1024'i32
|
||||
FILE_ATTRIBUTE_SYSTEM* = 4'i32
|
||||
FILE_ATTRIBUTE_TEMPORARY* = 256'i32
|
||||
|
||||
|
|
@ -284,7 +300,7 @@ else:
|
|||
dwFileAttributes: int32): WINBOOL {.
|
||||
stdcall, dynlib: "kernel32", importc: "SetFileAttributesA".}
|
||||
|
||||
proc copyFileA*(lpExistingFileName, lpNewFileName: CString,
|
||||
proc copyFileA*(lpExistingFileName, lpNewFileName: cstring,
|
||||
bFailIfExists: cint): cint {.
|
||||
importc: "CopyFileA", stdcall, dynlib: "kernel32".}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,11 +109,12 @@ type
|
|||
cur*: cstring
|
||||
dataSize*: cint
|
||||
finished*: TBsonBool
|
||||
stack*: array[0..32 - 1, cint]
|
||||
ownsData*: TBsonBool
|
||||
err*: cint
|
||||
stackSize*: cint
|
||||
stackPos*: cint
|
||||
err*: cint ## Bitfield representing errors or warnings on this buffer
|
||||
errstr*: cstring ## A string representation of the most recent error
|
||||
## or warning.
|
||||
stackPtr*: ptr csize
|
||||
stack*: array[0..32 - 1, csize]
|
||||
|
||||
TDate* = int64
|
||||
|
||||
|
|
@ -141,6 +142,7 @@ proc print*(TBson: cstring, depth: cint) {.stdcall,
|
|||
importc: "bson_print_raw", dynlib: bsondll.}
|
||||
## Print a string representation of a BSON object up to `depth`.
|
||||
|
||||
|
||||
proc data*(b: var TBson): cstring{.stdcall, importc: "bson_data",
|
||||
dynlib: bsondll.}
|
||||
## Return a pointer to the raw buffer stored by this bson object.
|
||||
|
|
@ -590,19 +592,30 @@ type
|
|||
hosts*: ptr THostPort ## List of host/ports given by the replica set
|
||||
name*: cstring ## Name of the replica set.
|
||||
primary_connected*: TBsonBool ## Primary node connection status.
|
||||
|
||||
TWriteConcern*{.pure, final.} = object ## mongo_write_concern
|
||||
w*: cint
|
||||
wtimeout*: cint
|
||||
j*: cint
|
||||
fsync*: cint
|
||||
mode*: cstring
|
||||
cmd*: TBSon
|
||||
|
||||
TMongo*{.pure, final.} = object ## mongo
|
||||
primary*: ptr THostPort ## Primary connection info.
|
||||
replset*: ptr TReplSet ## replset object if connected to a replica set.
|
||||
sock*: cint ## Socket file descriptor.
|
||||
flags*: cint ## Flags on this connection object.
|
||||
conn_timeout_ms*: cint ## Connection timeout in milliseconds.
|
||||
op_timeout_ms*: cint ## Read and write timeout in milliseconds.
|
||||
connected*: TBsonBool ## Connection status.
|
||||
err*: TError ## Most recent driver error code.
|
||||
errstr*: array[0..128 - 1, char] ## String version of most recent driver error code.
|
||||
lasterrcode*: cint ## getlasterror code given by the server on error.
|
||||
lasterrstr*: cstring ## getlasterror string generated by server.
|
||||
primary*: ptr THostPort ## Primary connection info.
|
||||
replset*: ptr TReplSet ## replset object if connected to a replica set.
|
||||
sock*: cint ## Socket file descriptor.
|
||||
flags*: cint ## Flags on this connection object.
|
||||
conn_timeout_ms*: cint ## Connection timeout in milliseconds.
|
||||
op_timeout_ms*: cint ## Read and write timeout in milliseconds.
|
||||
max_bson_size*: cint ## Largest BSON object allowed on this connection.
|
||||
connected*: TBsonBool ## Connection status.
|
||||
write_concern*: TWriteConcern ## The default write concern.
|
||||
err*: TError ## Most recent driver error code.
|
||||
errcode*: cint ## Most recent errno or WSAGetLastError().
|
||||
errstr*: array[0..128 - 1, char] ## String version of most recent driver error code.
|
||||
lasterrcode*: cint ## getlasterror code given by the server on error.
|
||||
lasterrstr*: array[0..128 - 1, char] ## getlasterror string generated by server.
|
||||
|
||||
TCursor*{.pure, final.} = object ## cursor
|
||||
reply*: ptr TReply ## reply is owned by cursor
|
||||
|
|
@ -654,7 +667,11 @@ proc init*(conn: var TMongo){.stdcall, importc: "mongo_init", dynlib: mongodll.}
|
|||
|
||||
proc connect*(conn: var TMongo, host: cstring = defaultHost,
|
||||
port: cint = defaultPort): cint {.stdcall,
|
||||
importc: "mongo_connect", dynlib: mongodll.}
|
||||
importc: "mongo_connect", dynlib: mongodll, deprecated.}
|
||||
## Connect to a single MongoDB server.
|
||||
proc client*(conn: var TMongo, host: cstring = defaultHost,
|
||||
port: cint = defaultPort): cint {.stdcall,
|
||||
importc: "mongo_client", dynlib: mongodll.}
|
||||
## Connect to a single MongoDB server.
|
||||
|
||||
proc replsetInit*(conn: var TMongo, name: cstring){.stdcall,
|
||||
|
|
@ -714,7 +731,8 @@ proc destroy*(conn: var TMongo){.stdcall, importc: "mongo_destroy",
|
|||
## You must always call this function when finished with the connection
|
||||
## object.
|
||||
|
||||
proc insert*(conn: var TMongo, ns: cstring, data: var TBson): cint{.stdcall,
|
||||
proc insert*(conn: var TMongo, ns: cstring, data: var TBson,
|
||||
custom_write_concern: ptr TWriteConcern): cint{.stdcall,
|
||||
importc: "mongo_insert", dynlib: mongodll, discardable.}
|
||||
## Insert a BSON document into a MongoDB server. This function
|
||||
## will fail if the supplied BSON struct is not UTF-8 or if
|
||||
|
|
|
|||
|
|
@ -268,14 +268,22 @@ proc OpenSSL_add_all_algorithms*(){.cdecl, dynlib: DLLUtilName, importc: "OPENSS
|
|||
|
||||
proc OPENSSL_config*(configName: cstring){.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, dynlib: DLLSSLName, importc.}
|
||||
when not defined(windows):
|
||||
proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl,
|
||||
dynlib: DLLSSLName, importc.}
|
||||
|
||||
proc CRYPTO_malloc_init*() =
|
||||
when not defined(windows):
|
||||
CRYPTO_set_mem_functions(alloc, realloc, dealloc)
|
||||
|
||||
when True:
|
||||
nil
|
||||
proc SSL_CTX_ctrl*(ctx: PSSL_CTX, cmd: cInt, larg: int, parg: pointer): int{.
|
||||
cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
proc SSLCTXSetMode*(ctx: PSSL_CTX, mode: int): int =
|
||||
result = SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, mode, nil)
|
||||
|
||||
when true:
|
||||
discard
|
||||
else:
|
||||
proc SslCtxSetCipherList*(arg0: PSSL_CTX, str: cstring): cInt{.cdecl,
|
||||
dynlib: DLLSSLName, importc.}
|
||||
|
|
@ -288,7 +296,6 @@ else:
|
|||
proc SslCTXCtrl*(ctx: PSSL_CTX, cmd: cInt, larg: int, parg: Pointer): int{.
|
||||
cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
proc SSLCTXSetMode*(ctx: PSSL_CTX, mode: int): int
|
||||
proc SSLSetMode*(s: PSSL, mode: int): int
|
||||
proc SSLCTXGetMode*(ctx: PSSL_CTX): int
|
||||
proc SSLGetMode*(s: PSSL): int
|
||||
|
|
@ -417,15 +424,12 @@ else:
|
|||
enc: cInt){.cdecl, dynlib: DLLUtilName, importc.}
|
||||
# implementation
|
||||
|
||||
proc SSLCTXSetMode(ctx: PSSL_CTX, mode: int): int =
|
||||
Result = SslCTXCtrl(ctx, SSL_CTRL_MODE, mode, nil)
|
||||
|
||||
proc SSLSetMode(s: PSSL, mode: int): int =
|
||||
Result = SSLctrl(s, SSL_CTRL_MODE, mode, nil)
|
||||
result = SSLctrl(s, SSL_CTRL_MODE, mode, nil)
|
||||
|
||||
proc SSLCTXGetMode(ctx: PSSL_CTX): int =
|
||||
Result = SSLCTXctrl(ctx, SSL_CTRL_MODE, 0, nil)
|
||||
result = SSLCTXctrl(ctx, SSL_CTRL_MODE, 0, nil)
|
||||
|
||||
proc SSLGetMode(s: PSSL): int =
|
||||
Result = SSLctrl(s, SSL_CTRL_MODE, 0, nil)
|
||||
result = SSLctrl(s, SSL_CTRL_MODE, 0, nil)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue