summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-08-02 23:16:17 +0200
committerAraq <rumpf_a@web.de>2012-08-02 23:16:17 +0200
commite2359aba44e90e22bce5069a91a53758a87dfa06 (patch)
treee69839103ed2ba72657247761054fa080795ed0c
parent7d6500f1de19379cdfc9c6f8a05d43781cf32291 (diff)
parent0aced03c055f07a67a90ba3fa26f108cecb66cbb (diff)
downloadNim-e2359aba44e90e22bce5069a91a53758a87dfa06.tar.gz
Merge branch 'master' of github.com:Araq/Nimrod
-rwxr-xr-xcompiler/cgen.nim3
-rwxr-xr-xcompiler/pragmas.nim22
-rw-r--r--devel/logging.nim149
-rwxr-xr-xlib/system.nim1
-rwxr-xr-xlib/system/threads.nim1
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: