summary refs log tree commit diff stats
path: root/lib/pure/os.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/os.nim')
-rw-r--r--lib/pure/os.nim325
1 files changed, 168 insertions, 157 deletions
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 71089494f..3a6930654 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -1,6 +1,6 @@
 #
 #
-#            Nimrod's Runtime Library
+#            Nim's Runtime Library
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -29,18 +29,23 @@ else:
 include "system/ansi_c"
 
 type
-  FReadEnv* = object of FReadIO   ## effect that denotes a read
-                                  ## from an environment variable
-  FWriteEnv* = object of FWriteIO ## effect that denotes a write
-                                  ## to an environment variable
-
-  FReadDir* = object of FReadIO   ## effect that denotes a write operation to
-                                  ## the directory structure
-  FWriteDir* = object of FWriteIO ## effect that denotes a write operation to
-                                  ## the directory structure
-
-  TOSErrorCode* = distinct int32 ## Specifies an OS Error Code.
-
+  ReadEnvEffect* = object of ReadIOEffect   ## effect that denotes a read
+                                            ## from an environment variable
+  WriteEnvEffect* = object of WriteIOEffect ## effect that denotes a write
+                                            ## to an environment variable
+
+  ReadDirEffect* = object of ReadIOEffect   ## effect that denotes a write
+                                            ## operation to the directory structure
+  WriteDirEffect* = object of WriteIOEffect ## effect that denotes a write operation to
+                                            ## the directory structure
+
+  OSErrorCode* = distinct int32 ## Specifies an OS Error Code.
+
+{.deprecated: [FReadEnv: ReadEnvEffect, FWriteEnv: WriteEnvEffect, 
+    FReadDir: ReadDirEffect,
+    FWriteDir: WriteDirEffect,
+    TOSErrorCode: OSErrorCode
+].}
 const
   doslike = defined(windows) or defined(OS2) or defined(DOS)
     # DOS-like filesystem
@@ -75,7 +80,7 @@ when defined(Nimdoc): # only for proper documentation:
       ## search patch components (as in PATH), such as ':' for POSIX or ';' for
       ## Windows.
 
-    FileSystemCaseSensitive* = True
+    FileSystemCaseSensitive* = true
       ## True if the file system is case sensitive, false otherwise. Used by
       ## `cmpPaths` to compare filenames properly.
 
@@ -182,7 +187,7 @@ proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
   ## On Windows ``GetLastError`` is checked before ``errno``.
   ## Returns "" if no error occured.
   ##
-  ## **Deprecated since version 0.9.4**: use the other ``OSErrorMsg`` proc.
+  ## **Deprecated since version 0.9.4**: use the other ``osErrorMsg`` proc.
 
   result = ""
   when defined(Windows):
@@ -204,7 +209,8 @@ proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
     result = $os.strerror(errno)
 
 {.push warning[deprecated]: off.}
-proc osError*(msg: string = "") {.noinline, rtl, extern: "nos$1", deprecated.} =
+proc raiseOSError*(msg: string = "") {.noinline, rtl, extern: "nos$1",
+                                       deprecated.} =
   ## raises an EOS exception with the given message ``msg``.
   ## If ``msg == ""``, the operating system's error flag
   ## (``errno``) is converted to a readable error message. On Windows
@@ -214,15 +220,18 @@ proc osError*(msg: string = "") {.noinline, rtl, extern: "nos$1", deprecated.} =
   ## **Deprecated since version 0.9.4**: use the other ``OSError`` proc.
   if len(msg) == 0:
     var m = osErrorMsg()
-    raise newException(EOS, if m.len > 0: m else: "unknown OS error")
+    raise newException(OSError, if m.len > 0: m else: "unknown OS error")
   else:
-    raise newException(EOS, msg)
+    raise newException(OSError, msg)
 {.pop.}
 
-proc `==`*(err1, err2: TOSErrorCode): bool {.borrow.}
-proc `$`*(err: TOSErrorCode): string {.borrow.}
+when not defined(nimfix):
+  {.deprecated: [osError: raiseOSError].}
 
-proc osErrorMsg*(errorCode: TOSErrorCode): string =
+proc `==`*(err1, err2: OSErrorCode): bool {.borrow.}
+proc `$`*(err: OSErrorCode): string {.borrow.}
+
+proc osErrorMsg*(errorCode: OSErrorCode): string =
   ## Converts an OS error code into a human readable string.
   ##
   ## The error code can be retrieved using the ``OSLastError`` proc.
@@ -235,7 +244,7 @@ proc osErrorMsg*(errorCode: TOSErrorCode): string =
   ## message.
   result = ""
   when defined(Windows):
-    if errorCode != TOSErrorCode(0'i32):
+    if errorCode != OSErrorCode(0'i32):
       when useWinUnicode:
         var msgbuf: WideCString
         if formatMessageW(0x00000100 or 0x00001000 or 0x00000200,
@@ -249,10 +258,10 @@ proc osErrorMsg*(errorCode: TOSErrorCode): string =
           result = $msgbuf
           if msgbuf != nil: localFree(msgbuf)
   else:
-    if errorCode != TOSErrorCode(0'i32):
+    if errorCode != OSErrorCode(0'i32):
       result = $os.strerror(errorCode.int32)
 
-proc osError*(errorCode: TOSErrorCode) =
+proc raiseOSError*(errorCode: OSErrorCode) =
   ## Raises an ``EOS`` exception. The ``errorCode`` will determine the
   ## message, ``OSErrorMsg`` will be used to get this message.
   ##
@@ -260,7 +269,7 @@ proc osError*(errorCode: TOSErrorCode) =
   ##
   ## If the error code is ``0`` or an error message could not be retrieved,
   ## the message ``unknown OS error`` will be used.
-  var e: ref EOS; new(e)
+  var e: ref OSError; new(e)
   e.errorCode = errorCode.int32
   e.msg = osErrorMsg(errorCode)
   if e.msg == "":
@@ -268,7 +277,7 @@ proc osError*(errorCode: TOSErrorCode) =
   raise e
 
 {.push stackTrace:off.}
-proc osLastError*(): TOSErrorCode =
+proc osLastError*(): OSErrorCode =
   ## Retrieves the last operating system error code.
   ##
   ## This procedure is useful in the event when an OS call fails. In that case
@@ -283,9 +292,9 @@ proc osLastError*(): TOSErrorCode =
   ## immediately after an OS call fails. On POSIX systems this is not a problem.
 
   when defined(windows):
-    result = TOSErrorCode(getLastError())
+    result = OSErrorCode(getLastError())
   else:
-    result = TOSErrorCode(errno)
+    result = OSErrorCode(errno)
 {.pop.}
 
 proc unixToNativePath*(path: string, drive=""): string {.
@@ -371,7 +380,7 @@ when defined(windows):
              f.cFileName[1].int == dot and f.cFileName[2].int == 0)
 
 proc existsFile*(filename: string): bool {.rtl, extern: "nos$1",
-                                          tags: [FReadDir].} =
+                                          tags: [ReadDirEffect].} =
   ## Returns true if the file exists, false otherwise.
   when defined(windows):
     when useWinUnicode:
@@ -384,7 +393,7 @@ proc existsFile*(filename: string): bool {.rtl, extern: "nos$1",
     var res: TStat
     return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode)
 
-proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} =
+proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect].} =
   ## Returns true iff the directory `dir` exists. If `dir` is a file, false
   ## is returned.
   when defined(windows):
@@ -399,7 +408,7 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} =
     return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
 
 proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
-                                          tags: [FReadDir].} =
+                                          tags: [ReadDirEffect].} =
   ## Returns true iff the symlink `link` exists. Will return true
   ## regardless of whether the link points to a directory or file.
   when defined(windows):
@@ -421,44 +430,44 @@ proc dirExists*(dir: string): bool {.inline.} =
   ## Synonym for existsDir
   existsDir(dir)
 
-proc getLastModificationTime*(file: string): TTime {.rtl, extern: "nos$1".} =
+proc getLastModificationTime*(file: string): Time {.rtl, extern: "nos$1".} =
   ## Returns the `file`'s last modification time.
   when defined(posix):
     var res: TStat
-    if stat(file, res) < 0'i32: osError(osLastError())
+    if stat(file, res) < 0'i32: raiseOSError(osLastError())
     return res.st_mtime
   else:
     var f: TWIN32_FIND_DATA
     var h = findFirstFile(file, f)
-    if h == -1'i32: osError(osLastError())
+    if h == -1'i32: raiseOSError(osLastError())
     result = winTimeToUnixTime(rdFileTime(f.ftLastWriteTime))
     findClose(h)
 
-proc getLastAccessTime*(file: string): TTime {.rtl, extern: "nos$1".} =
+proc getLastAccessTime*(file: string): Time {.rtl, extern: "nos$1".} =
   ## Returns the `file`'s last read or write access time.
   when defined(posix):
     var res: TStat
-    if stat(file, res) < 0'i32: osError(osLastError())
+    if stat(file, res) < 0'i32: raiseOSError(osLastError())
     return res.st_atime
   else:
     var f: TWIN32_FIND_DATA
     var h = findFirstFile(file, f)
-    if h == -1'i32: osError(osLastError())
+    if h == -1'i32: raiseOSError(osLastError())
     result = winTimeToUnixTime(rdFileTime(f.ftLastAccessTime))
     findClose(h)
 
-proc getCreationTime*(file: string): TTime {.rtl, extern: "nos$1".} =
+proc getCreationTime*(file: string): Time {.rtl, extern: "nos$1".} =
   ## Returns the `file`'s creation time.
   ## Note that under posix OS's, the returned time may actually be the time at
   ## which the file's attribute's were last modified.
   when defined(posix):
     var res: TStat
-    if stat(file, res) < 0'i32: osError(osLastError())
+    if stat(file, res) < 0'i32: raiseOSError(osLastError())
     return res.st_ctime
   else:
     var f: TWIN32_FIND_DATA
     var h = findFirstFile(file, f)
-    if h == -1'i32: osError(osLastError())
+    if h == -1'i32: raiseOSError(osLastError())
     result = winTimeToUnixTime(rdFileTime(f.ftCreationTime))
     findClose(h)
 
@@ -474,19 +483,19 @@ proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} =
     when useWinUnicode:
       var res = newWideCString("", bufsize)
       var L = getCurrentDirectoryW(bufsize, res)
-      if L == 0'i32: osError(osLastError())
+      if L == 0'i32: raiseOSError(osLastError())
       result = res$L
     else:
       result = newString(bufsize)
       var L = getCurrentDirectoryA(bufsize, result)
-      if L == 0'i32: osError(osLastError())
+      if L == 0'i32: raiseOSError(osLastError())
       setLen(result, L)
   else:
     result = newString(bufsize)
     if getcwd(result, bufsize) != nil:
       setLen(result, c_strlen(result))
     else:
-      osError(osLastError())
+      raiseOSError(osLastError())
 
 proc setCurrentDir*(newDir: string) {.inline, tags: [].} =
   ## Sets the `current working directory`:idx:; `EOS` is raised if
@@ -494,11 +503,11 @@ proc setCurrentDir*(newDir: string) {.inline, tags: [].} =
   when defined(Windows):
     when useWinUnicode:
       if setCurrentDirectoryW(newWideCString(newDir)) == 0'i32:
-        osError(osLastError())
+        raiseOSError(osLastError())
     else:
-      if setCurrentDirectoryA(newDir) == 0'i32: osError(osLastError())
+      if setCurrentDirectoryA(newDir) == 0'i32: raiseOSError(osLastError())
   else:
-    if chdir(newDir) != 0'i32: osError(osLastError())
+    if chdir(newDir) != 0'i32: raiseOSError(osLastError())
 
 proc joinPath*(head, tail: string): string {.
   noSideEffect, rtl, extern: "nos$1".} =
@@ -506,12 +515,12 @@ proc joinPath*(head, tail: string): string {.
   ##
   ## For example on Unix:
   ##
-  ## .. code-block:: nimrod
+  ## .. code-block:: nim
   ##   joinPath("usr", "lib")
   ##
   ## results in:
   ##
-  ## .. code-block:: nimrod
+  ## .. code-block:: nim
   ##   "usr/lib"
   ##
   ## If head is the empty string, tail is returned. If tail is the empty
@@ -520,7 +529,7 @@ proc joinPath*(head, tail: string): string {.
   ## path separators not located on boundaries won't be modified. More
   ## examples on Unix:
   ##
-  ## .. code-block:: nimrod
+  ## .. code-block:: nim
   ##   assert joinPath("usr", "") == "usr/"
   ##   assert joinPath("", "lib") == "lib"
   ##   assert joinPath("", "/lib") == "/lib"
@@ -552,7 +561,7 @@ proc `/` * (head, tail: string): string {.noSideEffect.} =
   ##
   ## Here are some examples for Unix:
   ##
-  ## .. code-block:: nimrod
+  ## .. code-block:: nim
   ##   assert "usr" / "" == "usr/"
   ##   assert "" / "lib" == "lib"
   ##   assert "" / "/lib" == "/lib"
@@ -566,7 +575,7 @@ proc splitPath*(path: string): tuple[head, tail: string] {.
   ##
   ## Examples:
   ##
-  ## .. code-block:: nimrod
+  ## .. code-block:: nim
   ##   splitPath("usr/local/bin") -> ("usr/local", "bin")
   ##   splitPath("usr/local/bin/") -> ("usr/local/bin", "")
   ##   splitPath("bin") -> ("", "bin")
@@ -666,10 +675,10 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {.
   ##
   ## Example:
   ##
-  ## .. code-block:: nimrod
-  ##   var (dir, name, ext) = splitFile("usr/local/nimrodc.html")
+  ## .. code-block:: nim
+  ##   var (dir, name, ext) = splitFile("usr/local/nimc.html")
   ##   assert dir == "usr/local"
-  ##   assert name == "nimrodc"
+  ##   assert name == "nimc"
   ##   assert ext == ".html"
   ##
   ## If `path` has no extension, `ext` is the empty string.
@@ -701,7 +710,7 @@ proc extractFilename*(path: string): string {.
     result = splitPath(path).tail
 
 proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
-  tags: [FReadDir].} =
+  tags: [ReadDirEffect].} =
   ## Returns the full path of `filename`, raises EOS in case of an error.
   when defined(windows):
     const bufsize = 3072'i32
@@ -710,19 +719,19 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
       var res = newWideCString("", bufsize div 2)
       var L = getFullPathNameW(newWideCString(filename), bufsize, res, unused)
       if L <= 0'i32 or L >= bufsize:
-        osError(osLastError())
+        raiseOSError(osLastError())
       result = res$L
     else:
       var unused: cstring
       result = newString(bufsize)
       var L = getFullPathNameA(filename, bufsize, result, unused)
-      if L <= 0'i32 or L >= bufsize: osError(osLastError())
+      if L <= 0'i32 or L >= bufsize: raiseOSError(osLastError())
       setLen(result, L)
   else:
     # careful, realpath needs to take an allocated buffer according to Posix:
     result = newString(pathMax)
     var r = realpath(filename, result)
-    if r.isNil: osError(osLastError())
+    if r.isNil: raiseOSError(osLastError())
     setLen(result, c_strlen(result))
 
 proc changeFileExt*(filename, ext: string): string {.
@@ -800,7 +809,7 @@ when defined(Windows):
         )
 
 proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
-  tags: [FReadDir].} =
+  tags: [ReadDirEffect].} =
   ## Returns True if both pathname arguments refer to the same physical
   ## file or directory. Raises an exception if any of the files does not
   ## exist or information about it can not be obtained.
@@ -812,7 +821,7 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
     var f1 = openHandle(path1)
     var f2 = openHandle(path2)
 
-    var lastErr: TOSErrorCode
+    var lastErr: OSErrorCode
     if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE:
       var fi1, fi2: TBY_HANDLE_FILE_INFORMATION
 
@@ -831,22 +840,22 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
     discard closeHandle(f1)
     discard closeHandle(f2)
 
-    if not success: osError(lastErr)
+    if not success: raiseOSError(lastErr)
   else:
     var a, b: TStat
     if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32:
-      osError(osLastError())
+      raiseOSError(osLastError())
     else:
       result = a.st_dev == b.st_dev and a.st_ino == b.st_ino
 
 proc sameFileContent*(path1, path2: string): bool {.rtl, extern: "nos$1",
-  tags: [FReadIO].} =
+  tags: [ReadIOEffect].} =
   ## Returns True if both pathname arguments refer to files with identical
   ## binary content.
   const
     bufSize = 8192 # 8K buffer
   var
-    a, b: TFile
+    a, b: File
   if not open(a, path1): return false
   if not open(b, path2):
     close(a)
@@ -883,13 +892,13 @@ type
     fpOthersRead           ## read access for others
 
 proc getFilePermissions*(filename: string): set[TFilePermission] {.
-  rtl, extern: "nos$1", tags: [FReadDir].} =
+  rtl, extern: "nos$1", tags: [ReadDirEffect].} =
   ## retrieves file permissions for `filename`. `OSError` is raised in case of
   ## an error. On Windows, only the ``readonly`` flag is checked, every other
   ## permission is available in any case.
   when defined(posix):
     var a: TStat
-    if stat(filename, a) < 0'i32: osError(osLastError())
+    if stat(filename, a) < 0'i32: raiseOSError(osLastError())
     result = {}
     if (a.st_mode and S_IRUSR) != 0'i32: result.incl(fpUserRead)
     if (a.st_mode and S_IWUSR) != 0'i32: result.incl(fpUserWrite)
@@ -907,7 +916,7 @@ proc getFilePermissions*(filename: string): set[TFilePermission] {.
       wrapUnary(res, getFileAttributesW, filename)
     else:
       var res = getFileAttributesA(filename)
-    if res == -1'i32: osError(osLastError())
+    if res == -1'i32: raiseOSError(osLastError())
     if (res and FILE_ATTRIBUTE_READONLY) != 0'i32:
       result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead, 
                 fpOthersExec, fpOthersRead}
@@ -915,7 +924,7 @@ proc getFilePermissions*(filename: string): set[TFilePermission] {.
       result = {fpUserExec..fpOthersRead}
   
 proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {.
-  rtl, extern: "nos$1", tags: [FWriteDir].} =
+  rtl, extern: "nos$1", tags: [WriteDirEffect].} =
   ## sets the file permissions for `filename`. `OSError` is raised in case of
   ## an error. On Windows, only the ``readonly`` flag is changed, depending on
   ## ``fpUserWrite``.
@@ -933,13 +942,13 @@ proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {.
     if fpOthersWrite in permissions: p = p or S_IWOTH
     if fpOthersExec in permissions: p = p or S_IXOTH
     
-    if chmod(filename, p) != 0: osError(osLastError())
+    if chmod(filename, p) != 0: raiseOSError(osLastError())
   else:
     when useWinUnicode:
       wrapUnary(res, getFileAttributesW, filename)
     else:
       var res = getFileAttributesA(filename)
-    if res == -1'i32: osError(osLastError())
+    if res == -1'i32: raiseOSError(osLastError())
     if fpUserWrite in permissions: 
       res = res and not FILE_ATTRIBUTE_READONLY
     else:
@@ -948,10 +957,10 @@ proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {.
       wrapBinary(res2, setFileAttributesW, filename, res)
     else:
       var res2 = setFileAttributesA(filename, res)
-    if res2 == - 1'i32: osError(osLastError())
+    if res2 == - 1'i32: raiseOSError(osLastError())
 
 proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
-  tags: [FReadIO, FWriteIO].} =
+  tags: [ReadIOEffect, WriteIOEffect].} =
   ## Copies a file from `source` to `dest`.
   ##
   ## If this fails, `EOS` is raised. On the Windows platform this proc will
@@ -966,17 +975,17 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
     when useWinUnicode:
       let s = newWideCString(source)
       let d = newWideCString(dest)
-      if copyFileW(s, d, 0'i32) == 0'i32: osError(osLastError())
+      if copyFileW(s, d, 0'i32) == 0'i32: raiseOSError(osLastError())
     else:
-      if copyFileA(source, dest, 0'i32) == 0'i32: osError(osLastError())
+      if copyFileA(source, dest, 0'i32) == 0'i32: raiseOSError(osLastError())
   else:
     # generic version of copyFile which works for any platform:
     const bufSize = 8000 # better for memory manager
-    var d, s: TFile
-    if not open(s, source): osError(osLastError())
+    var d, s: File
+    if not open(s, source): raiseOSError(osLastError())
     if not open(d, dest, fmWrite):
       close(s)
-      osError(osLastError())
+      raiseOSError(osLastError())
     var buf = alloc(bufSize)
     while true:
       var bytesread = readBuffer(s, buf, bufSize)
@@ -986,17 +995,17 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
           dealloc(buf)
           close(s)
           close(d)
-          osError(osLastError())
+          raiseOSError(osLastError())
       if bytesread != bufSize: break
     dealloc(buf)
     close(s)
     close(d)
 
 proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
-  tags: [FReadIO, FWriteIO].} =
+  tags: [ReadIOEffect, WriteIOEffect].} =
   ## Moves a file from `source` to `dest`. If this fails, `EOS` is raised.
   if c_rename(source, dest) != 0'i32:
-    raise newException(EOS, $strerror(errno))
+    raise newException(OSError, $strerror(errno))
 
 when not declared(ENOENT) and not defined(Windows):
   when NoFakeVars:
@@ -1014,7 +1023,7 @@ when defined(Windows):
     template setFileAttributes(file, attrs: expr): expr {.immediate.} = 
       setFileAttributesA(file, attrs)
 
-proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
+proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect].} =
   ## Removes the `file`. If this fails, `EOS` is raised. This does not fail
   ## if the file never existed in the first place.
   ## On Windows, ignores the read-only attribute.
@@ -1026,15 +1035,15 @@ proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
     if deleteFile(f) == 0:
       if getLastError() == ERROR_ACCESS_DENIED: 
         if setFileAttributes(f, FILE_ATTRIBUTE_NORMAL) == 0:
-          osError(osLastError())
+          raiseOSError(osLastError())
         if deleteFile(f) == 0:
-          osError(osLastError())
+          raiseOSError(osLastError())
   else:
     if c_remove(file) != 0'i32 and errno != ENOENT:
-      raise newException(EOS, $strerror(errno))
+      raise newException(OSError, $strerror(errno))
 
 proc execShellCmd*(command: string): int {.rtl, extern: "nos$1",
-  tags: [FExecIO].} =
+  tags: [ExecIOEffect].} =
   ## Executes a `shell command`:idx:.
   ##
   ## Command has the form 'program args' where args are the command
@@ -1076,7 +1085,7 @@ when defined(windows):
         while true:
           var eend = strEnd(e)
           add(environment, $e)
-          e = cast[WideCString](cast[TAddress](eend)+2)
+          e = cast[WideCString](cast[ByteAddress](eend)+2)
           if eend[1].int == 0: break
         discard freeEnvironmentStringsW(env)
       else:
@@ -1087,7 +1096,7 @@ when defined(windows):
         while true:
           var eend = strEnd(e)
           add(environment, $e)
-          e = cast[cstring](cast[TAddress](eend)+1)
+          e = cast[cstring](cast[ByteAddress](eend)+1)
           if eend[1] == '\0': break
         discard freeEnvironmentStringsA(env)
       envComputed = true
@@ -1130,7 +1139,7 @@ proc findEnvVar(key: string): int =
     if startsWith(environment[i], temp): return i
   return -1
 
-proc getEnv*(key: string): TaintedString {.tags: [FReadEnv].} =
+proc getEnv*(key: string): TaintedString {.tags: [ReadEnvEffect].} =
   ## Returns the value of the `environment variable`:idx: named `key`.
   ##
   ## If the variable does not exist, "" is returned. To distinguish
@@ -1144,13 +1153,13 @@ proc getEnv*(key: string): TaintedString {.tags: [FReadEnv].} =
     if env == nil: return TaintedString("")
     result = TaintedString($env)
 
-proc existsEnv*(key: string): bool {.tags: [FReadEnv].} =
+proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
   ## Checks whether the environment variable named `key` exists.
   ## Returns true if it exists, false otherwise.
   if c_getenv(key) != nil: return true
   else: return findEnvVar(key) >= 0
 
-proc putEnv*(key, val: string) {.tags: [FWriteEnv].} =
+proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
   ## Sets the value of the `environment variable`:idx: named `key` to `val`.
   ## If an error occurs, `EInvalidEnvVar` is raised.
 
@@ -1166,16 +1175,16 @@ proc putEnv*(key, val: string) {.tags: [FWriteEnv].} =
     indx = high(environment)
   when defined(unix):
     if c_putenv(environment[indx]) != 0'i32:
-      osError(osLastError())
+      raiseOSError(osLastError())
   else:
     when useWinUnicode:
       var k = newWideCString(key)
       var v = newWideCString(val)
-      if setEnvironmentVariableW(k, v) == 0'i32: osError(osLastError())
+      if setEnvironmentVariableW(k, v) == 0'i32: raiseOSError(osLastError())
     else:
-      if setEnvironmentVariableA(key, val) == 0'i32: osError(osLastError())
+      if setEnvironmentVariableA(key, val) == 0'i32: raiseOSError(osLastError())
 
-iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [FReadEnv].} =
+iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
   ## Iterate over all `environments variables`:idx:. In the first component
   ## of the tuple is the name of the current variable stored, in the second
   ## its value.
@@ -1185,7 +1194,7 @@ iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [FReadEnv].} =
     yield (TaintedString(substr(environment[i], 0, p-1)),
            TaintedString(substr(environment[i], p+1)))
 
-iterator walkFiles*(pattern: string): string {.tags: [FReadDir].} =
+iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} =
   ## Iterate over all the files that match the `pattern`. On POSIX this uses
   ## the `glob`:idx: call.
   ##
@@ -1225,7 +1234,7 @@ type
     pcLinkToDir           ## path refers to a symbolic link to a directory
 
 iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {.
-  tags: [FReadDir].} =
+  tags: [ReadDirEffect].} =
   ## walks over the directory `dir` and yields for each directory or file in
   ## `dir`. The component type and full path for each item is returned.
   ## Walking is not recursive.
@@ -1237,7 +1246,7 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {.
   ##
   ## and this code:
   ##
-  ## .. code-block:: Nimrod
+  ## .. code-block:: Nim
   ##     for kind, path in walkDir("dirA"):
   ##       echo(path)
   ##
@@ -1278,7 +1287,7 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {.
       discard closedir(d)
 
 iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
-  tags: [FReadDir].} =
+  tags: [ReadDirEffect].} =
   ## walks over the directory `dir` and yields for each file in `dir`. The
   ## full path for each file is returned.
   ## **Warning**:
@@ -1313,12 +1322,12 @@ proc rawRemoveDir(dir: string) =
     let lastError = osLastError()
     if res == 0'i32 and lastError.int32 != 3'i32 and
         lastError.int32 != 18'i32 and lastError.int32 != 2'i32:
-      osError(lastError)
+      raiseOSError(lastError)
   else:
-    if rmdir(dir) != 0'i32 and errno != ENOENT: osError(osLastError())
+    if rmdir(dir) != 0'i32 and errno != ENOENT: raiseOSError(osLastError())
 
 proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
-  FWriteDir, FReadDir].} =
+  WriteDirEffect, ReadDirEffect].} =
   ## Removes the directory `dir` including all subdirectories and files
   ## in `dir` (recursively).
   ##
@@ -1333,19 +1342,19 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
 proc rawCreateDir(dir: string) =
   when defined(solaris):
     if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST and errno != ENOSYS:
-      osError(osLastError())
+      raiseOSError(osLastError())
   elif defined(unix):
     if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST:
-      osError(osLastError())
+      raiseOSError(osLastError())
   else:
     when useWinUnicode:
       wrapUnary(res, createDirectoryW, dir)
     else:
       var res = createDirectoryA(dir)
     if res == 0'i32 and getLastError() != 183'i32:
-      osError(osLastError())
+      raiseOSError(osLastError())
 
-proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
+proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect].} =
   ## Creates the `directory`:idx: `dir`.
   ##
   ## The directory may contain several subdirectories that do not exist yet.
@@ -1364,7 +1373,7 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
   rawCreateDir(dir)
 
 proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
-  tags: [FWriteIO, FReadIO].} =
+  tags: [WriteIOEffect, ReadIOEffect].} =
   ## Copies a directory from `source` to `dest`.
   ##
   ## If this fails, `EOS` is raised. On the Windows platform this proc will
@@ -1395,13 +1404,13 @@ proc createSymlink*(src, dest: string) =
       var wSrc = newWideCString(src)
       var wDst = newWideCString(dest)
       if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0:
-        osError(osLastError())
+        raiseOSError(osLastError())
     else:
       if createSymbolicLinkA(dest, src, flag) == 0 or getLastError() != 0:
-        osError(osLastError())
+        raiseOSError(osLastError())
   else:
     if symlink(src, dest) != 0:
-      osError(osLastError())
+      raiseOSError(osLastError())
 
 proc createHardlink*(src, dest: string) =
   ## Create a hard link at `dest` which points to the item specified
@@ -1414,13 +1423,13 @@ proc createHardlink*(src, dest: string) =
       var wSrc = newWideCString(src)
       var wDst = newWideCString(dest)
       if createHardLinkW(wDst, wSrc, nil) == 0:
-        osError(osLastError())
+        raiseOSError(osLastError())
     else:
       if createHardLinkA(dest, src, nil) == 0:
-        osError(osLastError())
+        raiseOSError(osLastError())
   else:
     if link(src, dest) != 0:
-      osError(osLastError())
+      raiseOSError(osLastError())
 
 proc parseCmdLine*(c: string): seq[string] {.
   noSideEffect, rtl, extern: "nos$1".} =
@@ -1537,7 +1546,7 @@ proc copyFileWithPermissions*(source, dest: string,
 
 proc copyDirWithPermissions*(source, dest: string,
     ignorePermissionErrors = true) {.rtl, extern: "nos$1",
-    tags: [FWriteIO, FReadIO].} =
+    tags: [WriteIOEffect, ReadIOEffect].} =
   ## Copies a directory from `source` to `dest` preserving file permissions.
   ##
   ## If this fails, `EOS` is raised. This is a wrapper proc around `copyDir()
@@ -1568,23 +1577,23 @@ proc copyDirWithPermissions*(source, dest: string,
 
 proc inclFilePermissions*(filename: string,
                           permissions: set[TFilePermission]) {.
-  rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} =
+  rtl, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect].} =
   ## a convenience procedure for:
   ##
-  ## .. code-block:: nimrod
+  ## .. code-block:: nim
   ##   setFilePermissions(filename, getFilePermissions(filename)+permissions)
   setFilePermissions(filename, getFilePermissions(filename)+permissions)
 
 proc exclFilePermissions*(filename: string,
                           permissions: set[TFilePermission]) {.
-  rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} =
+  rtl, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect].} =
   ## a convenience procedure for:
   ##
-  ## .. code-block:: nimrod
+  ## .. code-block:: nim
   ##   setFilePermissions(filename, getFilePermissions(filename)-permissions)
   setFilePermissions(filename, getFilePermissions(filename)-permissions)
 
-proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
+proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} =
   ## Returns the home directory of the current user.
   ##
   ## This proc is wrapped by the expandTilde proc for the convenience of
@@ -1592,12 +1601,12 @@ proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
   when defined(windows): return string(getEnv("USERPROFILE")) & "\\"
   else: return string(getEnv("HOME")) & "/"
 
-proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
+proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} =
   ## Returns the config directory of the current user for applications.
   when defined(windows): return string(getEnv("APPDATA")) & "\\"
   else: return string(getEnv("HOME")) & "/.config/"
 
-proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
+proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [ReadEnvEffect].} =
   ## Returns the temporary directory of the current user for applications to
   ## save temporary files in.
   when defined(windows): return string(getEnv("TEMP")) & "\\"
@@ -1605,7 +1614,7 @@ proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
 
 when defined(nimdoc):
   # Common forward declaration docstring block for parameter retrieval procs.
-  proc paramCount*(): int {.tags: [FReadIO].} =
+  proc paramCount*(): int {.tags: [ReadIOEffect].} =
     ## Returns the number of `command line arguments`:idx: given to the
     ## application.
     ##
@@ -1619,13 +1628,13 @@ when defined(nimdoc):
     ## can test for its availability with `declared() <system.html#declared>`_.
     ## Example:
     ##
-    ## .. code-block:: nimrod
+    ## .. code-block:: nim
     ##   when declared(paramCount):
     ##     # Use paramCount() here
     ##   else:
     ##     # Do something else!
 
-  proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} =
+  proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} =
     ## Returns the `i`-th `command line argument`:idx: given to the application.
     ##
     ## `i` should be in the range `1..paramCount()`, the `EInvalidIndex`
@@ -1642,14 +1651,14 @@ when defined(nimdoc):
     ## can test for its availability with `declared() <system.html#declared>`_.
     ## Example:
     ##
-    ## .. code-block:: nimrod
+    ## .. code-block:: nim
     ##   when declared(paramStr):
     ##     # Use paramStr() here
     ##   else:
     ##     # Do something else!
 
 elif defined(windows):
-  # Since we support GUI applications with Nimrod, we sometimes generate
+  # Since we support GUI applications with Nim, we sometimes generate
   # a WinMain entry proc. But a WinMain proc has no access to the parsed
   # command line arguments. The way to get them differs. Thus we parse them
   # ourselves. This has the additional benefit that the program's behaviour
@@ -1657,13 +1666,13 @@ elif defined(windows):
   var
     ownArgv {.threadvar.}: seq[string]
 
-  proc paramCount*(): int {.rtl, extern: "nos$1", tags: [FReadIO].} =
+  proc paramCount*(): int {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
     # Docstring in nimdoc block.
     if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
     result = ownArgv.len-1
 
   proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1",
-    tags: [FReadIO].} =
+    tags: [ReadIOEffect].} =
     # Docstring in nimdoc block.
     if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
     return TaintedString(ownArgv[i])
@@ -1674,12 +1683,12 @@ elif not defined(createNimRtl):
     cmdCount {.importc: "cmdCount".}: cint
     cmdLine {.importc: "cmdLine".}: cstringArray
 
-  proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} =
+  proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} =
     # Docstring in nimdoc block.
     if i < cmdCount and i >= 0: return TaintedString($cmdLine[i])
-    raise newException(EInvalidIndex, "invalid index")
+    raise newException(IndexError, "invalid index")
 
-  proc paramCount*(): int {.tags: [FReadIO].} =
+  proc paramCount*(): int {.tags: [ReadIOEffect].} =
     # Docstring in nimdoc block.
     result = cmdCount-1
 
@@ -1695,7 +1704,7 @@ when declared(paramCount) or defined(nimdoc):
     ## can test for its availability with `declared() <system.html#declared>`_.
     ## Example:
     ##
-    ## .. code-block:: nimrod
+    ## .. code-block:: nim
     ##   when declared(commandLineParams):
     ##     # Use commandLineParams() here
     ##   else:
@@ -1739,7 +1748,7 @@ when defined(macosx):
   proc getExecPath2(c: cstring, size: var cuint32): bool {.
     importc: "_NSGetExecutablePath", header: "<mach-o/dyld.h>".}
 
-proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} =
+proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
   ## Returns the filename of the application's executable.
   ##
   ## This procedure will resolve symlinks.
@@ -1795,38 +1804,38 @@ proc getApplicationDir*(): string {.rtl, extern: "nos$1", deprecated.} =
   ## instead.
   result = splitFile(getAppFilename()).dir
 
-proc getAppDir*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} =
+proc getAppDir*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
   ## Returns the directory of the application's executable.
   ## **Note**: This does not work reliably on BSD.
   result = splitFile(getAppFilename()).dir
 
-proc sleep*(milsecs: int) {.rtl, extern: "nos$1", tags: [FTime].} =
+proc sleep*(milsecs: int) {.rtl, extern: "nos$1", tags: [TimeEffect].} =
   ## sleeps `milsecs` milliseconds.
   when defined(windows):
     winlean.sleep(int32(milsecs))
   else:
     var a, b: Ttimespec
-    a.tv_sec = TTime(milsecs div 1000)
+    a.tv_sec = Time(milsecs div 1000)
     a.tv_nsec = (milsecs mod 1000) * 1000 * 1000
     discard posix.nanosleep(a, b)
 
 proc getFileSize*(file: string): BiggestInt {.rtl, extern: "nos$1",
-  tags: [FReadIO].} =
+  tags: [ReadIOEffect].} =
   ## returns the file size of `file`. Can raise ``EOS``.
   when defined(windows):
     var a: TWIN32_FIND_DATA
     var resA = findFirstFile(file, a)
-    if resA == -1: osError(osLastError())
+    if resA == -1: raiseOSError(osLastError())
     result = rdFileSize(a)
     findClose(resA)
   else:
-    var f: TFile
+    var f: File
     if open(f, file):
       result = getFileSize(f)
       close(f)
-    else: osError(osLastError())
+    else: raiseOSError(osLastError())
 
-proc findExe*(exe: string): string {.tags: [FReadDir, FReadEnv].} =
+proc findExe*(exe: string): string {.tags: [ReadDirEffect, ReadEnvEffect].} =
   ## Searches for `exe` in the current working directory and then
   ## in directories listed in the ``PATH`` environment variable.
   ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe`
@@ -1850,11 +1859,10 @@ proc expandTilde*(path: string): string =
   ## The behaviour of this proc is the same on the Windows platform despite not
   ## having this convention. Example:
   ##
-  ## .. code-block:: nimrod
+  ## .. code-block:: nim
   ##   let configFile = expandTilde("~" / "appname.cfg")
   ##   echo configFile
   ##   # --> C:\Users\amber\appname.cfg
-
   if len(path) > 1 and path[0] == '~' and (path[1] == '/' or path[1] == '\\'):
     result = getHomeDir() / path[2..len(path)-1]
   else:
@@ -1867,7 +1875,7 @@ when defined(Windows):
 else:
   type
     DeviceId* = TDev
-    FileId* = TIno
+    FileId* = Tino
 
 type
   FileInfo* = object
@@ -1877,12 +1885,12 @@ type
     size*: BiggestInt # Size of file.
     permissions*: set[TFilePermission] # File permissions
     linkCount*: BiggestInt # Number of hard links the file object has.
-    lastAccessTime*: TTime # Time file was last accessed.
-    lastWriteTime*: TTime # Time file was last modified/written to.
-    creationTime*: TTime # Time file was created. Not supported on all systems!
+    lastAccessTime*: Time # Time file was last accessed.
+    lastWriteTime*: Time # Time file was last modified/written to.
+    creationTime*: Time # Time file was created. Not supported on all systems!
 
 template rawToFormalFileInfo(rawInfo, formalInfo): expr =
-  ## Transforms the native file info structure into the one nimrod uses.
+  ## Transforms the native file info structure into the one nim uses.
   ## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows,
   ## or a 'TStat' structure on posix
   when defined(Windows):
@@ -1939,7 +1947,7 @@ template rawToFormalFileInfo(rawInfo, formalInfo): expr =
     if S_ISDIR(rawInfo.st_mode): formalInfo.kind = pcDir
     if S_ISLNK(rawInfo.st_mode): formalInfo.kind.inc()
 
-proc getFileInfo*(handle: TFileHandle): FileInfo =
+proc getFileInfo*(handle: FileHandle): FileInfo =
   ## Retrieves file information for the file object represented by the given
   ## handle.
   ##
@@ -1952,16 +1960,16 @@ proc getFileInfo*(handle: TFileHandle): FileInfo =
     # To transform the C file descripter to a native file handle.
     var realHandle = get_osfhandle(handle)
     if getFileInformationByHandle(realHandle, addr rawInfo) == 0:
-      osError(osLastError())
+      raiseOSError(osLastError())
     rawToFormalFileInfo(rawInfo, result)
   else:
     var rawInfo: TStat
     if fstat(handle, rawInfo) < 0'i32:
-      osError(osLastError())
+      raiseOSError(osLastError())
     rawToFormalFileInfo(rawInfo, result)
 
-proc getFileInfo*(file: TFile): FileInfo =
-  result = getFileInfo(file.fileHandle())
+proc getFileInfo*(file: File): FileInfo =
+  result = getFileInfo(file.getFileHandle())
 
 proc getFileInfo*(path: string, followSymlink = true): FileInfo =
   ## Retrieves file information for the file object pointed to by `path`.
@@ -1982,19 +1990,19 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo =
       handle = openHandle(path, followSymlink)
       rawInfo: TBY_HANDLE_FILE_INFORMATION
     if handle == INVALID_HANDLE_VALUE:
-      osError(osLastError())
+      raiseOSError(osLastError())
     if getFileInformationByHandle(handle, addr rawInfo) == 0:
-      osError(osLastError())
+      raiseOSError(osLastError())
     rawToFormalFileInfo(rawInfo, result)
     discard closeHandle(handle)
   else:
     var rawInfo: TStat
     if followSymlink:
       if lstat(path, rawInfo) < 0'i32:
-        osError(osLastError())
+        raiseOSError(osLastError())
     else:
       if stat(path, rawInfo) < 0'i32:
-        osError(osLastError())
+        raiseOSError(osLastError())
     rawToFormalFileInfo(rawInfo, result)
 
 proc isHidden*(path: string): bool =
@@ -2006,7 +2014,10 @@ proc isHidden*(path: string): bool =
   ## On Unix-like systems, a file is hidden if it starts with a '.' (period)
   ## and is not *just* '.' or '..' ' ."
   when defined(Windows):
-    wrapUnary(attributes, getFileAttributesW, path)
+    when useWinUnicode:
+      wrapUnary(attributes, getFileAttributesW, path)
+    else:
+      var attributes = getFileAttributesA(path)
     if attributes != -1'i32:
       result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32
   else: