diff options
author | Araq <rumpf_a@web.de> | 2012-08-02 23:16:17 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-08-02 23:16:17 +0200 |
commit | e2359aba44e90e22bce5069a91a53758a87dfa06 (patch) | |
tree | e69839103ed2ba72657247761054fa080795ed0c | |
parent | 7d6500f1de19379cdfc9c6f8a05d43781cf32291 (diff) | |
parent | 0aced03c055f07a67a90ba3fa26f108cecb66cbb (diff) | |
download | Nim-e2359aba44e90e22bce5069a91a53758a87dfa06.tar.gz |
Merge branch 'master' of github.com:Araq/Nimrod
-rwxr-xr-x | compiler/cgen.nim | 3 | ||||
-rwxr-xr-x | compiler/pragmas.nim | 22 | ||||
-rw-r--r-- | devel/logging.nim | 149 | ||||
-rwxr-xr-x | lib/system.nim | 1 | ||||
-rwxr-xr-x | lib/system/threads.nim | 1 |
5 files changed, 123 insertions, 53 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 8d027b11c..06018fa99 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -861,7 +861,8 @@ proc genMainProc(m: BModule) = CommonMainBody & "}$n" WinCDllMain = "BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $n" & - " LPVOID lpvReserved) {$n" & "\tNimMain();$n" & + " LPVOID lpvReserved) {$n" & + "\tif(fwdreason == DLL_PROCESS_ATTACH) NimMain();$n" & "\treturn 1;$n" & "}$n" PosixNimDllMain = WinNimDllMain PosixCDllMain = diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 28f77d1b9..fd637f4c7 100755 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -212,16 +212,22 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode = result = newEmptyStrNode(n) proc processDynLib(c: PContext, n: PNode, sym: PSym) = - if (sym == nil) or (sym.kind == skModule): + if (sym == nil) or (sym.kind == skModule): POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic, expectDynlibNode(c, n)) - elif n.kind == nkExprColonExpr: - var lib = getLib(c, libDynamic, expectDynlibNode(c, n)) - addToLib(lib, sym) - incl(sym.loc.flags, lfDynamicLib) - else: - incl(sym.loc.flags, lfExportLib) - + else: + if n.kind == nkExprColonExpr: + var lib = getLib(c, libDynamic, expectDynlibNode(c, n)) + addToLib(lib, sym) + incl(sym.loc.flags, lfDynamicLib) + else: + incl(sym.loc.flags, lfExportLib) + # since we'll be loading the dynlib symbols dynamically, we must use + # a calling convention that doesn't introduce custom name mangling + # cdecl is the default - the use can override this explicitly + if sym.typ.callConv == ccDefault: + sym.typ.callConv = ccCDecl + proc processNote(c: PContext, n: PNode) = if (n.kind == nkExprColonExpr) and (sonsLen(n) == 2) and (n.sons[0].kind == nkBracketExpr) and diff --git a/devel/logging.nim b/devel/logging.nim index 7ae4d7eee..57b34ce5e 100644 --- a/devel/logging.nim +++ b/devel/logging.nim @@ -18,6 +18,8 @@ ## ## +import strutils, os, times + type TLevel* = enum ## logging level lvlAll, ## all levels active @@ -25,46 +27,39 @@ type 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 + lvlFatal, ## fatal level (and any above) active + lvlNone const LevelNames*: array [TLevel, string] = [ - "DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" + "DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE" ] + defaultFmtStr = "" ## default string between log level and message per logger + verboseFmtStr = "$date $time " + type TLogger* = object of TObject ## 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. + TConsoleLogger* = object of TLogger ## logger that writes the messages to the ## console TFileLogger* = object of TLogger ## logger that writes the messages to a file f: TFile - + + # TODO: implement rolling log, will produce filename.1, filename.2 etc. TRollingFileLogger* = object of TFileLogger ## logger that writes the ## message to a file - maxlines: int # maximum number of lines - lines: seq[string] - -method log*(L: ref TLogger, level: TLevel, - frmt: string, args: openArray[string]) = - ## override this method in custom loggers. Default implementation does - ## nothing. - nil - -method log*(L: ref TConsoleLogger, level: TLevel, - frmt: string, args: openArray[string]) = - Writeln(stdout, LevelNames[level], " ", frmt % args) - -method log*(L: ref TFileLogger, level: TLevel, - frmt: string, args: openArray[string]) = - Writeln(L.f, LevelNames[level], " ", frmt % args) + maxLines: int # maximum number of lines + curLine : int + baseName: string # initial filename + logFiles: int # how many log files already created, e.g. basename.1, basename.2... + + -proc defaultFilename*(): string = - ## returns the default filename for a logger - var (path, name, ext) = splitFile(getAppFilename()) - result = changeFileExt(path / name & "_" & getDateStr(), "log") proc substituteLog*(frmt: string): string = ## converts $date to the current date @@ -90,56 +85,126 @@ proc substituteLog*(frmt: string): string = of "app": result.add(app) of "appdir": result.add(app.splitFile.dir) of "appname": result.add(app.splitFile.name) + + + +method log*(L: ref TLogger, level: TLevel, + frmt: string, args: openArray[string]) = + ## override this method in custom loggers. Default implementation does + ## nothing. + nil + +method log*(L: ref TConsoleLogger, level: TLevel, + frmt: string, args: openArray[string]) = + Writeln(stdout, LevelNames[level], " ", substituteLog(L.fmtStr), frmt % args) + +method log*(L: ref TFileLogger, level: TLevel, + frmt: string, args: openArray[string]) = + Writeln(L.f, LevelNames[level], " ", substituteLog(L.fmtStr), frmt % args) + +proc defaultFilename*(): string = + ## returns the default filename for a logger + var (path, name, ext) = splitFile(getAppFilename()) + result = changeFileExt(path / name & "_" & getDateStr(), "log") + + +proc newConsoleLogger*(levelThreshold = lvlAll) : ref TConsoleLogger = + new result + result.fmtStr = defaultFmtStr + result.levelThreshold = levelThreshold + proc newFileLogger*(filename = defaultFilename(), mode: TFileMode = fmAppend, - levelThreshold = lvlNone): ref TFileLogger = + levelThreshold = lvlAll): ref TFileLogger = new(result) result.levelThreshold = levelThreshold result.f = open(filename, mode) + result.fmtStr = defaultFmtStr + +# ------ + +proc readLogLines(logger : ref TRollingFileLogger) = nil + #f.readLine # TODO read all lines, update curLine + proc newRollingFileLogger*(filename = defaultFilename(), - mode: TFileMode = fmAppend, - levelThreshold = lvlNone, - maxLines = 1000): ref TFileLogger = + mode: TFileMode = fmReadWrite, + levelThreshold = lvlAll, + maxLines = 1000): ref TRollingFileLogger = new(result) result.levelThreshold = levelThreshold + result.fmtStr = defaultFmtStr result.maxLines = maxLines result.f = open(filename, mode) + result.curLine = 0 + + # TODO count all number files + # count lines in existing filename file + # if >= maxLines then rename to next numbered file and create new file + + #if mode in {fmReadWrite, fmReadWriteExisting}: + # readLogLines(result) + + + +method log*(L: ref TRollingFileLogger, level: TLevel, + frmt: string, args: openArray[string]) = + # TODO + # if more than maxlines, then set cursor to zero + + Writeln(L.f, LevelNames[level], " ", frmt % args) + +# -------- var - level* = lvlNone - handlers*: seq[ref TLogger] = @[] + level* = lvlAll ## global log filter + handlers*: seq[ref TLogger] = @[] ## handlers with their own log levels -proc logLoop(level: TLevel, msg: string) = +proc logLoop(level: TLevel, frmt: string, args: openarray[string]) = for logger in items(handlers): if level >= logger.levelThreshold: - log(logger, level, msg) + log(logger, level, frmt, args) -template log*(level: TLevel, msg: string) = +template log*(level: TLevel, frmt: string, args: openarray[string]) = ## logs a message of the given level bind logLoop + bind `%` + bind logging.Level + if level >= logging.Level: logLoop(level, frmt, args) -template debug*(msg: string) = +template debug*(frmt: string, args: openarray[string]) = ## logs a debug message - log(lvlDebug, msg) + log(lvlDebug, frmt, args) -template info*(msg: string) = +template info*(frmt: string, args: openarray[string]) = ## logs an info message - log(lvlInfo, msg) + log(lvlInfo, frmt, args) -template warn*(msg: string) = +template warn*(frmt: string, args: openarray[string]) = ## logs a warning message - log(lvlWarn, msg) + log(lvlWarn, frmt, args) -template error*(msg: string) = +template error*(frmt: string, args: openarray[string]) = ## logs an error message - log(lvlError, msg) + log(lvlError, frmt, args) -template fatal*(msg: string) = +template fatal*(frmt: string, args: openarray[string]) = ## logs a fatal error message - log(lvlFatal, msg) + log(lvlFatal, frmt, args) + + +# -------------- + +when isMainModule: + var L = newConsoleLogger() + var fL = newFileLogger("test.log") + fL.fmtStr = verboseFmtStr + handlers.add(L) + handlers.add(fL) + info("hello", []) + diff --git a/lib/system.nim b/lib/system.nim index 84a3034f0..64a70b61b 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -1935,7 +1935,6 @@ when not defined(EcmaScript) and not defined(NimrodVM): include "system/syslocks" include "system/threads" elif not defined(nogc): - initStackBottom() initGC() proc setControlCHook*(hook: proc () {.noconv.}) diff --git a/lib/system/threads.nim b/lib/system/threads.nim index 7a60404ac..6b1fd2178 100755 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -203,7 +203,6 @@ when not defined(useNimRtl): when not useStackMaskHack: var mainThread: TGcThread ThreadVarSetValue(globalsSlot, addr(mainThread)) - initStackBottom() initGC() when emulatedThreadVars: |