summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-11-18 13:34:48 +0100
committerAraq <rumpf_a@web.de>2012-11-18 13:34:48 +0100
commitec9b1f78e1d574017ec7372eb6acf1e7078053f9 (patch)
tree060804c9f5a490580a5c29e7c7fa3760c5b70ad2 /lib
parent1c17d3e84158dc6c88a92af690fddd2c3f921c34 (diff)
downloadNim-ec9b1f78e1d574017ec7372eb6acf1e7078053f9.tar.gz
annotated effects of modules: os, sockets, times
Diffstat (limited to 'lib')
-rwxr-xr-xlib/pure/os.nim100
-rwxr-xr-xlib/pure/osproc.nim7
-rwxr-xr-xlib/pure/sockets.nim119
-rwxr-xr-xlib/pure/times.nim16
4 files changed, 142 insertions, 100 deletions
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 68634e4ca..a220c1da4 100755
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -28,6 +28,17 @@ 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
+
 const
   doslike = defined(windows) or defined(OS2) or defined(DOS)
     # DOS-like filesystem
@@ -275,7 +286,8 @@ when defined(windows):
 
     template getFilename(f: expr): expr = $f.cFilename
     
-proc existsFile*(filename: string): bool {.rtl, extern: "nos$1".} =
+proc existsFile*(filename: string): bool {.rtl, extern: "nos$1", 
+                                          tags: [FReadDir].} =
   ## Returns true if the file exists, false otherwise.
   when defined(windows):
     when useWinUnicode:
@@ -288,7 +300,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".} =
+proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} =
   ## Returns true iff the directory `dir` exists. If `dir` is a file, false
   ## is returned.
   when defined(windows):
@@ -346,7 +358,7 @@ proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} =
   ## modification time is later than `b`'s.
   result = getLastModificationTime(a) - getLastModificationTime(b) > 0
 
-proc getCurrentDir*(): string {.rtl, extern: "nos$1".} =
+proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} =
   ## Returns the `current working directory`:idx:.
   const bufsize = 512 # should be enough
   when defined(windows):
@@ -368,7 +380,7 @@ proc getCurrentDir*(): string {.rtl, extern: "nos$1".} =
     else:
       OSError()
 
-proc setCurrentDir*(newDir: string) {.inline.} =
+proc setCurrentDir*(newDir: string) {.inline, tags: [].} =
   ## Sets the `current working directory`:idx:; `EOS` is raised if
   ## `newDir` cannot been set.
   when defined(Windows):
@@ -559,7 +571,8 @@ proc extractFilename*(path: string): string {.
   else:
     result = splitPath(path).tail
 
-proc expandFilename*(filename: string): string {.rtl, extern: "nos$1".} =
+proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
+  tags: [FReadDir].} =
   ## Returns the full path of `filename`, raises EOS in case of an error.
   when defined(windows):
     const bufsize = 3072'i32
@@ -647,7 +660,8 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
   elif defined(posix):
     result = path[0] == '/'
 
-proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1".} =
+proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", 
+  tags: [FReadDir].} =
   ## 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.
@@ -702,7 +716,8 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1".} =
     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".} =
+proc sameFileContent*(path1, path2: string): bool {.rtl, extern: "nos$1",
+  tags: [FReadIO].} =
   ## Returns True if both pathname arguments refer to files with identical
   ## binary content.
   const
@@ -732,7 +747,8 @@ proc sameFileContent*(path1, path2: string): bool {.rtl, extern: "nos$1".} =
   close(a)
   close(b)
 
-proc copyFile*(source, dest: string) {.rtl, extern: "nos$1".} =
+proc copyFile*(source, dest: string) {.rtl, extern: "nos$1", 
+  tags: [FReadIO, FWriteIO].} =
   ## Copies a file from `source` to `dest`. If this fails,
   ## `EOS` is raised.
   when defined(Windows):
@@ -768,19 +784,21 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1".} =
     close(s)
     close(d)
 
-proc moveFile*(source, dest: string) {.rtl, extern: "nos$1".} =
+proc moveFile*(source, dest: string) {.rtl, extern: "nos$1", 
+  tags: [FReadIO, FWriteIO].} =
   ## Moves a file from `source` to `dest`. If this fails, `EOS` is raised.
   if crename(source, dest) != 0'i32: OSError()
 
 when not defined(ENOENT):
-  var ENOENT* {.importc, header: "<errno.h>".}: cint
+  var ENOENT {.importc, header: "<errno.h>".}: cint
 
-proc removeFile*(file: string) {.rtl, extern: "nos$1".} =
+proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
   ## Removes the `file`. If this fails, `EOS` is raised. This does not fail
   ## if the file never existed in the first place.
   if cremove(file) != 0'i32 and errno != ENOENT: OSError()
 
-proc execShellCmd*(command: string): int {.rtl, extern: "nos$1".} =
+proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", 
+  tags: [FExecIO].} =
   ## Executes a `shell command`:idx:.
   ##
   ## Command has the form 'program args' where args are the command
@@ -873,7 +891,7 @@ proc findEnvVar(key: string): int =
     if startsWith(environment[i], temp): return i
   return -1
 
-proc getEnv*(key: string): TaintedString =
+proc getEnv*(key: string): TaintedString {.tags: [FReadEnv].} =
   ## Returns the value of the `environment variable`:idx: named `key`.
   ##
   ## If the variable does not exist, "" is returned. To distinguish
@@ -887,13 +905,13 @@ proc getEnv*(key: string): TaintedString =
     if env == nil: return TaintedString("")
     result = TaintedString($env)
 
-proc existsEnv*(key: string): bool =
+proc existsEnv*(key: string): bool {.tags: [FReadEnv].} =
   ## Checks whether the environment variable named `key` exists.
   ## Returns true if it exists, false otherwise.
   if cgetenv(key) != nil: return true
   else: return findEnvVar(key) >= 0
 
-proc putEnv*(key, val: string) =
+proc putEnv*(key, val: string) {.tags: [FWriteEnv].} =
   ## Sets the value of the `environment variable`:idx: named `key` to `val`.
   ## If an error occurs, `EInvalidEnvVar` is raised.
 
@@ -921,7 +939,7 @@ proc putEnv*(key, val: string) =
     else:
       if SetEnvironmentVariableA(key, val) == 0'i32: OSError()
 
-iterator envPairs*(): tuple[key, value: TaintedString] =
+iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [FReadEnv].} =
   ## 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.
@@ -931,7 +949,7 @@ iterator envPairs*(): tuple[key, value: TaintedString] =
     yield (TaintedString(substr(environment[i], 0, p-1)), 
            TaintedString(substr(environment[i], p+1)))
 
-iterator walkFiles*(pattern: string): string =
+iterator walkFiles*(pattern: string): string {.tags: [FReadDir].} =
   ## Iterate over all the files that match the `pattern`. On POSIX this uses
   ## the `glob`:idx: call.
   ##
@@ -969,7 +987,8 @@ type
     pcDir,                ## path refers to a directory
     pcLinkToDir           ## path refers to a symbolic link to a directory
 
-iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] =
+iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {.
+  tags: [FReadDir].} =
   ## 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.
@@ -1019,7 +1038,8 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] =
           yield (k, y)
       discard closeDir(d)
 
-iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string =
+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.
   ## Walking is recursive. `filter` controls the behaviour of the iterator:
@@ -1052,7 +1072,8 @@ proc rawRemoveDir(dir: string) =
   else:
     if rmdir(dir) != 0'i32 and errno != ENOENT: OSError()
 
-proc removeDir*(dir: string) {.rtl, extern: "nos$1".} =
+proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
+  FWriteDir, FReadDir].} =
   ## Removes the directory `dir` including all subdirectories and files
   ## in `dir` (recursively). If this fails, `EOS` is raised. This does not fail
   ## if the directory never existed in the first place.
@@ -1074,7 +1095,7 @@ proc rawCreateDir(dir: string) =
     if res == 0'i32 and GetLastError() != 183'i32:
       OSError()
 
-proc createDir*(dir: string) {.rtl, extern: "nos$1".} =
+proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
   ## Creates the `directory`:idx: `dir`.
   ##
   ## The directory may contain several subdirectories that do not exist yet.
@@ -1085,7 +1106,8 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1".} =
     if dir[i] in {dirsep, altsep}: rawCreateDir(substr(dir, 0, i-1))
   rawCreateDir(dir)
 
-proc copyDir*(source, dest: string) {.rtl, extern: "nos$1".} =
+proc copyDir*(source, dest: string) {.rtl, extern: "nos$1", 
+  tags: [FWriteIO, FReadIO].} =
   ## Copies a directory from `source` to `dest`. If this fails, `EOS` is raised.
   createDir(dest)
   for kind, path in walkDir(source):
@@ -1199,7 +1221,7 @@ type
     fpOthersRead           ## read access for others
 
 proc getFilePermissions*(filename: string): set[TFilePermission] {.
-  rtl, extern: "nos$1".} =
+  rtl, extern: "nos$1", tags: [FReadDir].} =
   ## 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.
@@ -1231,7 +1253,7 @@ proc getFilePermissions*(filename: string): set[TFilePermission] {.
       result = {fpUserExec..fpOthersRead}
   
 proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {.
-  rtl, extern: "nos$1".} =
+  rtl, extern: "nos$1", tags: [FWriteDir].} =
   ## 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``.
@@ -1268,7 +1290,7 @@ proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {.
   
 proc inclFilePermissions*(filename: string, 
                           permissions: set[TFilePermission]) {.
-  rtl, extern: "nos$1".} =
+  rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} =
   ## a convenience procedure for: 
   ##
   ## .. code-block:: nimrod
@@ -1277,24 +1299,24 @@ proc inclFilePermissions*(filename: string,
 
 proc exclFilePermissions*(filename: string, 
                           permissions: set[TFilePermission]) {.
-  rtl, extern: "nos$1".} =
+  rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} =
   ## a convenience procedure for: 
   ##
   ## .. code-block:: nimrod
   ##   setFilePermissions(filename, getFilePermissions(filename)-permissions)
   setFilePermissions(filename, getFilePermissions(filename)-permissions)
 
-proc getHomeDir*(): string {.rtl, extern: "nos$1".} =
+proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
   ## Returns the home directory of the current user.
   when defined(windows): return string(getEnv("USERPROFILE")) & "\\"
   else: return string(getEnv("HOME")) & "/"
 
-proc getConfigDir*(): string {.rtl, extern: "nos$1".} =
+proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
   ## 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".} =
+proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} =
   ## Returns the temporary directory of the current user for applications to
   ## save temporary files in.
   when defined(windows): return string(getEnv("TEMP")) & "\\"
@@ -1309,13 +1331,14 @@ when defined(windows):
   var
     ownArgv: seq[string]
 
-  proc paramCount*(): int {.rtl, extern: "nos$1".} =
+  proc paramCount*(): int {.rtl, extern: "nos$1", tags: [FReadIO].} =
     ## Returns the number of `command line arguments`:idx: given to the
     ## application.
     if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
     result = ownArgv.len-1
 
-  proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1".} =
+  proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1", 
+    tags: [FReadIO].} =
     ## Returns the `i`-th `command line argument`:idx: given to the
     ## application.
     ##
@@ -1330,11 +1353,11 @@ elif not defined(createNimRtl):
     cmdCount {.importc: "cmdCount".}: cint
     cmdLine {.importc: "cmdLine".}: cstringArray
 
-  proc paramStr*(i: int): TaintedString =
+  proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} =
     if i < cmdCount and i >= 0: return TaintedString($cmdLine[i])
     raise newException(EInvalidIndex, "invalid index")
 
-  proc paramCount*(): int = return cmdCount-1
+  proc paramCount*(): int {.tags: [FReadIO].} = return cmdCount-1
 
 when defined(linux) or defined(solaris) or defined(bsd) or defined(aix):
   proc getApplAux(procPath: string): string =
@@ -1357,7 +1380,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".} =
+proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} =
   ## Returns the filename of the application's executable.
   ## **Note**: This does not work reliably on BSD.
 
@@ -1413,12 +1436,12 @@ proc getApplicationDir*(): string {.rtl, extern: "nos$1", deprecated.} =
   ## instead.
   result = splitFile(getAppFilename()).dir
 
-proc getAppDir*(): string {.rtl, extern: "nos$1".} =
+proc getAppDir*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} =
   ## 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".} =
+proc sleep*(milsecs: int) {.rtl, extern: "nos$1", tags: [FTime].} =
   ## sleeps `milsecs` milliseconds.
   when defined(windows):
     winlean.sleep(int32(milsecs))
@@ -1428,7 +1451,8 @@ proc sleep*(milsecs: int) {.rtl, extern: "nos$1".} =
     a.tv_nsec = (milsecs mod 1000) * 1000
     discard posix.nanosleep(a, b)
 
-proc getFileSize*(file: string): biggestInt {.rtl, extern: "nos$1".} =
+proc getFileSize*(file: string): biggestInt {.rtl, extern: "nos$1",
+  tags: [FReadIO].} =
   ## returns the file size of `file`. Can raise ``EOS``. 
   when defined(windows):
     var a: TWin32FindData
@@ -1443,7 +1467,7 @@ proc getFileSize*(file: string): biggestInt {.rtl, extern: "nos$1".} =
       close(f)
     else: OSError()
 
-proc findExe*(exe: string): string = 
+proc findExe*(exe: string): string {.tags: [FReadDir, FReadEnv].} = 
   ## 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` 
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 46b35cb10..a8c0ea809 100755
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -58,7 +58,7 @@ proc startProcess*(command: string,
                    args: openarray[string] = [],
                    env: PStringTable = nil, 
                    options: set[TProcessOption] = {poStdErrToStdOut}): 
-              PProcess {.rtl, extern: "nosp$1", tags: [FExecIO].}
+              PProcess {.rtl, extern: "nosp$1", tags: [FExecIO, FReadEnv].}
   ## Starts a process. `Command` is the executable file, `workingDir` is the
   ## process's working directory. If ``workingDir == ""`` the current directory
   ## is used. `args` are the command line arguments that are passed to the
@@ -74,7 +74,8 @@ proc startProcess*(command: string,
   ## but ``EOS`` is raised in case of an error.
 
 proc startCmd*(command: string, options: set[TProcessOption] = {
-               poStdErrToStdOut, poUseShell}): PProcess {.tags: [FExecIO].} =
+               poStdErrToStdOut, poUseShell}): PProcess {.
+               tags: [FExecIO, FReadEnv].} =
   ## a simpler version of `startProcess` that parses the command line into
   ## program and arguments and then calls `startProcess` with the empty string
   ## for `workingDir` and the nil string table for `env`.
@@ -159,7 +160,7 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
 proc execProcesses*(cmds: openArray[string],
                     options = {poStdErrToStdOut, poParentStreams},
                     n = countProcessors()): int {.rtl, extern: "nosp$1", 
-                    tags: [FExecIO].} =
+                    tags: [FExecIO, FTime, FReadEnv].} =
   ## executes the commands `cmds` in parallel. Creates `n` processes
   ## that execute in parallel. The highest return value of all processes
   ## is returned.
diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim
index 6e0574e85..328f9cb9e 100755
--- a/lib/pure/sockets.nim
+++ b/lib/pure/sockets.nim
@@ -242,9 +242,10 @@ when defined(ssl):
     ## are available with the addition of ``ProtSSLv23`` which allows for 
     ## compatibility with all of them.
     ##
-    ## There are currently only two options for verify mode; one is ``CVerifyNone``
-    ## and with it certificates will not be verified the other is ``CVerifyPeer``
-    ## and certificates will be verified for it, ``CVerifyPeer`` is the safest choice.
+    ## There are currently only two options for verify mode;
+    ## one is ``CVerifyNone`` and with it certificates will not be verified
+    ## the other is ``CVerifyPeer`` and certificates will be verified for
+    ## it, ``CVerifyPeer`` is the safest choice.
     ##
     ## The last two parameters specify the certificate file path and the key file
     ## path, a server socket will most likely not work without these.
@@ -291,7 +292,7 @@ when defined(ssl):
     if SSLSetFd(socket.sslHandle, socket.fd) != 1:
       SSLError()
 
-proc listen*(socket: TSocket, backlog = SOMAXCONN) =
+proc listen*(socket: TSocket, backlog = SOMAXCONN) {.tags: [FReadIO].} =
   ## Marks ``socket`` as accepting connections. 
   ## ``Backlog`` specifies the maximum length of the 
   ## queue of pending connections.
@@ -335,7 +336,8 @@ template gaiNim(a, p, h, list: expr): stmt =
       else:
         OSError($gai_strerror(gaiResult))
 
-proc bindAddr*(socket: TSocket, port = TPort(0), address = "") =
+proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {.
+  tags: [FReadIO].} =
   ## binds an address/port number to a socket.
   ## Use address string in dotted decimal form like "a.b.c.d"
   ## or leave "" for any address.
@@ -390,15 +392,6 @@ proc getSockName*(socket: TSocket): TPort =
     OSError()
   result = TPort(sockets.ntohs(name.sin_port))
 
-proc selectWrite*(writefds: var seq[TSocket], timeout = 500): int
-  ## When a socket in ``writefds`` is ready to be written to then a non-zero
-  ## value will be returned specifying the count of the sockets which can be
-  ## written to. The sockets which can be written to will also be removed
-  ## from ``writefds``.
-  ##
-  ## ``timeout`` is specified in miliseconds and ``-1`` can be specified for
-  ## an unlimited time.
-
 template acceptAddrPlain(noClientRet, successRet: expr, 
                          sslImplementation: stmt): stmt {.immediate.} =
   assert(client != nil)
@@ -439,7 +432,8 @@ template acceptAddrPlain(noClientRet, successRet: expr,
     else:
       return successRet
 
-proc acceptAddr*(server: TSocket, client: var TSocket, address: var string) =
+proc acceptAddr*(server: TSocket, client: var TSocket, address: var string) {.
+  tags: [FReadIO].} =
   ## Blocks until a connection is being made from a client. When a connection
   ## is made sets ``client`` to the client socket and ``address`` to the address
   ## of the connecting client.
@@ -482,7 +476,8 @@ proc acceptAddr*(server: TSocket, client: var TSocket, address: var string) =
 proc setBlocking*(s: TSocket, blocking: bool)
 when defined(ssl):
   proc acceptAddrSSL*(server: TSocket, client: var TSocket,
-                      address: var string): TSSLAcceptResult =
+                      address: var string): TSSLAcceptResult {.
+                      tags: [FReadIO].} =
     ## This procedure should only be used for non-blocking **SSL** sockets. 
     ## It will immediately return with one of the following values:
     ## 
@@ -531,7 +526,7 @@ when defined(ssl):
       acceptAddrPlain(AcceptNoClient, AcceptSuccess):
         doHandshake()
 
-proc accept*(server: TSocket, client: var TSocket) =
+proc accept*(server: TSocket, client: var TSocket) {.tags: [FReadIO].} =
   ## Equivalent to ``acceptAddr`` but doesn't return the address, only the
   ## socket.
   ## 
@@ -541,7 +536,8 @@ proc accept*(server: TSocket, client: var TSocket) =
   var addrDummy = ""
   acceptAddr(server, client, addrDummy)
 
-proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] {.deprecated.} =
+proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] {.
+  deprecated, tags: [FReadIO].} =
   ## Slightly different version of ``acceptAddr``.
   ##
   ## **Deprecated since version 0.9.0:** Please use the function above.
@@ -551,7 +547,7 @@ proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] {.dep
   acceptAddr(server, client, address)
   return (client, address)
 
-proc accept*(server: TSocket): TSocket {.deprecated.} =
+proc accept*(server: TSocket): TSocket {.deprecated, tags: [FReadIO].} =
   ## **Deprecated since version 0.9.0:** Please use the function above.
   new(result)
   var address = ""
@@ -568,7 +564,7 @@ proc close*(socket: TSocket) =
     if socket.isSSL:
       discard SSLShutdown(socket.sslHandle)
 
-proc getServByName*(name, proto: string): TServent =
+proc getServByName*(name, proto: string): TServent {.tags: [FReadIO].} =
   ## well-known getservbyname proc.
   when defined(Windows):
     var s = winlean.getservbyname(name, proto)
@@ -580,7 +576,7 @@ proc getServByName*(name, proto: string): TServent =
   result.port = TPort(s.s_port)
   result.proto = $s.s_proto
   
-proc getServByPort*(port: TPort, proto: string): TServent = 
+proc getServByPort*(port: TPort, proto: string): TServent {.tags: [FReadIO].} = 
   ## well-known getservbyport proc.
   when defined(Windows):
     var s = winlean.getservbyport(ze(int16(port)).cint, proto)
@@ -592,7 +588,7 @@ proc getServByPort*(port: TPort, proto: string): TServent =
   result.port = TPort(s.s_port)
   result.proto = $s.s_proto
 
-proc getHostByAddr*(ip: string): THostEnt =
+proc getHostByAddr*(ip: string): THostEnt {.tags: [FReadIO].} =
   ## This function will lookup the hostname of an IP Address.
   var myaddr: TInAddr
   myaddr.s_addr = inet_addr(ip)
@@ -621,7 +617,7 @@ proc getHostByAddr*(ip: string): THostEnt =
   result.addrList = cstringArrayToSeq(s.h_addr_list)
   result.length = int(s.h_length)
 
-proc getHostByName*(name: string): THostEnt = 
+proc getHostByName*(name: string): THostEnt {.tags: [FReadIO].} = 
   ## well-known gethostbyname proc.
   when defined(Windows):
     var s = winlean.gethostbyname(name)
@@ -642,7 +638,8 @@ proc getHostByName*(name: string): THostEnt =
   result.addrList = cstringArrayToSeq(s.h_addr_list)
   result.length = int(s.h_length)
 
-proc getSockOptInt*(socket: TSocket, level, optname: int): int = 
+proc getSockOptInt*(socket: TSocket, level, optname: int): int {.
+  tags: [FReadIO].} = 
   ## getsockopt for integer options.
   var res: cint
   var size = sizeof(res).TSockLen
@@ -651,7 +648,8 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int =
     OSError()
   result = int(res)
 
-proc setSockOptInt*(socket: TSocket, level, optname, optval: int) =
+proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {.
+  tags: [FWriteIO].} =
   ## setsockopt for integer options.
   var value = cint(optval)
   if setsockopt(socket.fd, cint(level), cint(optname), addr(value),  
@@ -659,7 +657,7 @@ proc setSockOptInt*(socket: TSocket, level, optname, optval: int) =
     OSError()
 
 proc connect*(socket: TSocket, name: string, port = TPort(0), 
-              af: TDomain = AF_INET) =
+              af: TDomain = AF_INET) {.tags: [FReadIO].} =
   ## Connects socket to ``name``:``port``. ``Name`` can be an IP address or a
   ## host name. If ``name`` is a host name, this function will try each IP
   ## of that host name. ``htons`` is already performed on ``port`` so you must
@@ -719,7 +717,7 @@ proc connect*(socket: TSocket, name: string, port = TPort(0),
       OSError()
 
 proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
-                     af: TDomain = AF_INET) =
+                     af: TDomain = AF_INET) {.tags: [FReadIO].} =
   ## A variant of ``connect`` for non-blocking sockets.
   ##
   ## This procedure will immediatelly return, it will not block until a connection
@@ -764,7 +762,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
       socket.sslNoHandshake = true
 
 when defined(ssl):
-  proc handshake*(socket: TSocket): bool =
+  proc handshake*(socket: TSocket): bool {.tags: [FReadIO, RWriteIO].} =
     ## This proc needs to be called on a socket after it connects. This is
     ## only applicable when using ``connectAsync``.
     ## This proc performs the SSL handshake.
@@ -854,7 +852,7 @@ proc checkBuffer(readfds: var seq[TSocket]): int =
   readfds = res
 
 proc select*(readfds, writefds, exceptfds: var seq[TSocket], 
-             timeout = 500): int = 
+             timeout = 500): int {.tags: [FReadIO].} = 
   ## Traditional select function. This function will return the number of
   ## sockets that are ready to be read from, written to, or which have errors
   ## if there are none; 0 is returned. 
@@ -884,7 +882,7 @@ proc select*(readfds, writefds, exceptfds: var seq[TSocket],
   pruneSocketSet(exceptfds, (ex))
 
 proc select*(readfds, writefds: var seq[TSocket], 
-             timeout = 500): int =
+             timeout = 500): int {.tags: [FReadIO].} =
   ## variant of select with only a read and write list.
   let buffersFilled = checkBuffer(readfds)
   if buffersFilled > 0:
@@ -905,7 +903,14 @@ proc select*(readfds, writefds: var seq[TSocket],
   pruneSocketSet(writefds, (wr))
 
 proc selectWrite*(writefds: var seq[TSocket], 
-                  timeout = 500): int =
+                  timeout = 500): int {.tags: [FReadIO].} =
+  ## When a socket in ``writefds`` is ready to be written to then a non-zero
+  ## value will be returned specifying the count of the sockets which can be
+  ## written to. The sockets which can be written to will also be removed
+  ## from ``writefds``.
+  ##
+  ## ``timeout`` is specified in miliseconds and ``-1`` can be specified for
+  ## an unlimited time.
   var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout)
   
   var wr: TFdSet
@@ -961,7 +966,7 @@ template retRead(flags, readBytes: int) =
     else:
       return res
 
-proc recv*(socket: TSocket, data: pointer, size: int): int =
+proc recv*(socket: TSocket, data: pointer, size: int): int {.tags: [FReadIO].} =
   ## receives data from a socket
   if socket.isBuffered:
     if socket.bufLen == 0:
@@ -999,7 +1004,8 @@ proc recv*(socket: TSocket, data: pointer, size: int): int =
     else:
       result = recv(socket.fd, data, size.cint, 0'i32)
 
-proc waitFor(socket: TSocket, waited: var float, timeout: int): int =
+proc waitFor(socket: TSocket, waited: var float, timeout: int): int {.
+  tags: [FTime].} =
   ## returns the number of characters available to be read. In unbuffered
   ## sockets this is always 1, otherwise this may as big as the buffer, currently
   ## 4000.
@@ -1015,7 +1021,8 @@ proc waitFor(socket: TSocket, waited: var float, timeout: int): int =
       raise newException(ETimeout, "Call to recv() timed out.")
     waited += (epochTime() - startTime)
 
-proc recv*(socket: TSocket, data: pointer, size: int, timeout: int): int =
+proc recv*(socket: TSocket, data: pointer, size: int, timeout: int): int {.
+  tags: [FReadIO, FTime].} =
   ## overload with a ``timeout`` parameter in miliseconds.
   var waited = 0.0 # number of seconds already waited  
   
@@ -1031,7 +1038,7 @@ proc recv*(socket: TSocket, data: pointer, size: int, timeout: int): int =
   
   result = read
 
-proc peekChar(socket: TSocket, c: var char): int =
+proc peekChar(socket: TSocket, c: var char): int {.tags: [FReadIO].} =
   if socket.isBuffered:
     result = 1
     if socket.bufLen == 0 or socket.currPos > socket.bufLen-1:
@@ -1047,7 +1054,8 @@ proc peekChar(socket: TSocket, c: var char): int =
   
     result = recv(socket.fd, addr(c), 1, MSG_PEEK)
 
-proc recvLine*(socket: TSocket, line: var TaintedString): bool =
+proc recvLine*(socket: TSocket, line: var TaintedString): bool {.
+  tags: [FReadIO].} =
   ## retrieves a line from ``socket``. If a full line is received ``\r\L`` is not
   ## added to ``line``, however if solely ``\r\L`` is received then ``line``
   ## will be set to it.
@@ -1082,7 +1090,8 @@ proc recvLine*(socket: TSocket, line: var TaintedString): bool =
       return true
     add(line.string, c)
 
-proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool =
+proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool {.
+  tags: [FReadIO, FTime].} =
   ## variant with a ``timeout`` parameter, the timeout parameter specifies
   ## how many miliseconds to wait for data.
   template addNLIfEmpty(): stmt =
@@ -1111,7 +1120,8 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool =
       return true
     add(line.string, c)
 
-proc recvLineAsync*(socket: TSocket, line: var TaintedString): TRecvLineResult =
+proc recvLineAsync*(socket: TSocket, 
+  line: var TaintedString): TRecvLineResult {.tags: [FReadIO].} =
   ## similar to ``recvLine`` but for non-blocking sockets.
   ## The values of the returned enum should be pretty self explanatory:
   ## If a full line has been retrieved; ``RecvFullLine`` is returned.
@@ -1136,7 +1146,7 @@ proc recvLineAsync*(socket: TSocket, line: var TaintedString): TRecvLineResult =
     elif c == '\L': return RecvFullLine
     add(line.string, c)
 
-proc recv*(socket: TSocket): TaintedString =
+proc recv*(socket: TSocket): TaintedString {.tags: [FReadIO].} =
   ## receives all the available data from the socket.
   ## Socket errors will result in an ``EOS`` error.
   ## If socket is not a connectionless socket and socket is not connected
@@ -1165,7 +1175,8 @@ proc recv*(socket: TSocket): TaintedString =
       add(result.string, buf)
       if bytesRead != bufSize-1: break
 
-proc recvTimeout*(socket: TSocket, timeout: int): TaintedString =
+proc recvTimeout*(socket: TSocket, timeout: int): TaintedString {.
+  tags: [FReadIO].} =
   ## overloaded variant to support a ``timeout`` parameter, the ``timeout``
   ## parameter specifies the amount of miliseconds to wait for data on the
   ## socket.
@@ -1176,7 +1187,8 @@ proc recvTimeout*(socket: TSocket, timeout: int): TaintedString =
   
   return socket.recv
 
-proc recvAsync*(socket: TSocket, s: var TaintedString): bool =
+proc recvAsync*(socket: TSocket, s: var TaintedString): bool {.
+  tags: [FReadIO].} =
   ## receives all the data from a non-blocking socket. If socket is non-blocking 
   ## and there are no messages available, `False` will be returned.
   ## Other socket errors will result in an ``EOS`` error.
@@ -1226,7 +1238,8 @@ proc recvAsync*(socket: TSocket, s: var TaintedString): bool =
   result = True
 
 proc recvFrom*(socket: TSocket, data: var string, length: int,
-               address: var string, port: var TPort, flags = 0'i32): int =
+               address: var string, port: var TPort, flags = 0'i32): int {.
+               tags: [FReadIO].} =
   ## Receives data from ``socket``. This function should normally be used with
   ## connection-less sockets (UDP sockets).
   ##
@@ -1248,7 +1261,8 @@ proc recvFrom*(socket: TSocket, data: var string, length: int,
     port = ntohs(sockAddress.sin_port).TPort
 
 proc recvFromAsync*(socket: TSocket, data: var String, length: int,
-                    address: var string, port: var TPort, flags = 0'i32): bool =
+                    address: var string, port: var TPort, 
+                    flags = 0'i32): bool {.tags: [FReadIO].} =
   ## Similar to ``recvFrom`` but raises an EOS error when an error occurs and
   ## is also meant for non-blocking sockets.
   ## Returns False if no messages could be received from ``socket``.
@@ -1266,14 +1280,15 @@ proc recvFromAsync*(socket: TSocket, data: var String, length: int,
         return False
       else: OSError()
 
-proc skip*(socket: TSocket) =
+proc skip*(socket: TSocket) {.tags: [FReadIO].} =
   ## skips all the data that is pending for the socket
   const bufSize = 1000
   var buf = alloc(bufSize)
   while recv(socket, buf, bufSize) == bufSize: nil
   dealloc(buf)
 
-proc send*(socket: TSocket, data: pointer, size: int): int =
+proc send*(socket: TSocket, data: pointer, size: int): int {.
+  tags: [FWriteIO].} =
   ## sends data to a socket.
   when defined(ssl):
     if socket.isSSL:
@@ -1284,7 +1299,7 @@ proc send*(socket: TSocket, data: pointer, size: int): int =
   else:
     result = send(socket.fd, data, size, int32(MSG_NOSIGNAL))
 
-proc send*(socket: TSocket, data: string) =
+proc send*(socket: TSocket, data: string) {.tags: [FWriteIO].} =
   ## sends data to a socket.
   if send(socket, cstring(data), data.len) != data.len:
     when defined(ssl):
@@ -1293,7 +1308,7 @@ proc send*(socket: TSocket, data: string) =
     
     OSError()
 
-proc sendAsync*(socket: TSocket, data: string): bool =
+proc sendAsync*(socket: TSocket, data: string): bool {.tags: [FWriteIO].} =
   ## sends data to a non-blocking socket. Returns whether ``data`` was sent.
   result = true
   var bytesSent = send(socket, cstring(data), data.len)
@@ -1327,13 +1342,14 @@ proc sendAsync*(socket: TSocket, data: string): bool =
         return false
       else: OSError()
 
-proc trySend*(socket: TSocket, data: string): bool =
+proc trySend*(socket: TSocket, data: string): bool {.tags: [FWriteIO].} =
   ## safe alternative to ``send``. Does not raise an EOS when an error occurs,
   ## and instead returns ``false`` on failure.
   result = send(socket, cstring(data), data.len) == data.len
 
 proc sendTo*(socket: TSocket, address: string, port: TPort, data: pointer,
-             size: int, af: TDomain = AF_INET, flags = 0'i32): int =
+             size: int, af: TDomain = AF_INET, flags = 0'i32): int {.
+             tags: [FWriteIO].} =
   ## low-level sendTo proc. This proc sends ``data`` to the specified ``address``,
   ## which may be an IP address or a hostname, if a hostname is specified 
   ## this function will try each IP of that hostname.
@@ -1359,7 +1375,8 @@ proc sendTo*(socket: TSocket, address: string, port: TPort, data: pointer,
 
   freeaddrinfo(aiList)
 
-proc sendTo*(socket: TSocket, address: string, port: TPort, data: string): int =
+proc sendTo*(socket: TSocket, address: string, port: TPort, 
+             data: string): int {.tags: [FWriteIO].} =
   ## Friendlier version of the low-level ``sendTo``.
   result = socket.sendTo(address, port, cstring(data), data.len)
 
@@ -1391,7 +1408,7 @@ proc setBlocking*(s: TSocket, blocking: bool) =
         OSError()
 
 proc connect*(socket: TSocket, timeout: int, name: string, port = TPort(0),
-             af: TDomain = AF_INET) =
+             af: TDomain = AF_INET) {.tags: [FReadIO].} =
   ## Overload for ``connect`` to support timeouts. The ``timeout`` parameter 
   ## specifies the time in miliseconds of how long to wait for a connection
   ## to be made.
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 8e2d10a98..b0ce2454c 100755
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -131,7 +131,7 @@ type
     months*: int      ## The number of months
     years*: int       ## The number of years
 
-proc getTime*(): TTime ## gets the current calendar time
+proc getTime*(): TTime {.tags: [FTime].} ## gets the current calendar time
 proc getLocalTime*(t: TTime): TTimeInfo
   ## converts the calendar time `t` to broken-time representation,
   ## expressed relative to the user's specified time zone.
@@ -164,14 +164,14 @@ proc `<=` * (a, b: TTime): bool {.
   ## returns true iff ``a <= b``.
   result = a - b <= 0
 
-proc getTzname*(): tuple[nonDST, DST: string]
+proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime].}
   ## returns the local timezone; ``nonDST`` is the name of the local non-DST
   ## timezone, ``DST`` is the name of the local DST timezone.
 
-proc getTimezone*(): int
+proc getTimezone*(): int {.tags: [FTime].}
   ## returns the offset of the local (non-DST) timezone in seconds west of UTC.
 
-proc getStartMilsecs*(): int {.deprecated.}
+proc getStartMilsecs*(): int {.deprecated, tags: [FTime].}
   ## get the miliseconds from the start of the program. **Deprecated since
   ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
 
@@ -247,12 +247,12 @@ proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
     result = getLocalTime(TTime(float(t) - secs))
 
 when not defined(ECMAScript):  
-  proc epochTime*(): float {.rtl, extern: "nt$1".}
+  proc epochTime*(): float {.rtl, extern: "nt$1", tags: [FTime].}
     ## gets time after the UNIX epoch (1970) in seconds. It is a float
     ## because sub-second resolution is likely to be supported (depending 
     ## on the hardware/OS).
 
-  proc cpuTime*(): float {.rtl, extern: "nt$1".}
+  proc cpuTime*(): float {.rtl, extern: "nt$1", tags: [FTime].}
     ## gets time spent that the CPU spent to run the current process in
     ## seconds. This may be more useful for benchmarking than ``epochTime``.
     ## However, it may measure the real time instead (depending on the OS).
@@ -478,13 +478,13 @@ else:
     return int(getTime() - startMilsecs)
 
 
-proc getDateStr*(): string {.rtl, extern: "nt$1".} =
+proc getDateStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} =
   ## gets the current date as a string of the format ``YYYY-MM-DD``.
   var ti = getLocalTime(getTime())
   result = $ti.year & '-' & intToStr(ord(ti.month)+1, 2) &
     '-' & intToStr(ti.monthDay, 2)
 
-proc getClockStr*(): string {.rtl, extern: "nt$1".} =
+proc getClockStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} =
   ## gets the current clock time as a string of the format ``HH:MM:SS``.
   var ti = getLocalTime(getTime())
   result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) &