diff options
author | Miguel <leu-gim@moy-server.ru> | 2014-02-10 01:20:42 +0400 |
---|---|---|
committer | Miguel <leu-gim@moy-server.ru> | 2014-02-10 01:20:42 +0400 |
commit | eb9964fbbb9e1311edd72fcd6d47048db6178ed6 (patch) | |
tree | 402a1dcbfc2dd4bea122cd27d233ded67309c7ed /lib | |
parent | a8b4e3c764dd967e1ac90305a574c4cd5e0d019b (diff) | |
parent | e478374e0d16cf42051e753ccdd364aec13cf7d7 (diff) | |
download | Nim-eb9964fbbb9e1311edd72fcd6d47048db6178ed6.tar.gz |
Merge branch 'devel' of git://github.com/Araq/Nimrod
Diffstat (limited to 'lib')
37 files changed, 2306 insertions, 658 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 3b36e31e0..585ccf869 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -294,19 +294,6 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst".} ## if not `ex`: ## echo `info` & ": Check failed: " & `expString` -when not defined(booting): - template emit*(e: static[string]): stmt = - ## accepts a single string argument and treats it as nimrod code - ## that should be inserted verbatim in the program - ## Example: - ## - ## .. code-block:: nimrod - ## emit("echo " & '"' & "hello world".toUpper & '"') - ## - macro payload: stmt {.gensym.} = - result = e.parseStmt - payload() - proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} = ## checks that `n` is of kind `k`. If this is not the case, ## compilation aborts with an error message. This is useful for writing @@ -421,7 +408,8 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} = of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal) of nnkStrLit..nnkTripleStrLit: add(result, $n.strVal) of nnkIdent: add(result, "!\"" & $n.ident & '"') - of nnkSym, nnkNone: assert false + of nnkSym: add(result, $n.symbol) + of nnkNone: assert false else: add(result, lispRepr(n[0])) for j in 1..n.len-1: @@ -745,3 +733,15 @@ proc addIdentIfAbsent*(dest: PNimrodNode, ident: string) {.compiletime.} = else: discard dest.add(ident(ident)) +when not defined(booting): + template emit*(e: static[string]): stmt = + ## accepts a single string argument and treats it as nimrod code + ## that should be inserted verbatim in the program + ## Example: + ## + ## .. code-block:: nimrod + ## emit("echo " & '"' & "hello world".toUpper & '"') + ## + macro payload: stmt {.gensym.} = + result = parseStmt(e) + payload() diff --git a/lib/impure/db_mongo.nim b/lib/impure/db_mongo.nim index d012f677f..dc8a808f2 100644 --- a/lib/impure/db_mongo.nim +++ b/lib/impure/db_mongo.nim @@ -58,7 +58,7 @@ proc open*(host: string = defaultHost, port: int = defaultPort): TDbConn {. ## be established. init(result) - let x = connect(result, host, port.cint) + let x = client(result, host, port.cint) if x != 0'i32: dbError(result, "cannot open: " & host) @@ -119,7 +119,7 @@ proc insertId*(db: var TDbConn, namespace: string, data: PJsonNode): TOid {. ## the generated OID for the ``_id`` field. result = genOid() var x = jsonToBSon(data, result) - insert(db, namespace, x) + insert(db, namespace, x, nil) destroy(x) proc insert*(db: var TDbConn, namespace: string, data: PJsonNode) {. diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index a3499a6df..809ee7039 100644 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -148,7 +148,8 @@ proc getValue*(db: TDbConn, query: TSqlQuery, if finalize(stmt) != SQLITE_OK: dbError(db) proc tryInsertID*(db: TDbConn, query: TSqlQuery, - args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = + args: varargs[string, `$`]): int64 + {.tags: [FWriteDb], raises: [].} = ## executes the query (typically "INSERT") and returns the ## generated ID for the row or -1 in case of an error. var q = dbFormat(query, args) @@ -157,7 +158,8 @@ proc tryInsertID*(db: TDbConn, query: TSqlQuery, if prepare_v2(db, q, q.len.cint, stmt, nil) == SQLITE_OK: if step(stmt) == SQLITE_DONE: result = last_insert_rowid(db) - if finalize(stmt) != SQLITE_OK: dbError(db) + if finalize(stmt) != SQLITE_OK: + result = -1 proc insertID*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim index db7a63928..4ca0c79e0 100644 --- a/lib/packages/docutils/highlite.nim +++ b/lib/packages/docutils/highlite.nim @@ -19,7 +19,7 @@ type gtEof, gtNone, gtWhitespace, gtDecNumber, gtBinNumber, gtHexNumber, gtOctNumber, gtFloatNumber, gtIdentifier, gtKeyword, gtStringLit, gtLongStringLit, gtCharLit, gtEscapeSequence, # escape sequence like \xff - gtOperator, gtPunctation, gtComment, gtLongComment, gtRegularExpression, + gtOperator, gtPunctuation, gtComment, gtLongComment, gtRegularExpression, gtTagStart, gtTagEnd, gtKey, gtValue, gtRawData, gtAssembler, gtPreprocessor, gtDirective, gtCommand, gtRule, gtHyperlink, gtLabel, gtReference, gtOther @@ -39,7 +39,7 @@ const tokenClassToStr*: array[TTokenClass, string] = ["Eof", "None", "Whitespace", "DecNumber", "BinNumber", "HexNumber", "OctNumber", "FloatNumber", "Identifier", "Keyword", "StringLit", "LongStringLit", "CharLit", - "EscapeSequence", "Operator", "Punctation", "Comment", "LongComment", + "EscapeSequence", "Operator", "Punctuation", "Comment", "LongComment", "RegularExpression", "TagStart", "TagEnd", "Key", "Value", "RawData", "Assembler", "Preprocessor", "Directive", "Command", "Rule", "Hyperlink", "Label", "Reference", "Other"] @@ -258,7 +258,7 @@ proc nimNextToken(g: var TGeneralTokenizer) = else: inc(pos) of '(', ')', '[', ']', '{', '}', '`', ':', ',', ';': inc(pos) - g.kind = gtPunctation + g.kind = gtPunctuation of '\0': g.kind = gtEof else: @@ -473,7 +473,7 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openArray[string], else: inc(pos) of '(', ')', '[', ']', '{', '}', ':', ',', ';', '.': inc(pos) - g.kind = gtPunctation + g.kind = gtPunctuation of '\0': g.kind = gtEof else: diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim new file mode 100644 index 000000000..d50394f60 --- /dev/null +++ b/lib/posix/epoll.nim @@ -0,0 +1,88 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2013 Dominik Picheta +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +const + EPOLLIN* = 0x00000001 + EPOLLPRI* = 0x00000002 + EPOLLOUT* = 0x00000004 + EPOLLERR* = 0x00000008 + EPOLLHUP* = 0x00000010 + EPOLLRDNORM* = 0x00000040 + EPOLLRDBAND* = 0x00000080 + EPOLLWRNORM* = 0x00000100 + EPOLLWRBAND* = 0x00000200 + EPOLLMSG* = 0x00000400 + EPOLLRDHUP* = 0x00002000 + EPOLLWAKEUP* = 1 shl 29 + EPOLLONESHOT* = 1 shl 30 + EPOLLET* = 1 shl 31 + +# Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). + +const + EPOLL_CTL_ADD* = 1 # Add a file descriptor to the interface. + EPOLL_CTL_DEL* = 2 # Remove a file descriptor from the interface. + EPOLL_CTL_MOD* = 3 # Change file descriptor epoll_event structure. + +type + epoll_data* {.importc: "union epoll_data", + header: "<sys/epoll.h>", pure, final.} = object # TODO: This is actually a union. + thePtr* {.importc: "ptr".}: pointer # \ + #fd*: cint + #u32*: uint32 + #u64*: uint64 + + epoll_event* {.importc: "struct epoll_event", header: "<sys/epoll.h>", pure, final.} = object + events*: uint32 # Epoll events + data*: epoll_data # User data variable + +proc epoll_create*(size: cint): cint {.importc: "epoll_create", + header: "<sys/epoll.h>".} + ## Creates an epoll instance. Returns an fd for the new instance. + ## The "size" parameter is a hint specifying the number of file + ## descriptors to be associated with the new instance. The fd + ## returned by epoll_create() should be closed with close(). + +proc epoll_create1*(flags: cint): cint {.importc: "epoll_create1", + header: "<sys/epoll.h>".} + ## Same as epoll_create but with an FLAGS parameter. The unused SIZE + ## parameter has been dropped. + +proc epoll_ctl*(epfd: cint; op: cint; fd: cint; event: ptr epoll_event): cint {. + importc: "epoll_ctl", header: "<sys/epoll.h>".} + ## Manipulate an epoll instance "epfd". Returns 0 in case of success, + ## -1 in case of error ( the "errno" variable will contain the + ## specific error code ) The "op" parameter is one of the EPOLL_CTL_* + ## constants defined above. The "fd" parameter is the target of the + ## operation. The "event" parameter describes which events the caller + ## is interested in and any associated user data. + +proc epoll_wait*(epfd: cint; events: ptr epoll_event; maxevents: cint; + timeout: cint): cint {.importc: "epoll_wait", + header: "<sys/epoll.h>".} + ## Wait for events on an epoll instance "epfd". Returns the number of + ## triggered events returned in "events" buffer. Or -1 in case of + ## error with the "errno" variable set to the specific error code. The + ## "events" parameter is a buffer that will contain triggered + ## events. The "maxevents" is the maximum number of events to be + ## returned ( usually size of "events" ). The "timeout" parameter + ## specifies the maximum wait time in milliseconds (-1 == infinite). + ## + ## This function is a cancellation point and therefore not marked with + ## __THROW. + + +#proc epoll_pwait*(epfd: cint; events: ptr epoll_event; maxevents: cint; +# timeout: cint; ss: ptr sigset_t): cint {. +# importc: "epoll_pwait", header: "<sys/epoll.h>".} +# Same as epoll_wait, but the thread's signal mask is temporarily +# and atomically replaced with the one provided as parameter. +# +# This function is a cancellation point and therefore not marked with +# __THROW. diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index 685a1dafc..41260b36f 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -14,7 +14,7 @@ ## This is a raw POSIX interface module. It does not not provide any ## convenience: cstrings are used instead of proper Nimrod strings and -## return codes indicate errors. If you want exceptions +## return codes indicate errors. If you want exceptions ## and a proper Nimrod-like interface, use the OS module or write a wrapper. ## Coding conventions: @@ -63,74 +63,74 @@ const MM_NULLTXT* = nil MM_NULLACT* = nil MM_NULLTAG* = nil - + STDERR_FILENO* = 2 ## File number of stderr; STDIN_FILENO* = 0 ## File number of stdin; - STDOUT_FILENO* = 1 ## File number of stdout; + STDOUT_FILENO* = 1 ## File number of stdout; when defined(endb): # to not break bootstrapping again ... type - TDIR* {.importc: "DIR", header: "<dirent.h>", + TDIR* {.importc: "DIR", header: "<dirent.h>", final, pure, incompleteStruct.} = object - ## A type representing a directory stream. + ## A type representing a directory stream. else: type - TDIR* {.importc: "DIR", header: "<dirent.h>", + TDIR* {.importc: "DIR", header: "<dirent.h>", final, pure.} = object - ## A type representing a directory stream. - + ## A type representing a directory stream. + type TSocketHandle* = distinct cint # The type used to represent socket descriptors - Tdirent* {.importc: "struct dirent", + Tdirent* {.importc: "struct dirent", header: "<dirent.h>", final, pure.} = object ## dirent_t struct d_ino*: Tino ## File serial number. d_name*: array [0..255, char] ## Name of entry. Tflock* {.importc: "flock", final, pure, header: "<fcntl.h>".} = object ## flock type - l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. - l_whence*: cshort ## Flag for starting offset. - l_start*: TOff ## Relative offset in bytes. - l_len*: TOff ## Size; if 0 then until EOF. - l_pid*: TPid ## Process ID of the process holding the lock; - ## returned with F_GETLK. - - Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final, pure.} = + l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. + l_whence*: cshort ## Flag for starting offset. + l_start*: TOff ## Relative offset in bytes. + l_len*: TOff ## Size; if 0 then until EOF. + l_pid*: TPid ## Process ID of the process holding the lock; + ## returned with F_GETLK. + + Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final, pure.} = object ## Represents the entire floating-point environment. The ## floating-point environment refers collectively to any ## floating-point status flags and control modes supported ## by the implementation. - Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final, pure.} = - object ## Represents the floating-point status flags collectively, - ## including any status the implementation associates with the - ## flags. A floating-point status flag is a system variable + Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final, pure.} = + object ## Represents the floating-point status flags collectively, + ## including any status the implementation associates with the + ## flags. A floating-point status flag is a system variable ## whose value is set (but never cleared) when a floating-point ## exception is raised, which occurs as a side effect of ## exceptional floating-point arithmetic to provide auxiliary ## information. A floating-point control mode is a system variable - ## whose value may be set by the user to affect the subsequent + ## whose value may be set by the user to affect the subsequent ## behavior of floating-point arithmetic. TFTW* {.importc: "struct FTW", header: "<ftw.h>", final, pure.} = object base*: cint level*: cint - - TGlob* {.importc: "glob_t", header: "<glob.h>", + + TGlob* {.importc: "glob_t", header: "<glob.h>", final, pure.} = object ## glob_t - gl_pathc*: int ## Count of paths matched by pattern. - gl_pathv*: cstringArray ## Pointer to a list of matched pathnames. - gl_offs*: int ## Slots to reserve at the beginning of gl_pathv. - - TGroup* {.importc: "struct group", header: "<grp.h>", + gl_pathc*: int ## Count of paths matched by pattern. + gl_pathv*: cstringArray ## Pointer to a list of matched pathnames. + gl_offs*: int ## Slots to reserve at the beginning of gl_pathv. + + TGroup* {.importc: "struct group", header: "<grp.h>", final, pure.} = object ## struct group - gr_name*: cstring ## The name of the group. - gr_gid*: TGid ## Numerical group ID. - gr_mem*: cstringArray ## Pointer to a null-terminated array of character - ## pointers to member names. + gr_name*: cstring ## The name of the group. + gr_gid*: TGid ## Numerical group ID. + gr_mem*: cstringArray ## Pointer to a null-terminated array of character + ## pointers to member names. - Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final, pure.} = + Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final, pure.} = object ## Identifies the conversion from one codeset to another. Tlconv* {.importc: "struct lconv", header: "<locale.h>", final, @@ -161,21 +161,21 @@ type thousands_sep*: cstring TMqd* {.importc: "mqd_t", header: "<mqueue.h>", final, pure.} = object - TMqAttr* {.importc: "struct mq_attr", - header: "<mqueue.h>", + TMqAttr* {.importc: "struct mq_attr", + header: "<mqueue.h>", final, pure.} = object ## message queue attribute - mq_flags*: int ## Message queue flags. - mq_maxmsg*: int ## Maximum number of messages. - mq_msgsize*: int ## Maximum message size. - mq_curmsgs*: int ## Number of messages currently queued. + mq_flags*: int ## Message queue flags. + mq_maxmsg*: int ## Maximum number of messages. + mq_msgsize*: int ## Maximum message size. + mq_curmsgs*: int ## Number of messages currently queued. - TPasswd* {.importc: "struct passwd", header: "<pwd.h>", + TPasswd* {.importc: "struct passwd", header: "<pwd.h>", final, pure.} = object ## struct passwd - pw_name*: cstring ## User's login name. - pw_uid*: Tuid ## Numerical user ID. - pw_gid*: TGid ## Numerical group ID. - pw_dir*: cstring ## Initial working directory. - pw_shell*: cstring ## Program to use as shell. + pw_name*: cstring ## User's login name. + pw_uid*: Tuid ## Numerical user ID. + pw_gid*: TGid ## Numerical group ID. + pw_dir*: cstring ## Initial working directory. + pw_shell*: cstring ## Program to use as shell. Tblkcnt* {.importc: "blkcnt_t", header: "<sys/types.h>".} = int ## used for file block counts @@ -195,289 +195,289 @@ type TOff* {.importc: "off_t", header: "<sys/types.h>".} = int64 TPid* {.importc: "pid_t", header: "<sys/types.h>".} = int Tpthread_attr* {.importc: "pthread_attr_t", header: "<sys/types.h>".} = int - Tpthread_barrier* {.importc: "pthread_barrier_t", + Tpthread_barrier* {.importc: "pthread_barrier_t", header: "<sys/types.h>".} = int - Tpthread_barrierattr* {.importc: "pthread_barrierattr_t", + Tpthread_barrierattr* {.importc: "pthread_barrierattr_t", header: "<sys/types.h>".} = int Tpthread_cond* {.importc: "pthread_cond_t", header: "<sys/types.h>".} = int - Tpthread_condattr* {.importc: "pthread_condattr_t", + Tpthread_condattr* {.importc: "pthread_condattr_t", header: "<sys/types.h>".} = int Tpthread_key* {.importc: "pthread_key_t", header: "<sys/types.h>".} = int Tpthread_mutex* {.importc: "pthread_mutex_t", header: "<sys/types.h>".} = int - Tpthread_mutexattr* {.importc: "pthread_mutexattr_t", + Tpthread_mutexattr* {.importc: "pthread_mutexattr_t", header: "<sys/types.h>".} = int Tpthread_once* {.importc: "pthread_once_t", header: "<sys/types.h>".} = int - Tpthread_rwlock* {.importc: "pthread_rwlock_t", + Tpthread_rwlock* {.importc: "pthread_rwlock_t", header: "<sys/types.h>".} = int - Tpthread_rwlockattr* {.importc: "pthread_rwlockattr_t", + Tpthread_rwlockattr* {.importc: "pthread_rwlockattr_t", header: "<sys/types.h>".} = int - Tpthread_spinlock* {.importc: "pthread_spinlock_t", + Tpthread_spinlock* {.importc: "pthread_spinlock_t", header: "<sys/types.h>".} = int Tpthread* {.importc: "pthread_t", header: "<sys/types.h>".} = int Tsuseconds* {.importc: "suseconds_t", header: "<sys/types.h>".} = int #Ttime* {.importc: "time_t", header: "<sys/types.h>".} = int Ttimer* {.importc: "timer_t", header: "<sys/types.h>".} = int Ttrace_attr* {.importc: "trace_attr_t", header: "<sys/types.h>".} = int - Ttrace_event_id* {.importc: "trace_event_id_t", + Ttrace_event_id* {.importc: "trace_event_id_t", header: "<sys/types.h>".} = int - Ttrace_event_set* {.importc: "trace_event_set_t", + Ttrace_event_set* {.importc: "trace_event_set_t", header: "<sys/types.h>".} = int Ttrace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int Tuid* {.importc: "uid_t", header: "<sys/types.h>".} = int Tuseconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int - - Tutsname* {.importc: "struct utsname", - header: "<sys/utsname.h>", + + Tutsname* {.importc: "struct utsname", + header: "<sys/utsname.h>", final, pure.} = object ## struct utsname - sysname*, ## Name of this implementation of the operating system. - nodename*, ## Name of this node within the communications - ## network to which this node is attached, if any. - release*, ## Current release level of this implementation. - version*, ## Current version level of this release. + sysname*, ## Name of this implementation of the operating system. + nodename*, ## Name of this node within the communications + ## network to which this node is attached, if any. + release*, ## Current release level of this implementation. + version*, ## Current version level of this release. machine*: array [0..255, char] ## Name of the hardware type on which the - ## system is running. + ## system is running. TSem* {.importc: "sem_t", header: "<semaphore.h>", final, pure.} = object - Tipc_perm* {.importc: "struct ipc_perm", + Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>", final, pure.} = object ## struct ipc_perm - uid*: Tuid ## Owner's user ID. - gid*: TGid ## Owner's group ID. - cuid*: Tuid ## Creator's user ID. - cgid*: TGid ## Creator's group ID. - mode*: TMode ## Read/write permission. - - TStat* {.importc: "struct stat", + uid*: Tuid ## Owner's user ID. + gid*: TGid ## Owner's group ID. + cuid*: Tuid ## Creator's user ID. + cgid*: TGid ## Creator's group ID. + mode*: TMode ## Read/write permission. + + TStat* {.importc: "struct stat", header: "<sys/stat.h>", final, pure.} = object ## struct stat - st_dev*: TDev ## Device ID of device containing file. - st_ino*: Tino ## File serial number. - st_mode*: TMode ## Mode of file (see below). - st_nlink*: TNlink ## Number of hard links to the file. - st_uid*: Tuid ## User ID of file. - st_gid*: TGid ## Group ID of file. - st_rdev*: TDev ## Device ID (if file is character or block special). - st_size*: TOff ## For regular files, the file size in bytes. - ## For symbolic links, the length in bytes of the - ## pathname contained in the symbolic link. - ## For a shared memory object, the length in bytes. - ## For a typed memory object, the length in bytes. - ## For other file types, the use of this field is - ## unspecified. - st_atime*: TTime ## Time of last access. - st_mtime*: TTime ## Time of last data modification. - st_ctime*: TTime ## Time of last status change. - st_blksize*: Tblksize ## A file system-specific preferred I/O block size - ## for this object. In some file system types, this - ## may vary from file to file. - st_blocks*: Tblkcnt ## Number of blocks allocated for this object. - - - TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>", + st_dev*: TDev ## Device ID of device containing file. + st_ino*: Tino ## File serial number. + st_mode*: TMode ## Mode of file (see below). + st_nlink*: TNlink ## Number of hard links to the file. + st_uid*: Tuid ## User ID of file. + st_gid*: TGid ## Group ID of file. + st_rdev*: TDev ## Device ID (if file is character or block special). + st_size*: TOff ## For regular files, the file size in bytes. + ## For symbolic links, the length in bytes of the + ## pathname contained in the symbolic link. + ## For a shared memory object, the length in bytes. + ## For a typed memory object, the length in bytes. + ## For other file types, the use of this field is + ## unspecified. + st_atime*: TTime ## Time of last access. + st_mtime*: TTime ## Time of last data modification. + st_ctime*: TTime ## Time of last status change. + st_blksize*: Tblksize ## A file system-specific preferred I/O block size + ## for this object. In some file system types, this + ## may vary from file to file. + st_blocks*: Tblkcnt ## Number of blocks allocated for this object. + + + TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>", final, pure.} = object ## struct statvfs - f_bsize*: int ## File system block size. - f_frsize*: int ## Fundamental file system block size. + f_bsize*: int ## File system block size. + f_frsize*: int ## Fundamental file system block size. f_blocks*: Tfsblkcnt ## Total number of blocks on file system - ## in units of f_frsize. - f_bfree*: Tfsblkcnt ## Total number of free blocks. - f_bavail*: Tfsblkcnt ## Number of free blocks available to - ## non-privileged process. - f_files*: Tfsfilcnt ## Total number of file serial numbers. - f_ffree*: Tfsfilcnt ## Total number of free file serial numbers. - f_favail*: Tfsfilcnt ## Number of file serial numbers available to - ## non-privileged process. - f_fsid*: int ## File system ID. - f_flag*: int ## Bit mask of f_flag values. - f_namemax*: int ## Maximum filename length. - - Tposix_typed_mem_info* {.importc: "struct posix_typed_mem_info", + ## in units of f_frsize. + f_bfree*: Tfsblkcnt ## Total number of free blocks. + f_bavail*: Tfsblkcnt ## Number of free blocks available to + ## non-privileged process. + f_files*: Tfsfilcnt ## Total number of file serial numbers. + f_ffree*: Tfsfilcnt ## Total number of free file serial numbers. + f_favail*: Tfsfilcnt ## Number of file serial numbers available to + ## non-privileged process. + f_fsid*: int ## File system ID. + f_flag*: int ## Bit mask of f_flag values. + f_namemax*: int ## Maximum filename length. + + Tposix_typed_mem_info* {.importc: "struct posix_typed_mem_info", header: "<sys/mman.h>", final, pure.} = object posix_tmi_length*: int - - Ttm* {.importc: "struct tm", header: "<time.h>", + + Ttm* {.importc: "struct tm", header: "<time.h>", final, pure.} = object ## struct tm - tm_sec*: cint ## Seconds [0,60]. - tm_min*: cint ## Minutes [0,59]. - tm_hour*: cint ## Hour [0,23]. - tm_mday*: cint ## Day of month [1,31]. - tm_mon*: cint ## Month of year [0,11]. - tm_year*: cint ## Years since 1900. - tm_wday*: cint ## Day of week [0,6] (Sunday =0). - tm_yday*: cint ## Day of year [0,365]. - tm_isdst*: cint ## Daylight Savings flag. - Ttimespec* {.importc: "struct timespec", + tm_sec*: cint ## Seconds [0,60]. + tm_min*: cint ## Minutes [0,59]. + tm_hour*: cint ## Hour [0,23]. + tm_mday*: cint ## Day of month [1,31]. + tm_mon*: cint ## Month of year [0,11]. + tm_year*: cint ## Years since 1900. + tm_wday*: cint ## Day of week [0,6] (Sunday =0). + tm_yday*: cint ## Day of year [0,365]. + tm_isdst*: cint ## Daylight Savings flag. + Ttimespec* {.importc: "struct timespec", header: "<time.h>", final, pure.} = object ## struct timespec - tv_sec*: TTime ## Seconds. - tv_nsec*: int ## Nanoseconds. - titimerspec* {.importc: "struct itimerspec", header: "<time.h>", + tv_sec*: TTime ## Seconds. + tv_nsec*: int ## Nanoseconds. + titimerspec* {.importc: "struct itimerspec", header: "<time.h>", final, pure.} = object ## struct itimerspec - it_interval*: Ttimespec ## Timer period. - it_value*: Ttimespec ## Timer expiration. - + it_interval*: Ttimespec ## Timer period. + it_value*: Ttimespec ## Timer expiration. + Tsig_atomic* {.importc: "sig_atomic_t", header: "<signal.h>".} = cint - ## Possibly volatile-qualified integer type of an object that can be + ## Possibly volatile-qualified integer type of an object that can be ## accessed as an atomic entity, even in the presence of asynchronous ## interrupts. Tsigset* {.importc: "sigset_t", header: "<signal.h>", final, pure.} = object - - TsigEvent* {.importc: "struct sigevent", + + TsigEvent* {.importc: "struct sigevent", header: "<signal.h>", final, pure.} = object ## struct sigevent - sigev_notify*: cint ## Notification type. - sigev_signo*: cint ## Signal number. - sigev_value*: TsigVal ## Signal value. - sigev_notify_function*: proc (x: TsigVal) {.noconv.} ## Notification func. + sigev_notify*: cint ## Notification type. + sigev_signo*: cint ## Signal number. + sigev_value*: TsigVal ## Signal value. + sigev_notify_function*: proc (x: TsigVal) {.noconv.} ## Notification func. sigev_notify_attributes*: ptr Tpthread_attr ## Notification attributes. - TsigVal* {.importc: "union sigval", + TsigVal* {.importc: "union sigval", header: "<signal.h>", final, pure.} = object ## struct sigval - sival_ptr*: pointer ## pointer signal value; + sival_ptr*: pointer ## pointer signal value; ## integer signal value not defined! - TSigaction* {.importc: "struct sigaction", + TSigaction* {.importc: "struct sigaction", header: "<signal.h>", final, pure.} = object ## struct sigaction sa_handler*: proc (x: cint) {.noconv.} ## Pointer to a signal-catching - ## function or one of the macros - ## SIG_IGN or SIG_DFL. - sa_mask*: Tsigset ## Set of signals to be blocked during execution of - ## the signal handling function. - sa_flags*: cint ## Special flags. + ## function or one of the macros + ## SIG_IGN or SIG_DFL. + sa_mask*: Tsigset ## Set of signals to be blocked during execution of + ## the signal handling function. + sa_flags*: cint ## Special flags. sa_sigaction*: proc (x: cint, y: var TsigInfo, z: pointer) {.noconv.} TStack* {.importc: "stack_t", header: "<signal.h>", final, pure.} = object ## stack_t - ss_sp*: pointer ## Stack base or pointer. - ss_size*: int ## Stack size. - ss_flags*: cint ## Flags. + ss_sp*: pointer ## Stack base or pointer. + ss_size*: int ## Stack size. + ss_flags*: cint ## Flags. - TSigStack* {.importc: "struct sigstack", + TSigStack* {.importc: "struct sigstack", header: "<signal.h>", final, pure.} = object ## struct sigstack - ss_onstack*: cint ## Non-zero when signal stack is in use. - ss_sp*: pointer ## Signal stack pointer. + ss_onstack*: cint ## Non-zero when signal stack is in use. + ss_sp*: pointer ## Signal stack pointer. - TsigInfo* {.importc: "siginfo_t", + TsigInfo* {.importc: "siginfo_t", header: "<signal.h>", final, pure.} = object ## siginfo_t - si_signo*: cint ## Signal number. - si_code*: cint ## Signal code. - si_errno*: cint ## If non-zero, an errno value associated with - ## this signal, as defined in <errno.h>. - si_pid*: TPid ## Sending process ID. - si_uid*: Tuid ## Real user ID of sending process. - si_addr*: pointer ## Address of faulting instruction. - si_status*: cint ## Exit value or signal. - si_band*: int ## Band event for SIGPOLL. - si_value*: TsigVal ## Signal value. - + si_signo*: cint ## Signal number. + si_code*: cint ## Signal code. + si_errno*: cint ## If non-zero, an errno value associated with + ## this signal, as defined in <errno.h>. + si_pid*: TPid ## Sending process ID. + si_uid*: Tuid ## Real user ID of sending process. + si_addr*: pointer ## Address of faulting instruction. + si_status*: cint ## Exit value or signal. + si_band*: int ## Band event for SIGPOLL. + si_value*: TsigVal ## Signal value. + Tnl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint Tnl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = cint - Tsched_param* {.importc: "struct sched_param", - header: "<sched.h>", + Tsched_param* {.importc: "struct sched_param", + header: "<sched.h>", final, pure.} = object ## struct sched_param sched_priority*: cint - sched_ss_low_priority*: cint ## Low scheduling priority for - ## sporadic server. - sched_ss_repl_period*: Ttimespec ## Replenishment period for - ## sporadic server. - sched_ss_init_budget*: Ttimespec ## Initial budget for sporadic server. - sched_ss_max_repl*: cint ## Maximum pending replenishments for - ## sporadic server. - - Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>", + sched_ss_low_priority*: cint ## Low scheduling priority for + ## sporadic server. + sched_ss_repl_period*: Ttimespec ## Replenishment period for + ## sporadic server. + sched_ss_init_budget*: Ttimespec ## Initial budget for sporadic server. + sched_ss_max_repl*: cint ## Maximum pending replenishments for + ## sporadic server. + + Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>", final, pure.} = object ## struct timeval - tv_sec*: int ## Seconds. - tv_usec*: int ## Microseconds. - TFdSet* {.importc: "fd_set", header: "<sys/select.h>", + tv_sec*: int ## Seconds. + tv_usec*: int ## Microseconds. + TFdSet* {.importc: "fd_set", header: "<sys/select.h>", final, pure.} = object - Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", + Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", final, pure.} = object - Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>", + Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>", final, pure.} = object ## ucontext_t - uc_link*: ptr Tucontext ## Pointer to the context that is resumed - ## when this context returns. - uc_sigmask*: Tsigset ## The set of signals that are blocked when this - ## context is active. - uc_stack*: TStack ## The stack used by this context. - uc_mcontext*: Tmcontext ## A machine-specific representation of the saved - ## context. + uc_link*: ptr Tucontext ## Pointer to the context that is resumed + ## when this context returns. + uc_sigmask*: Tsigset ## The set of signals that are blocked when this + ## context is active. + uc_stack*: TStack ## The stack used by this context. + uc_mcontext*: Tmcontext ## A machine-specific representation of the saved + ## context. when hasAioH: type - Taiocb* {.importc: "struct aiocb", header: "<aio.h>", + Taiocb* {.importc: "struct aiocb", header: "<aio.h>", final, pure.} = object ## struct aiocb - aio_fildes*: cint ## File descriptor. - aio_offset*: TOff ## File offset. - aio_buf*: pointer ## Location of buffer. - aio_nbytes*: int ## Length of transfer. - aio_reqprio*: cint ## Request priority offset. - aio_sigevent*: TsigEvent ## Signal number and value. - aio_lio_opcode: cint ## Operation to be performed. - + aio_fildes*: cint ## File descriptor. + aio_offset*: TOff ## File offset. + aio_buf*: pointer ## Location of buffer. + aio_nbytes*: int ## Length of transfer. + aio_reqprio*: cint ## Request priority offset. + aio_sigevent*: TsigEvent ## Signal number and value. + aio_lio_opcode: cint ## Operation to be performed. + when hasSpawnH: type - Tposix_spawnattr* {.importc: "posix_spawnattr_t", + Tposix_spawnattr* {.importc: "posix_spawnattr_t", header: "<spawn.h>", final, pure.} = object - Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", + Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", header: "<spawn.h>", final, pure.} = object type TSocklen* {.importc: "socklen_t", header: "<sys/socket.h>".} = cuint TSa_Family* {.importc: "sa_family_t", header: "<sys/socket.h>".} = cint - - TSockAddr* {.importc: "struct sockaddr", header: "<sys/socket.h>", + + TSockAddr* {.importc: "struct sockaddr", header: "<sys/socket.h>", pure, final.} = object ## struct sockaddr - sa_family*: TSa_Family ## Address family. - sa_data*: array [0..255, char] ## Socket address (variable-length data). - + sa_family*: TSa_Family ## Address family. + sa_data*: array [0..255, char] ## Socket address (variable-length data). + Tsockaddr_storage* {.importc: "struct sockaddr_storage", - header: "<sys/socket.h>", + header: "<sys/socket.h>", pure, final.} = object ## struct sockaddr_storage - ss_family*: TSa_Family ## Address family. + ss_family*: TSa_Family ## Address family. - Tif_nameindex* {.importc: "struct if_nameindex", final, + Tif_nameindex* {.importc: "struct if_nameindex", final, pure, header: "<net/if.h>".} = object ## struct if_nameindex - if_index*: cint ## Numeric index of the interface. - if_name*: cstring ## Null-terminated name of the interface. + if_index*: cint ## Numeric index of the interface. + if_name*: cstring ## Null-terminated name of the interface. TIOVec* {.importc: "struct iovec", pure, final, header: "<sys/uio.h>".} = object ## struct iovec - iov_base*: pointer ## Base address of a memory region for input or output. - iov_len*: int ## The size of the memory pointed to by iov_base. - + iov_base*: pointer ## Base address of a memory region for input or output. + iov_len*: int ## The size of the memory pointed to by iov_base. + Tmsghdr* {.importc: "struct msghdr", pure, final, header: "<sys/socket.h>".} = object ## struct msghdr - msg_name*: pointer ## Optional address. - msg_namelen*: TSocklen ## Size of address. - msg_iov*: ptr TIOVec ## Scatter/gather array. - msg_iovlen*: cint ## Members in msg_iov. - msg_control*: pointer ## Ancillary data; see below. - msg_controllen*: TSocklen ## Ancillary data buffer len. - msg_flags*: cint ## Flags on received message. + msg_name*: pointer ## Optional address. + msg_namelen*: TSocklen ## Size of address. + msg_iov*: ptr TIOVec ## Scatter/gather array. + msg_iovlen*: cint ## Members in msg_iov. + msg_control*: pointer ## Ancillary data; see below. + msg_controllen*: TSocklen ## Ancillary data buffer len. + msg_flags*: cint ## Flags on received message. - Tcmsghdr* {.importc: "struct cmsghdr", pure, final, + Tcmsghdr* {.importc: "struct cmsghdr", pure, final, header: "<sys/socket.h>".} = object ## struct cmsghdr - cmsg_len*: TSocklen ## Data byte count, including the cmsghdr. - cmsg_level*: cint ## Originating protocol. - cmsg_type*: cint ## Protocol-specific type. + cmsg_len*: TSocklen ## Data byte count, including the cmsghdr. + cmsg_level*: cint ## Originating protocol. + cmsg_type*: cint ## Protocol-specific type. - TLinger* {.importc: "struct linger", pure, final, + TLinger* {.importc: "struct linger", pure, final, header: "<sys/socket.h>".} = object ## struct linger - l_onoff*: cint ## Indicates whether linger option is enabled. - l_linger*: cint ## Linger time, in seconds. - + l_onoff*: cint ## Indicates whether linger option is enabled. + l_linger*: cint ## Linger time, in seconds. + TInPort* = int16 ## unsigned! TInAddrScalar* = int32 ## unsigned! TInAddrT* {.importc: "in_addr_t", pure, final, header: "<netinet/in.h>".} = int32 ## unsigned! - TInAddr* {.importc: "struct in_addr", pure, final, + TInAddr* {.importc: "struct in_addr", pure, final, header: "<netinet/in.h>".} = object ## struct in_addr s_addr*: TInAddrScalar - Tsockaddr_in* {.importc: "struct sockaddr_in", pure, final, + Tsockaddr_in* {.importc: "struct sockaddr_in", pure, final, header: "<netinet/in.h>".} = object ## struct sockaddr_in - sin_family*: TSa_Family ## AF_INET. - sin_port*: TInPort ## Port number. - sin_addr*: TInAddr ## IP address. + sin_family*: TSa_Family ## AF_INET. + sin_port*: TInPort ## Port number. + sin_addr*: TInAddr ## IP address. TIn6Addr* {.importc: "struct in6_addr", pure, final, header: "<netinet/in.h>".} = object ## struct in6_addr @@ -485,75 +485,75 @@ type Tsockaddr_in6* {.importc: "struct sockaddr_in6", pure, final, header: "<netinet/in.h>".} = object ## struct sockaddr_in6 - sin6_family*: TSa_Family ## AF_INET6. - sin6_port*: TInPort ## Port number. - sin6_flowinfo*: int32 ## IPv6 traffic class and flow information. - sin6_addr*: TIn6Addr ## IPv6 address. - sin6_scope_id*: int32 ## Set of interfaces for a scope. - - Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final, + sin6_family*: TSa_Family ## AF_INET6. + sin6_port*: TInPort ## Port number. + sin6_flowinfo*: int32 ## IPv6 traffic class and flow information. + sin6_addr*: TIn6Addr ## IPv6 address. + sin6_scope_id*: int32 ## Set of interfaces for a scope. + + Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final, header: "<netinet/in.h>".} = object ## struct ipv6_mreq - ipv6mr_multiaddr*: TIn6Addr ## IPv6 multicast address. - ipv6mr_interface*: cint ## Interface index. + ipv6mr_multiaddr*: TIn6Addr ## IPv6 multicast address. + ipv6mr_interface*: cint ## Interface index. - Thostent* {.importc: "struct hostent", pure, final, + Thostent* {.importc: "struct hostent", pure, final, header: "<netdb.h>".} = object ## struct hostent - h_name*: cstring ## Official name of the host. - h_aliases*: cstringArray ## A pointer to an array of pointers to - ## alternative host names, terminated by a - ## null pointer. - h_addrtype*: cint ## Address type. - h_length*: cint ## The length, in bytes, of the address. - h_addr_list*: cstringArray ## A pointer to an array of pointers to network + h_name*: cstring ## Official name of the host. + h_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative host names, terminated by a + ## null pointer. + h_addrtype*: cint ## Address type. + h_length*: cint ## The length, in bytes, of the address. + h_addr_list*: cstringArray ## A pointer to an array of pointers to network ## addresses (in network byte order) for the - ## host, terminated by a null pointer. + ## host, terminated by a null pointer. - Tnetent* {.importc: "struct netent", pure, final, + Tnetent* {.importc: "struct netent", pure, final, header: "<netdb.h>".} = object ## struct netent - n_name*: cstring ## Official, fully-qualified (including the - ## domain) name of the host. - n_aliases*: cstringArray ## A pointer to an array of pointers to - ## alternative network names, terminated by a - ## null pointer. - n_addrtype*: cint ## The address type of the network. - n_net*: int32 ## The network number, in host byte order. - - TProtoent* {.importc: "struct protoent", pure, final, + n_name*: cstring ## Official, fully-qualified (including the + ## domain) name of the host. + n_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative network names, terminated by a + ## null pointer. + n_addrtype*: cint ## The address type of the network. + n_net*: int32 ## The network number, in host byte order. + + TProtoent* {.importc: "struct protoent", pure, final, header: "<netdb.h>".} = object ## struct protoent - p_name*: cstring ## Official name of the protocol. - p_aliases*: cstringArray ## A pointer to an array of pointers to - ## alternative protocol names, terminated by - ## a null pointer. - p_proto*: cint ## The protocol number. + p_name*: cstring ## Official name of the protocol. + p_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative protocol names, terminated by + ## a null pointer. + p_proto*: cint ## The protocol number. - TServent* {.importc: "struct servent", pure, final, + TServent* {.importc: "struct servent", pure, final, header: "<netdb.h>".} = object ## struct servent - s_name*: cstring ## Official name of the service. - s_aliases*: cstringArray ## A pointer to an array of pointers to - ## alternative service names, terminated by - ## a null pointer. - s_port*: cint ## The port number at which the service - ## resides, in network byte order. - s_proto*: cstring ## The name of the protocol to use when - ## contacting the service. - - Taddrinfo* {.importc: "struct addrinfo", pure, final, + s_name*: cstring ## Official name of the service. + s_aliases*: cstringArray ## A pointer to an array of pointers to + ## alternative service names, terminated by + ## a null pointer. + s_port*: cint ## The port number at which the service + ## resides, in network byte order. + s_proto*: cstring ## The name of the protocol to use when + ## contacting the service. + + Taddrinfo* {.importc: "struct addrinfo", pure, final, header: "<netdb.h>".} = object ## struct addrinfo - ai_flags*: cint ## Input flags. - ai_family*: cint ## Address family of socket. - ai_socktype*: cint ## Socket type. - ai_protocol*: cint ## Protocol of socket. - ai_addrlen*: TSocklen ## Length of socket address. - ai_addr*: ptr TSockAddr ## Socket address of socket. - ai_canonname*: cstring ## Canonical name of service location. - ai_next*: ptr Taddrinfo ## Pointer to next in list. - - TPollfd* {.importc: "struct pollfd", pure, final, + ai_flags*: cint ## Input flags. + ai_family*: cint ## Address family of socket. + ai_socktype*: cint ## Socket type. + ai_protocol*: cint ## Protocol of socket. + ai_addrlen*: TSocklen ## Length of socket address. + ai_addr*: ptr TSockAddr ## Socket address of socket. + ai_canonname*: cstring ## Canonical name of service location. + ai_next*: ptr Taddrinfo ## Pointer to next in list. + + TPollfd* {.importc: "struct pollfd", pure, final, header: "<poll.h>".} = object ## struct pollfd - fd*: cint ## The following descriptor being polled. - events*: cshort ## The input event flags (see below). - revents*: cshort ## The output event flags (see below). - + fd*: cint ## The following descriptor being polled. + events*: cshort ## The input event flags (see below). + revents*: cshort ## The output event flags (see below). + Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint var @@ -561,31 +561,31 @@ var h_errno* {.importc, header: "<netdb.h>".}: cint daylight* {.importc, header: "<time.h>".}: cint timezone* {.importc, header: "<time.h>".}: int - + # Constants as variables: when hasAioH: var AIO_ALLDONE* {.importc, header: "<aio.h>".}: cint - ## A return value indicating that none of the requested operations + ## A return value indicating that none of the requested operations ## could be canceled since they are already complete. AIO_CANCELED* {.importc, header: "<aio.h>".}: cint ## A return value indicating that all requested operations have ## been canceled. AIO_NOTCANCELED* {.importc, header: "<aio.h>".}: cint - ## A return value indicating that some of the requested operations could + ## A return value indicating that some of the requested operations could ## not be canceled since they are in progress. LIO_NOP* {.importc, header: "<aio.h>".}: cint ## A lio_listio() element operation option indicating that no transfer is ## requested. LIO_NOWAIT* {.importc, header: "<aio.h>".}: cint - ## A lio_listio() synchronization operation indicating that the calling - ## thread is to continue execution while the lio_listio() operation is + ## A lio_listio() synchronization operation indicating that the calling + ## thread is to continue execution while the lio_listio() operation is ## being performed, and no notification is given when the operation is ## complete. LIO_READ* {.importc, header: "<aio.h>".}: cint ## A lio_listio() element operation option requesting a read. LIO_WAIT* {.importc, header: "<aio.h>".}: cint - ## A lio_listio() synchronization operation indicating that the calling + ## A lio_listio() synchronization operation indicating that the calling ## thread is to suspend until the lio_listio() operation is complete. LIO_WRITE* {.importc, header: "<aio.h>".}: cint ## A lio_listio() element operation option requesting a write. @@ -598,9 +598,9 @@ var RTLD_GLOBAL* {.importc, header: "<dlfcn.h>".}: cint ## All symbols are available for relocation processing of other modules. RTLD_LOCAL* {.importc, header: "<dlfcn.h>".}: cint - ## All symbols are not made available for relocation processing by - ## other modules. - + ## All symbols are not made available for relocation processing by + ## other modules. + E2BIG* {.importc, header: "<errno.h>".}: cint ## Argument list too long. EACCES* {.importc, header: "<errno.h>".}: cint @@ -758,7 +758,7 @@ var EWOULDBLOCK* {.importc, header: "<errno.h>".}: cint ## Operation would block (may be the same value as [EAGAIN]). EXDEV* {.importc, header: "<errno.h>".}: cint - ## Cross-device link. + ## Cross-device link. F_DUPFD* {.importc, header: "<fcntl.h>".}: cint ## Duplicate file descriptor. @@ -779,15 +779,15 @@ var F_GETOWN* {.importc, header: "<fcntl.h>".}: cint ## Get process or process group ID to receive SIGURG signals. F_SETOWN* {.importc, header: "<fcntl.h>".}: cint - ## Set process or process group ID to receive SIGURG signals. + ## Set process or process group ID to receive SIGURG signals. FD_CLOEXEC* {.importc, header: "<fcntl.h>".}: cint - ## Close the file descriptor upon execution of an exec family function. + ## Close the file descriptor upon execution of an exec family function. F_RDLCK* {.importc, header: "<fcntl.h>".}: cint ## Shared or read lock. F_UNLCK* {.importc, header: "<fcntl.h>".}: cint ## Unlock. F_WRLCK* {.importc, header: "<fcntl.h>".}: cint - ## Exclusive or write lock. + ## Exclusive or write lock. O_CREAT* {.importc, header: "<fcntl.h>".}: cint ## Create file if it does not exist. O_EXCL* {.importc, header: "<fcntl.h>".}: cint @@ -795,7 +795,7 @@ var O_NOCTTY* {.importc, header: "<fcntl.h>".}: cint ## Do not assign controlling terminal. O_TRUNC* {.importc, header: "<fcntl.h>".}: cint - ## Truncate flag. + ## Truncate flag. O_APPEND* {.importc, header: "<fcntl.h>".}: cint ## Set append mode. O_DSYNC* {.importc, header: "<fcntl.h>".}: cint @@ -805,21 +805,21 @@ var O_RSYNC* {.importc, header: "<fcntl.h>".}: cint ## Synchronized read I/O operations. O_SYNC* {.importc, header: "<fcntl.h>".}: cint - ## Write according to synchronized I/O file integrity completion. + ## Write according to synchronized I/O file integrity completion. O_ACCMODE* {.importc, header: "<fcntl.h>".}: cint - ## Mask for file access modes. + ## Mask for file access modes. O_RDONLY* {.importc, header: "<fcntl.h>".}: cint ## Open for reading only. O_RDWR* {.importc, header: "<fcntl.h>".}: cint ## Open for reading and writing. O_WRONLY* {.importc, header: "<fcntl.h>".}: cint - ## Open for writing only. + ## Open for writing only. POSIX_FADV_NORMAL* {.importc, header: "<fcntl.h>".}: cint ## The application has no advice to give on its behavior with ## respect to the specified data. It is the default characteristic ## if no advice is given for an open file. POSIX_FADV_SEQUENTIAL* {.importc, header: "<fcntl.h>".}: cint - ## The application expects to access the specified data + ## The application expects to access the specified data # sequentially from lower offsets to higher offsets. POSIX_FADV_RANDOM* {.importc, header: "<fcntl.h>".}: cint ## The application expects to access the specified data in a random order. @@ -829,8 +829,8 @@ var ## The application expects that it will not access the specified data ## in the near future. POSIX_FADV_NOREUSE* {.importc, header: "<fcntl.h>".}: cint - ## The application expects to access the specified data once and - ## then not reuse it thereafter. + ## The application expects to access the specified data once and + ## then not reuse it thereafter. FE_DIVBYZERO* {.importc, header: "<fenv.h>".}: cint FE_INEXACT* {.importc, header: "<fenv.h>".}: cint @@ -875,20 +875,20 @@ when not defined(haiku): MM_PRINT* {.importc, header: "<fmtmsg.h>".}: cint ## Display message on standard error. MM_CONSOLE* {.importc, header: "<fmtmsg.h>".}: cint - ## Display message on system console. + ## Display message on system console. MM_OK* {.importc, header: "<fmtmsg.h>".}: cint ## The function succeeded. MM_NOTOK* {.importc, header: "<fmtmsg.h>".}: cint ## The function failed completely. MM_NOMSG* {.importc, header: "<fmtmsg.h>".}: cint - ## The function was unable to generate a message on standard error, + ## The function was unable to generate a message on standard error, ## but otherwise succeeded. MM_NOCON* {.importc, header: "<fmtmsg.h>".}: cint - ## The function was unable to generate a console message, but - ## otherwise succeeded. + ## The function was unable to generate a console message, but + ## otherwise succeeded. -var +var FNM_NOMATCH* {.importc, header: "<fnmatch.h>".}: cint ## The string does not match the specified pattern. FNM_PATHNAME* {.importc, header: "<fnmatch.h>".}: cint @@ -916,14 +916,14 @@ var ## Symbolic link that names a nonexistent file. FTW_PHYS* {.importc, header: "<ftw.h>".}: cint - ## Physical walk, does not follow symbolic links. Otherwise, nftw() + ## Physical walk, does not follow symbolic links. Otherwise, nftw() ## follows links but does not walk down any path that crosses itself. FTW_MOUNT* {.importc, header: "<ftw.h>".}: cint ## The walk does not cross a mount point. FTW_DEPTH* {.importc, header: "<ftw.h>".}: cint ## All subdirectories are visited before the directory itself. FTW_CHDIR* {.importc, header: "<ftw.h>".}: cint - ## The walk changes to each directory before reading it. + ## The walk changes to each directory before reading it. GLOB_APPEND* {.importc, header: "<glob.h>".}: cint ## Append generated pathnames to those previously obtained. @@ -932,7 +932,7 @@ var GLOB_ERR* {.importc, header: "<glob.h>".}: cint ## Cause glob() to return on error. GLOB_MARK* {.importc, header: "<glob.h>".}: cint - ## Each pathname that is a directory that matches pattern has a + ## Each pathname that is a directory that matches pattern has a ## slash appended. GLOB_NOCHECK* {.importc, header: "<glob.h>".}: cint ## If pattern does not match any pathname, then return a list @@ -942,10 +942,10 @@ var GLOB_NOSORT* {.importc, header: "<glob.h>".}: cint ## Do not sort the pathnames returned. GLOB_ABORTED* {.importc, header: "<glob.h>".}: cint - ## The scan was stopped because GLOB_ERR was set or errfunc() + ## The scan was stopped because GLOB_ERR was set or errfunc() ## returned non-zero. GLOB_NOMATCH* {.importc, header: "<glob.h>".}: cint - ## The pattern does not match any existing pathname, and GLOB_NOCHECK + ## The pattern does not match any existing pathname, and GLOB_NOCHECK ## was not set in flags. GLOB_NOSPACE* {.importc, header: "<glob.h>".}: cint ## An attempt to allocate memory failed. @@ -1033,10 +1033,10 @@ var NOEXPR* {.importc, header: "<langinfo.h>".}: cint ## Negative response expression. CRNCYSTR* {.importc, header: "<langinfo.h>".}: cint - ## Local currency symbol, preceded by '-' if the symbol - ## should appear before the value, '+' if the symbol should appear + ## Local currency symbol, preceded by '-' if the symbol + ## should appear before the value, '+' if the symbol should appear ## after the value, or '.' if the symbol should replace the radix - ## character. If the local currency symbol is the empty string, + ## character. If the local currency symbol is the empty string, ## implementations may return the empty string ( "" ). LC_ALL* {.importc, header: "<locale.h>".}: cint @@ -1046,7 +1046,7 @@ var LC_MONETARY* {.importc, header: "<locale.h>".}: cint LC_NUMERIC* {.importc, header: "<locale.h>".}: cint LC_TIME* {.importc, header: "<locale.h>".}: cint - + PTHREAD_BARRIER_SERIAL_THREAD* {.importc, header: "<pthread.h>".}: cint PTHREAD_CANCEL_ASYNCHRONOUS* {.importc, header: "<pthread.h>".}: cint PTHREAD_CANCEL_ENABLE* {.importc, header: "<pthread.h>".}: cint @@ -1115,7 +1115,7 @@ var PC_ALLOC_SIZE_MIN* {.importc: "_PC_ALLOC_SIZE_MIN", header: "<unistd.h>".}: cint PC_ASYNC_IO* {.importc: "_PC_ASYNC_IO", header: "<unistd.h>".}: cint - PC_CHOWN_RESTRICTED* {.importc: "_PC_CHOWN_RESTRICTED", + PC_CHOWN_RESTRICTED* {.importc: "_PC_CHOWN_RESTRICTED", header: "<unistd.h>".}: cint PC_FILESIZEBITS* {.importc: "_PC_FILESIZEBITS", header: "<unistd.h>".}: cint PC_LINK_MAX* {.importc: "_PC_LINK_MAX", header: "<unistd.h>".}: cint @@ -1127,9 +1127,9 @@ var PC_PATH_MAX*{.importc: "_PC_PATH_MAX", header: "<unistd.h>".}: cint PC_PIPE_BUF*{.importc: "_PC_PIPE_BUF", header: "<unistd.h>".}: cint PC_PRIO_IO*{.importc: "_PC_PRIO_IO", header: "<unistd.h>".}: cint - PC_REC_INCR_XFER_SIZE*{.importc: "_PC_REC_INCR_XFER_SIZE", + PC_REC_INCR_XFER_SIZE*{.importc: "_PC_REC_INCR_XFER_SIZE", header: "<unistd.h>".}: cint - PC_REC_MIN_XFER_SIZE*{.importc: "_PC_REC_MIN_XFER_SIZE", + PC_REC_MIN_XFER_SIZE*{.importc: "_PC_REC_MIN_XFER_SIZE", header: "<unistd.h>".}: cint PC_REC_XFER_ALIGN*{.importc: "_PC_REC_XFER_ALIGN", header: "<unistd.h>".}: cint PC_SYMLINK_MAX*{.importc: "_PC_SYMLINK_MAX", header: "<unistd.h>".}: cint @@ -1142,9 +1142,9 @@ var SC_2_FORT_RUN*{.importc: "_SC_2_FORT_RUN", header: "<unistd.h>".}: cint SC_2_LOCALEDEF*{.importc: "_SC_2_LOCALEDEF", header: "<unistd.h>".}: cint SC_2_PBS*{.importc: "_SC_2_PBS", header: "<unistd.h>".}: cint - SC_2_PBS_ACCOUNTING*{.importc: "_SC_2_PBS_ACCOUNTING", + SC_2_PBS_ACCOUNTING*{.importc: "_SC_2_PBS_ACCOUNTING", header: "<unistd.h>".}: cint - SC_2_PBS_CHECKPOINT*{.importc: "_SC_2_PBS_CHECKPOINT", + SC_2_PBS_CHECKPOINT*{.importc: "_SC_2_PBS_CHECKPOINT", header: "<unistd.h>".}: cint SC_2_PBS_LOCATE*{.importc: "_SC_2_PBS_LOCATE", header: "<unistd.h>".}: cint SC_2_PBS_MESSAGE*{.importc: "_SC_2_PBS_MESSAGE", header: "<unistd.h>".}: cint @@ -1155,10 +1155,10 @@ var SC_ADVISORY_INFO*{.importc: "_SC_ADVISORY_INFO", header: "<unistd.h>".}: cint SC_AIO_LISTIO_MAX*{.importc: "_SC_AIO_LISTIO_MAX", header: "<unistd.h>".}: cint SC_AIO_MAX*{.importc: "_SC_AIO_MAX", header: "<unistd.h>".}: cint - SC_AIO_PRIO_DELTA_MAX*{.importc: "_SC_AIO_PRIO_DELTA_MAX", + SC_AIO_PRIO_DELTA_MAX*{.importc: "_SC_AIO_PRIO_DELTA_MAX", header: "<unistd.h>".}: cint SC_ARG_MAX*{.importc: "_SC_ARG_MAX", header: "<unistd.h>".}: cint - SC_ASYNCHRONOUS_IO*{.importc: "_SC_ASYNCHRONOUS_IO", + SC_ASYNCHRONOUS_IO*{.importc: "_SC_ASYNCHRONOUS_IO", header: "<unistd.h>".}: cint SC_ATEXIT_MAX*{.importc: "_SC_ATEXIT_MAX", header: "<unistd.h>".}: cint SC_BARRIERS*{.importc: "_SC_BARRIERS", header: "<unistd.h>".}: cint @@ -1168,17 +1168,17 @@ var SC_BC_STRING_MAX*{.importc: "_SC_BC_STRING_MAX", header: "<unistd.h>".}: cint SC_CHILD_MAX*{.importc: "_SC_CHILD_MAX", header: "<unistd.h>".}: cint SC_CLK_TCK*{.importc: "_SC_CLK_TCK", header: "<unistd.h>".}: cint - SC_CLOCK_SELECTION*{.importc: "_SC_CLOCK_SELECTION", + SC_CLOCK_SELECTION*{.importc: "_SC_CLOCK_SELECTION", header: "<unistd.h>".}: cint - SC_COLL_WEIGHTS_MAX*{.importc: "_SC_COLL_WEIGHTS_MAX", + SC_COLL_WEIGHTS_MAX*{.importc: "_SC_COLL_WEIGHTS_MAX", header: "<unistd.h>".}: cint SC_CPUTIME*{.importc: "_SC_CPUTIME", header: "<unistd.h>".}: cint SC_DELAYTIMER_MAX*{.importc: "_SC_DELAYTIMER_MAX", header: "<unistd.h>".}: cint SC_EXPR_NEST_MAX*{.importc: "_SC_EXPR_NEST_MAX", header: "<unistd.h>".}: cint SC_FSYNC*{.importc: "_SC_FSYNC", header: "<unistd.h>".}: cint - SC_GETGR_R_SIZE_MAX*{.importc: "_SC_GETGR_R_SIZE_MAX", + SC_GETGR_R_SIZE_MAX*{.importc: "_SC_GETGR_R_SIZE_MAX", header: "<unistd.h>".}: cint - SC_GETPW_R_SIZE_MAX*{.importc: "_SC_GETPW_R_SIZE_MAX", + SC_GETPW_R_SIZE_MAX*{.importc: "_SC_GETPW_R_SIZE_MAX", header: "<unistd.h>".}: cint SC_HOST_NAME_MAX*{.importc: "_SC_HOST_NAME_MAX", header: "<unistd.h>".}: cint SC_IOV_MAX*{.importc: "_SC_IOV_MAX", header: "<unistd.h>".}: cint @@ -1189,11 +1189,11 @@ var SC_MAPPED_FILES*{.importc: "_SC_MAPPED_FILES", header: "<unistd.h>".}: cint SC_MEMLOCK*{.importc: "_SC_MEMLOCK", header: "<unistd.h>".}: cint SC_MEMLOCK_RANGE*{.importc: "_SC_MEMLOCK_RANGE", header: "<unistd.h>".}: cint - SC_MEMORY_PROTECTION*{.importc: "_SC_MEMORY_PROTECTION", + SC_MEMORY_PROTECTION*{.importc: "_SC_MEMORY_PROTECTION", header: "<unistd.h>".}: cint - SC_MESSAGE_PASSING*{.importc: "_SC_MESSAGE_PASSING", + SC_MESSAGE_PASSING*{.importc: "_SC_MESSAGE_PASSING", header: "<unistd.h>".}: cint - SC_MONOTONIC_CLOCK*{.importc: "_SC_MONOTONIC_CLOCK", + SC_MONOTONIC_CLOCK*{.importc: "_SC_MONOTONIC_CLOCK", header: "<unistd.h>".}: cint SC_MQ_OPEN_MAX*{.importc: "_SC_MQ_OPEN_MAX", header: "<unistd.h>".}: cint SC_MQ_PRIO_MAX*{.importc: "_SC_MQ_PRIO_MAX", header: "<unistd.h>".}: cint @@ -1201,13 +1201,13 @@ var SC_OPEN_MAX*{.importc: "_SC_OPEN_MAX", header: "<unistd.h>".}: cint SC_PAGE_SIZE*{.importc: "_SC_PAGE_SIZE", header: "<unistd.h>".}: cint SC_PRIORITIZED_IO*{.importc: "_SC_PRIORITIZED_IO", header: "<unistd.h>".}: cint - SC_PRIORITY_SCHEDULING*{.importc: "_SC_PRIORITY_SCHEDULING", + SC_PRIORITY_SCHEDULING*{.importc: "_SC_PRIORITY_SCHEDULING", header: "<unistd.h>".}: cint SC_RAW_SOCKETS*{.importc: "_SC_RAW_SOCKETS", header: "<unistd.h>".}: cint SC_RE_DUP_MAX*{.importc: "_SC_RE_DUP_MAX", header: "<unistd.h>".}: cint - SC_READER_WRITER_LOCKS*{.importc: "_SC_READER_WRITER_LOCKS", + SC_READER_WRITER_LOCKS*{.importc: "_SC_READER_WRITER_LOCKS", header: "<unistd.h>".}: cint - SC_REALTIME_SIGNALS*{.importc: "_SC_REALTIME_SIGNALS", + SC_REALTIME_SIGNALS*{.importc: "_SC_REALTIME_SIGNALS", header: "<unistd.h>".}: cint SC_REGEXP*{.importc: "_SC_REGEXP", header: "<unistd.h>".}: cint SC_RTSIG_MAX*{.importc: "_SC_RTSIG_MAX", header: "<unistd.h>".}: cint @@ -1215,43 +1215,43 @@ var SC_SEM_NSEMS_MAX*{.importc: "_SC_SEM_NSEMS_MAX", header: "<unistd.h>".}: cint SC_SEM_VALUE_MAX*{.importc: "_SC_SEM_VALUE_MAX", header: "<unistd.h>".}: cint SC_SEMAPHORES*{.importc: "_SC_SEMAPHORES", header: "<unistd.h>".}: cint - SC_SHARED_MEMORY_OBJECTS*{.importc: "_SC_SHARED_MEMORY_OBJECTS", + SC_SHARED_MEMORY_OBJECTS*{.importc: "_SC_SHARED_MEMORY_OBJECTS", header: "<unistd.h>".}: cint SC_SHELL*{.importc: "_SC_SHELL", header: "<unistd.h>".}: cint SC_SIGQUEUE_MAX*{.importc: "_SC_SIGQUEUE_MAX", header: "<unistd.h>".}: cint SC_SPAWN*{.importc: "_SC_SPAWN", header: "<unistd.h>".}: cint SC_SPIN_LOCKS*{.importc: "_SC_SPIN_LOCKS", header: "<unistd.h>".}: cint - SC_SPORADIC_SERVER*{.importc: "_SC_SPORADIC_SERVER", + SC_SPORADIC_SERVER*{.importc: "_SC_SPORADIC_SERVER", header: "<unistd.h>".}: cint SC_SS_REPL_MAX*{.importc: "_SC_SS_REPL_MAX", header: "<unistd.h>".}: cint SC_STREAM_MAX*{.importc: "_SC_STREAM_MAX", header: "<unistd.h>".}: cint SC_SYMLOOP_MAX*{.importc: "_SC_SYMLOOP_MAX", header: "<unistd.h>".}: cint - SC_SYNCHRONIZED_IO*{.importc: "_SC_SYNCHRONIZED_IO", + SC_SYNCHRONIZED_IO*{.importc: "_SC_SYNCHRONIZED_IO", header: "<unistd.h>".}: cint - SC_THREAD_ATTR_STACKADDR*{.importc: "_SC_THREAD_ATTR_STACKADDR", + SC_THREAD_ATTR_STACKADDR*{.importc: "_SC_THREAD_ATTR_STACKADDR", header: "<unistd.h>".}: cint - SC_THREAD_ATTR_STACKSIZE*{.importc: "_SC_THREAD_ATTR_STACKSIZE", + SC_THREAD_ATTR_STACKSIZE*{.importc: "_SC_THREAD_ATTR_STACKSIZE", header: "<unistd.h>".}: cint SC_THREAD_CPUTIME*{.importc: "_SC_THREAD_CPUTIME", header: "<unistd.h>".}: cint SC_THREAD_DESTRUCTOR_ITERATIONS*{.importc: "_SC_THREAD_DESTRUCTOR_ITERATIONS", header: "<unistd.h>".}: cint - SC_THREAD_KEYS_MAX*{.importc: "_SC_THREAD_KEYS_MAX", + SC_THREAD_KEYS_MAX*{.importc: "_SC_THREAD_KEYS_MAX", header: "<unistd.h>".}: cint - SC_THREAD_PRIO_INHERIT*{.importc: "_SC_THREAD_PRIO_INHERIT", + SC_THREAD_PRIO_INHERIT*{.importc: "_SC_THREAD_PRIO_INHERIT", header: "<unistd.h>".}: cint - SC_THREAD_PRIO_PROTECT*{.importc: "_SC_THREAD_PRIO_PROTECT", + SC_THREAD_PRIO_PROTECT*{.importc: "_SC_THREAD_PRIO_PROTECT", header: "<unistd.h>".}: cint SC_THREAD_PRIORITY_SCHEDULING*{.importc: "_SC_THREAD_PRIORITY_SCHEDULING", header: "<unistd.h>".}: cint - SC_THREAD_PROCESS_SHARED*{.importc: "_SC_THREAD_PROCESS_SHARED", + SC_THREAD_PROCESS_SHARED*{.importc: "_SC_THREAD_PROCESS_SHARED", header: "<unistd.h>".}: cint - SC_THREAD_SAFE_FUNCTIONS*{.importc: "_SC_THREAD_SAFE_FUNCTIONS", + SC_THREAD_SAFE_FUNCTIONS*{.importc: "_SC_THREAD_SAFE_FUNCTIONS", header: "<unistd.h>".}: cint - SC_THREAD_SPORADIC_SERVER*{.importc: "_SC_THREAD_SPORADIC_SERVER", + SC_THREAD_SPORADIC_SERVER*{.importc: "_SC_THREAD_SPORADIC_SERVER", header: "<unistd.h>".}: cint - SC_THREAD_STACK_MIN*{.importc: "_SC_THREAD_STACK_MIN", + SC_THREAD_STACK_MIN*{.importc: "_SC_THREAD_STACK_MIN", header: "<unistd.h>".}: cint - SC_THREAD_THREADS_MAX*{.importc: "_SC_THREAD_THREADS_MAX", + SC_THREAD_THREADS_MAX*{.importc: "_SC_THREAD_THREADS_MAX", header: "<unistd.h>".}: cint SC_THREADS*{.importc: "_SC_THREADS", header: "<unistd.h>".}: cint SC_TIMEOUTS*{.importc: "_SC_TIMEOUTS", header: "<unistd.h>".}: cint @@ -1276,21 +1276,21 @@ var SC_XBS5_ILP32_OFF32*{.importc: "_SC_XBS5_ILP32_OFF32", header: "<unistd.h>".}: cint SC_XBS5_ILP32_OFFBIG*{.importc: "_SC_XBS5_ILP32_OFFBIG", header: "<unistd.h>".}: cint SC_XBS5_LP64_OFF64*{.importc: "_SC_XBS5_LP64_OFF64", header: "<unistd.h>".}: cint - SC_XBS5_LPBIG_OFFBIG*{.importc: "_SC_XBS5_LPBIG_OFFBIG", + SC_XBS5_LPBIG_OFFBIG*{.importc: "_SC_XBS5_LPBIG_OFFBIG", header: "<unistd.h>".}: cint SC_XOPEN_CRYPT*{.importc: "_SC_XOPEN_CRYPT", header: "<unistd.h>".}: cint SC_XOPEN_ENH_I18N*{.importc: "_SC_XOPEN_ENH_I18N", header: "<unistd.h>".}: cint SC_XOPEN_LEGACY*{.importc: "_SC_XOPEN_LEGACY", header: "<unistd.h>".}: cint SC_XOPEN_REALTIME*{.importc: "_SC_XOPEN_REALTIME", header: "<unistd.h>".}: cint - SC_XOPEN_REALTIME_THREADS*{.importc: "_SC_XOPEN_REALTIME_THREADS", + SC_XOPEN_REALTIME_THREADS*{.importc: "_SC_XOPEN_REALTIME_THREADS", header: "<unistd.h>".}: cint SC_XOPEN_SHM*{.importc: "_SC_XOPEN_SHM", header: "<unistd.h>".}: cint SC_XOPEN_STREAMS*{.importc: "_SC_XOPEN_STREAMS", header: "<unistd.h>".}: cint SC_XOPEN_UNIX*{.importc: "_SC_XOPEN_UNIX", header: "<unistd.h>".}: cint SC_XOPEN_VERSION*{.importc: "_SC_XOPEN_VERSION", header: "<unistd.h>".}: cint - SC_NPROCESSORS_ONLN*{.importc: "_SC_NPROCESSORS_ONLN", + SC_NPROCESSORS_ONLN*{.importc: "_SC_NPROCESSORS_ONLN", header: "<unistd.h>".}: cint - + SEM_FAILED* {.importc, header: "<semaphore.h>".}: pointer IPC_CREAT* {.importc, header: "<sys/ipc.h>".}: cint ## Create entry if key does not exist. @@ -1307,7 +1307,7 @@ var IPC_SET* {.importc, header: "<sys/ipc.h>".}: cint ## Set options. IPC_STAT* {.importc, header: "<sys/ipc.h>".}: cint - ## Get options. + ## Get options. S_IFMT* {.importc, header: "<sys/stat.h>".}: cint ## Type of file. @@ -1355,12 +1355,12 @@ var ## Set-group-ID on execution. S_ISVTX* {.importc, header: "<sys/stat.h>".}: cint ## On directories, restricted deletion flag. - + ST_RDONLY* {.importc, header: "<sys/statvfs.h>".}: cint ## Read-only file system. ST_NOSUID* {.importc, header: "<sys/statvfs.h>".}: cint ## Does not support the semantics of the ST_ISUID and ST_ISGID file mode bits. - + PROT_READ* {.importc, header: "<sys/mman.h>".}: cint ## Page can be read. PROT_WRITE* {.importc, header: "<sys/mman.h>".}: cint @@ -1387,8 +1387,8 @@ var ## Lock pages that become mapped. MAP_FAILED* {.importc, header: "<sys/mman.h>".}: cint POSIX_MADV_NORMAL* {.importc, header: "<sys/mman.h>".}: cint - ## The application has no advice to give on its behavior with - ## respect to the specified range. It is the default characteristic + ## The application has no advice to give on its behavior with + ## respect to the specified range. It is the default characteristic ## if no advice is given for a range of memory. POSIX_MADV_SEQUENTIAL* {.importc, header: "<sys/mman.h>".}: cint ## The application expects to access the specified range sequentially @@ -1407,13 +1407,13 @@ var ## A number used to convert the value returned by the clock() function ## into seconds. CLOCK_PROCESS_CPUTIME_ID* {.importc, header: "<time.h>".}: cint - ## The identifier of the CPU-time clock associated with the process + ## The identifier of the CPU-time clock associated with the process ## making a clock() or timer*() function call. CLOCK_THREAD_CPUTIME_ID* {.importc, header: "<time.h>".}: cint CLOCK_REALTIME* {.importc, header: "<time.h>".}: cint ## The identifier of the system-wide realtime clock. TIMER_ABSTIME* {.importc, header: "<time.h>".}: cint - ## Flag indicating time is absolute. For functions taking timer + ## Flag indicating time is absolute. For functions taking timer ## objects, this refers to the clock associated with the timer. CLOCK_MONOTONIC* {.importc, header: "<time.h>".}: cint @@ -1438,25 +1438,25 @@ var WEXITED* {.importc, header: "<sys/wait.h>".}: cint ## Wait for processes that have exited. WSTOPPED* {.importc, header: "<sys/wait.h>".}: cint - ## Status is returned for any child that has stopped upon receipt + ## Status is returned for any child that has stopped upon receipt ## of a signal. WCONTINUED* {.importc, header: "<sys/wait.h>".}: cint ## Status is returned for any child that was stopped and has been continued. WNOWAIT* {.importc, header: "<sys/wait.h>".}: cint - ## Keep the process whose status is returned in infop in a waitable state. - P_ALL* {.importc, header: "<sys/wait.h>".}: cint - P_PID* {.importc, header: "<sys/wait.h>".}: cint + ## Keep the process whose status is returned in infop in a waitable state. + P_ALL* {.importc, header: "<sys/wait.h>".}: cint + P_PID* {.importc, header: "<sys/wait.h>".}: cint P_PGID* {.importc, header: "<sys/wait.h>".}: cint - + SIG_DFL* {.importc, header: "<signal.h>".}: proc (x: cint) {.noconv.} ## Request for default signal handling. SIG_ERR* {.importc, header: "<signal.h>".}: proc (x: cint) {.noconv.} ## Return value from signal() in case of error. - cSIG_HOLD* {.importc: "SIG_HOLD", + cSIG_HOLD* {.importc: "SIG_HOLD", header: "<signal.h>".}: proc (x: cint) {.noconv.} ## Request that signal be held. SIG_IGN* {.importc, header: "<signal.h>".}: proc (x: cint) {.noconv.} - ## Request that signal be ignored. + ## Request that signal be ignored. SIGEV_NONE* {.importc, header: "<signal.h>".}: cint SIGEV_SIGNAL* {.importc, header: "<signal.h>".}: cint @@ -1518,8 +1518,8 @@ var SEEK_END* {.importc, header: "<unistd.h>".}: cint SCM_RIGHTS* {.importc, header: "<sys/socket.h>".}: cint - ## Indicates that the data array contains the access rights - ## to be sent or received. + ## Indicates that the data array contains the access rights + ## to be sent or received. SOCK_DGRAM* {.importc, header: "<sys/socket.h>".}: cint ## Datagram socket. SOCK_RAW* {.importc, header: "<sys/socket.h>".}: cint @@ -1527,11 +1527,11 @@ var SOCK_SEQPACKET* {.importc, header: "<sys/socket.h>".}: cint ## Sequenced-packet socket. SOCK_STREAM* {.importc, header: "<sys/socket.h>".}: cint - ## Byte-stream socket. - + ## Byte-stream socket. + SOL_SOCKET* {.importc, header: "<sys/socket.h>".}: cint - ## Options to be accessed at socket level, not protocol level. - + ## Options to be accessed at socket level, not protocol level. + SO_ACCEPTCONN* {.importc, header: "<sys/socket.h>".}: cint ## Socket is accepting connections. SO_BROADCAST* {.importc, header: "<sys/socket.h>".}: cint @@ -1563,11 +1563,11 @@ var SO_SNDTIMEO* {.importc, header: "<sys/socket.h>".}: cint ## Send timeout. SO_TYPE* {.importc, header: "<sys/socket.h>".}: cint - ## Socket type. - + ## Socket type. + SOMAXCONN* {.importc, header: "<sys/socket.h>".}: cint - ## The maximum backlog queue length. - + ## The maximum backlog queue length. + MSG_CTRUNC* {.importc, header: "<sys/socket.h>".}: cint ## Control data truncated. MSG_DONTROUTE* {.importc, header: "<sys/socket.h>".}: cint @@ -1583,7 +1583,7 @@ var MSG_TRUNC* {.importc, header: "<sys/socket.h>".}: cint ## Normal data truncated. MSG_WAITALL* {.importc, header: "<sys/socket.h>".}: cint - ## Attempt to fill the read buffer. + ## Attempt to fill the read buffer. AF_INET* {.importc, header: "<sys/socket.h>".}: cint ## Internet domain sockets for use with IPv4 addresses. @@ -1592,17 +1592,17 @@ var AF_UNIX* {.importc, header: "<sys/socket.h>".}: cint ## UNIX domain sockets. AF_UNSPEC* {.importc, header: "<sys/socket.h>".}: cint - ## Unspecified. + ## Unspecified. SHUT_RD* {.importc, header: "<sys/socket.h>".}: cint ## Disables further receive operations. SHUT_RDWR* {.importc, header: "<sys/socket.h>".}: cint ## Disables further send and receive operations. SHUT_WR* {.importc, header: "<sys/socket.h>".}: cint - ## Disables further send operations. + ## Disables further send operations. IF_NAMESIZE* {.importc, header: "<net/if.h>".}: cint - + IPPROTO_IP* {.importc, header: "<netinet/in.h>".}: cint ## Internet protocol. IPPROTO_IPV6* {.importc, header: "<netinet/in.h>".}: cint @@ -1610,7 +1610,7 @@ var IPPROTO_ICMP* {.importc, header: "<netinet/in.h>".}: cint ## Control message protocol. IPPROTO_RAW* {.importc, header: "<netinet/in.h>".}: cint - ## Raw IP Packets Protocol. + ## Raw IP Packets Protocol. IPPROTO_TCP* {.importc, header: "<netinet/in.h>".}: cint ## Transmission control protocol. IPPROTO_UDP* {.importc, header: "<netinet/in.h>".}: cint @@ -1622,7 +1622,7 @@ var ## IPv4 broadcast address. INET_ADDRSTRLEN* {.importc, header: "<netinet/in.h>".}: cint - ## 16. Length of the string form for IP. + ## 16. Length of the string form for IP. IPV6_JOIN_GROUP* {.importc, header: "<netinet/in.h>".}: cint ## Join a multicast group. @@ -1640,68 +1640,68 @@ var ## Restrict AF_INET6 socket to IPv6 communications only. TCP_NODELAY* {.importc, header: "<netinet/tcp.h>".}: cint - ## Avoid coalescing of small segments. + ## Avoid coalescing of small segments. - IPPORT_RESERVED* {.importc, header: "<netdb.h>".}: cint + IPPORT_RESERVED* {.importc, header: "<netdb.h>".}: cint - HOST_NOT_FOUND* {.importc, header: "<netdb.h>".}: cint - NO_DATA* {.importc, header: "<netdb.h>".}: cint - NO_RECOVERY* {.importc, header: "<netdb.h>".}: cint - TRY_AGAIN* {.importc, header: "<netdb.h>".}: cint + HOST_NOT_FOUND* {.importc, header: "<netdb.h>".}: cint + NO_DATA* {.importc, header: "<netdb.h>".}: cint + NO_RECOVERY* {.importc, header: "<netdb.h>".}: cint + TRY_AGAIN* {.importc, header: "<netdb.h>".}: cint - AI_PASSIVE* {.importc, header: "<netdb.h>".}: cint + AI_PASSIVE* {.importc, header: "<netdb.h>".}: cint ## Socket address is intended for bind(). - AI_CANONNAME* {.importc, header: "<netdb.h>".}: cint + AI_CANONNAME* {.importc, header: "<netdb.h>".}: cint ## Request for canonical name. - AI_NUMERICHOST* {.importc, header: "<netdb.h>".}: cint + AI_NUMERICHOST* {.importc, header: "<netdb.h>".}: cint ## Return numeric host address as name. - AI_NUMERICSERV* {.importc, header: "<netdb.h>".}: cint + AI_NUMERICSERV* {.importc, header: "<netdb.h>".}: cint ## Inhibit service name resolution. - AI_V4MAPPED* {.importc, header: "<netdb.h>".}: cint + AI_V4MAPPED* {.importc, header: "<netdb.h>".}: cint ## If no IPv6 addresses are found, query for IPv4 addresses and ## return them to the caller as IPv4-mapped IPv6 addresses. - AI_ALL* {.importc, header: "<netdb.h>".}: cint + AI_ALL* {.importc, header: "<netdb.h>".}: cint ## Query for both IPv4 and IPv6 addresses. - AI_ADDRCONFIG* {.importc, header: "<netdb.h>".}: cint - ## Query for IPv4 addresses only when an IPv4 address is configured; + AI_ADDRCONFIG* {.importc, header: "<netdb.h>".}: cint + ## Query for IPv4 addresses only when an IPv4 address is configured; ## query for IPv6 addresses only when an IPv6 address is configured. - NI_NOFQDN* {.importc, header: "<netdb.h>".}: cint + NI_NOFQDN* {.importc, header: "<netdb.h>".}: cint ## Only the nodename portion of the FQDN is returned for local hosts. - NI_NUMERICHOST* {.importc, header: "<netdb.h>".}: cint + NI_NUMERICHOST* {.importc, header: "<netdb.h>".}: cint ## The numeric form of the node's address is returned instead of its name. - NI_NAMEREQD* {.importc, header: "<netdb.h>".}: cint + NI_NAMEREQD* {.importc, header: "<netdb.h>".}: cint ## Return an error if the node's name cannot be located in the database. - NI_NUMERICSERV* {.importc, header: "<netdb.h>".}: cint + NI_NUMERICSERV* {.importc, header: "<netdb.h>".}: cint ## The numeric form of the service address is returned instead of its name. - NI_NUMERICSCOPE* {.importc, header: "<netdb.h>".}: cint + NI_NUMERICSCOPE* {.importc, header: "<netdb.h>".}: cint ## For IPv6 addresses, the numeric form of the scope identifier is ## returned instead of its name. - NI_DGRAM* {.importc, header: "<netdb.h>".}: cint - ## Indicates that the service is a datagram service (SOCK_DGRAM). + NI_DGRAM* {.importc, header: "<netdb.h>".}: cint + ## Indicates that the service is a datagram service (SOCK_DGRAM). - EAI_AGAIN* {.importc, header: "<netdb.h>".}: cint + EAI_AGAIN* {.importc, header: "<netdb.h>".}: cint ## The name could not be resolved at this time. Future attempts may succeed. - EAI_BADFLAGS* {.importc, header: "<netdb.h>".}: cint + EAI_BADFLAGS* {.importc, header: "<netdb.h>".}: cint ## The flags had an invalid value. - EAI_FAIL* {.importc, header: "<netdb.h>".}: cint + EAI_FAIL* {.importc, header: "<netdb.h>".}: cint ## A non-recoverable error occurred. - EAI_FAMILY* {.importc, header: "<netdb.h>".}: cint - ## The address family was not recognized or the address length + EAI_FAMILY* {.importc, header: "<netdb.h>".}: cint + ## The address family was not recognized or the address length ## was invalid for the specified family. - EAI_MEMORY* {.importc, header: "<netdb.h>".}: cint + EAI_MEMORY* {.importc, header: "<netdb.h>".}: cint ## There was a memory allocation failure. - EAI_NONAME* {.importc, header: "<netdb.h>".}: cint + EAI_NONAME* {.importc, header: "<netdb.h>".}: cint ## The name does not resolve for the supplied parameters. - ## NI_NAMEREQD is set and the host's name cannot be located, + ## NI_NAMEREQD is set and the host's name cannot be located, ## or both nodename and servname were null. - EAI_SERVICE* {.importc, header: "<netdb.h>".}: cint + EAI_SERVICE* {.importc, header: "<netdb.h>".}: cint ## The service passed was not recognized for the specified socket type. - EAI_SOCKTYPE* {.importc, header: "<netdb.h>".}: cint + EAI_SOCKTYPE* {.importc, header: "<netdb.h>".}: cint ## The intended socket type was not recognized. - EAI_SYSTEM* {.importc, header: "<netdb.h>".}: cint + EAI_SYSTEM* {.importc, header: "<netdb.h>".}: cint ## A system error occurred. The error code can be found in errno. - EAI_OVERFLOW* {.importc, header: "<netdb.h>".}: cint + EAI_OVERFLOW* {.importc, header: "<netdb.h>".}: cint ## An argument buffer overflowed. POLLIN* {.importc, header: "<poll.h>".}: cshort @@ -1723,7 +1723,7 @@ var POLLHUP* {.importc, header: "<poll.h>".}: cshort ## Device has been disconnected (revents only). POLLNVAL* {.importc, header: "<poll.h>".}: cshort - ## Invalid fd member (revents only). + ## Invalid fd member (revents only). when hasSpawnH: @@ -1743,7 +1743,7 @@ when hasSpawnH: # macosx lacks this, so we define the constant to be 0 to not affect # OR'ing of flags: const POSIX_SPAWN_USEVFORK* = cint(0) - + when hasAioH: proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".} proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".} @@ -1817,13 +1817,13 @@ proc feupdateenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".} when not defined(haiku): proc fmtmsg*(a1: int, a2: cstring, a3: cint, a4, a5, a6: cstring): cint {.importc, header: "<fmtmsg.h>".} - + proc fnmatch*(a1, a2: cstring, a3: cint): cint {.importc, header: "<fnmatch.h>".} -proc ftw*(a1: cstring, +proc ftw*(a1: cstring, a2: proc (x1: cstring, x2: ptr TStat, x3: cint): cint {.noconv.}, a3: cint): cint {.importc, header: "<ftw.h>".} -proc nftw*(a1: cstring, - a2: proc (x1: cstring, x2: ptr TStat, +proc nftw*(a1: cstring, + a2: proc (x1: cstring, x2: ptr TStat, x3: cint, x4: ptr TFTW): cint {.noconv.}, a3: cint, a4: cint): cint {.importc, header: "<ftw.h>".} @@ -1837,7 +1837,7 @@ proc getgrgid*(a1: TGid): ptr TGroup {.importc, header: "<grp.h>".} proc getgrnam*(a1: cstring): ptr TGroup {.importc, header: "<grp.h>".} proc getgrgid_r*(a1: TGid, a2: ptr TGroup, a3: cstring, a4: int, a5: ptr ptr TGroup): cint {.importc, header: "<grp.h>".} -proc getgrnam_r*(a1: cstring, a2: ptr TGroup, a3: cstring, +proc getgrnam_r*(a1: cstring, a2: ptr TGroup, a3: cstring, a4: int, a5: ptr ptr TGroup): cint {. importc, header: "<grp.h>".} proc getgrent*(): ptr TGroup {.importc, header: "<grp.h>".} @@ -1876,9 +1876,9 @@ proc mq_send*(a1: TMqd, a2: cstring, a3: int, a4: int): cint {. proc mq_setattr*(a1: TMqd, a2, a3: ptr TMqAttr): cint {. importc, header: "<mqueue.h>".} -proc mq_timedreceive*(a1: TMqd, a2: cstring, a3: int, a4: int, +proc mq_timedreceive*(a1: TMqd, a2: cstring, a3: int, a4: int, a5: ptr Ttimespec): int {.importc, header: "<mqueue.h>".} -proc mq_timedsend*(a1: TMqd, a2: cstring, a3: int, a4: int, +proc mq_timedsend*(a1: TMqd, a2: cstring, a3: int, a4: int, a5: ptr Ttimespec): cint {.importc, header: "<mqueue.h>".} proc mq_unlink*(a1: cstring): cint {.importc, header: "<mqueue.h>".} @@ -1951,7 +1951,7 @@ proc pthread_barrierattr_getpshared*( importc, header: "<pthread.h>".} proc pthread_barrierattr_init*(a1: ptr Tpthread_barrierattr): cint {. importc, header: "<pthread.h>".} -proc pthread_barrierattr_setpshared*(a1: ptr Tpthread_barrierattr, +proc pthread_barrierattr_setpshared*(a1: ptr Tpthread_barrierattr, a2: cint): cint {.importc, header: "<pthread.h>".} proc pthread_cancel*(a1: Tpthread): cint {.importc, header: "<pthread.h>".} proc pthread_cleanup_push*(a1: proc (x: pointer) {.noconv.}, a2: pointer) {. @@ -1973,7 +1973,7 @@ proc pthread_condattr_getclock*(a1: ptr Tpthread_condattr, a2: var TClockId): cint {.importc, header: "<pthread.h>".} proc pthread_condattr_getpshared*(a1: ptr Tpthread_condattr, a2: var cint): cint {.importc, header: "<pthread.h>".} - + proc pthread_condattr_init*(a1: ptr Tpthread_condattr): cint {.importc, header: "<pthread.h>".} proc pthread_condattr_setclock*(a1: ptr Tpthread_condattr,a2: TClockId): cint {.importc, header: "<pthread.h>".} proc pthread_condattr_setpshared*(a1: ptr Tpthread_condattr, a2: cint): cint {.importc, header: "<pthread.h>".} @@ -2085,6 +2085,7 @@ proc execv*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>" proc execve*(a1: cstring, a2, a3: cstringArray): cint {. importc, header: "<unistd.h>".} proc execvp*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>".} +proc execvpe*(a1: cstring, a2: cstringArray, a3: cstringArray): cint {.importc, header: "<unistd.h>".} proc fchown*(a1: cint, a2: Tuid, a3: TGid): cint {.importc, header: "<unistd.h>".} proc fchdir*(a1: cint): cint {.importc, header: "<unistd.h>".} proc fdatasync*(a1: cint): cint {.importc, header: "<unistd.h>".} @@ -2205,18 +2206,18 @@ proc S_ISREG*(m: TMode): bool {.importc, header: "<sys/stat.h>".} proc S_ISLNK*(m: TMode): bool {.importc, header: "<sys/stat.h>".} ## Test for a symbolic link. proc S_ISSOCK*(m: TMode): bool {.importc, header: "<sys/stat.h>".} - ## Test for a socket. - + ## Test for a socket. + proc S_TYPEISMQ*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".} ## Test for a message queue. proc S_TYPEISSEM*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".} ## Test for a semaphore. proc S_TYPEISSHM*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".} - ## Test for a shared memory object. - + ## Test for a shared memory object. + proc S_TYPEISTMO*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".} - ## Test macro for a typed memory object. - + ## Test macro for a typed memory object. + proc mlock*(a1: pointer, a2: int): cint {.importc, header: "<sys/mman.h>".} proc mlockall*(a1: cint): cint {.importc, header: "<sys/mman.h>".} proc mmap*(a1: pointer, a2: int, a3, a4, a5: cint, a6: TOff): pointer {. @@ -2231,7 +2232,7 @@ proc posix_madvise*(a1: pointer, a2: int, a3: cint): cint {. importc, header: "<sys/mman.h>".} proc posix_mem_offset*(a1: pointer, a2: int, a3: var TOff, a4: var int, a5: var cint): cint {.importc, header: "<sys/mman.h>".} -proc posix_typed_mem_get_info*(a1: cint, +proc posix_typed_mem_get_info*(a1: cint, a2: var Tposix_typed_mem_info): cint {.importc, header: "<sys/mman.h>".} proc posix_typed_mem_open*(a1: cstring, a2, a3: cint): cint {. importc, header: "<sys/mman.h>".} @@ -2317,7 +2318,7 @@ proc sigrelse*(a1: cint): cint {.importc, header: "<signal.h>".} proc sigset*(a1: int, a2: proc (x: cint) {.noconv.}) {. importc, header: "<signal.h>".} proc sigsuspend*(a1: var Tsigset): cint {.importc, header: "<signal.h>".} -proc sigtimedwait*(a1: var Tsigset, a2: var TsigInfo, +proc sigtimedwait*(a1: var Tsigset, a2: var TsigInfo, a3: var Ttimespec): cint {.importc, header: "<signal.h>".} proc sigwait*(a1: var Tsigset, a2: var cint): cint {. importc, header: "<signal.h>".} @@ -2361,7 +2362,7 @@ proc select*(a1: cint, a2, a3, a4: ptr TFdSet, a5: ptr Ttimeval): cint {. when hasSpawnH: proc posix_spawn*(a1: var TPid, a2: cstring, a3: var Tposix_spawn_file_actions, - a4: var Tposix_spawnattr, + a4: var Tposix_spawnattr, a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".} proc posix_spawn_file_actions_addclose*(a1: var Tposix_spawn_file_actions, a2: cint): cint {.importc, header: "<spawn.h>".} @@ -2388,7 +2389,7 @@ when hasSpawnH: a2: var cint): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_getsigmask*(a1: var Tposix_spawnattr, a2: var Tsigset): cint {.importc, header: "<spawn.h>".} - + proc posix_spawnattr_init*(a1: var Tposix_spawnattr): cint {. importc, header: "<spawn.h>".} proc posix_spawnattr_setsigdefault*(a1: var Tposix_spawnattr, @@ -2397,10 +2398,10 @@ when hasSpawnH: importc, header: "<spawn.h>".} proc posix_spawnattr_setpgroup*(a1: var Tposix_spawnattr, a2: TPid): cint {. importc, header: "<spawn.h>".} - + proc posix_spawnattr_setschedparam*(a1: var Tposix_spawnattr, a2: var Tsched_param): cint {.importc, header: "<spawn.h>".} - proc posix_spawnattr_setschedpolicy*(a1: var Tposix_spawnattr, + proc posix_spawnattr_setschedpolicy*(a1: var Tposix_spawnattr, a2: cint): cint {. importc, header: "<spawn.h>".} proc posix_spawnattr_setsigmask*(a1: var Tposix_spawnattr, @@ -2441,7 +2442,7 @@ proc accept*(a1: TSocketHandle, a2: ptr TSockAddr, a3: ptr TSocklen): TSocketHan proc bindSocket*(a1: TSocketHandle, a2: ptr TSockAddr, a3: TSocklen): cint {. importc: "bind", header: "<sys/socket.h>".} ## is Posix's ``bind``, because ``bind`` is a reserved word - + proc connect*(a1: TSocketHandle, a2: ptr TSockAddr, a3: TSocklen): cint {. importc, header: "<sys/socket.h>".} proc getpeername*(a1: TSocketHandle, a2: ptr TSockAddr, a3: ptr TSocklen): cint {. @@ -2530,9 +2531,9 @@ proc freeaddrinfo*(a1: ptr Taddrinfo) {.importc, header: "<netdb.h>".} proc gai_strerror*(a1: cint): cstring {.importc, header: "<netdb.h>".} -proc getaddrinfo*(a1, a2: cstring, a3: ptr Taddrinfo, +proc getaddrinfo*(a1, a2: cstring, a3: ptr Taddrinfo, a4: var ptr Taddrinfo): cint {.importc, header: "<netdb.h>".} - + proc gethostbyaddr*(a1: pointer, a2: TSocklen, a3: cint): ptr Thostent {. importc, header: "<netdb.h>".} proc gethostbyname*(a1: cstring): ptr Thostent {.importc, header: "<netdb.h>".} @@ -2566,4 +2567,14 @@ proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {. proc realpath*(name, resolved: cstring): cstring {. importc: "realpath", header: "<stdlib.h>".} - +proc utimes*(path: cstring, times: ptr array [2, Ttimeval]): int {. + importc: "utimes", header: "<sys/time.h>".} + ## Sets file access and modification times. + ## + ## Pass the filename and an array of times to set the access and modification + ## times respectively. If you pass nil as the array both attributes will be + ## set to the current time. + ## + ## Returns zero on success. + ## + ## For more information read http://www.unix.com/man-page/posix/3/utimes/. diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index df7ae6d17..921c659de 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -131,3 +131,36 @@ proc sort*[T](a: var openArray[T], dec(m, s*2) s = s*2 +proc product*[T](x: openarray[seq[T]]): seq[seq[T]] = + ## produces the Cartesian product of the array. Warning: complexity + ## may explode. + result = @[] + if x.len == 0: + return + if x.len == 1: + result = @x + return + var + indexes = newSeq[int](x.len) + initial = newSeq[int](x.len) + index = 0 + # replace with newSeq as soon as #853 is fixed + var next: seq[T] = @[] + next.setLen(x.len) + for i in 0..(x.len-1): + if len(x[i]) == 0: return + initial[i] = len(x[i])-1 + indexes = initial + while true: + while indexes[index] == -1: + indexes[index] = initial[index] + index +=1 + if index == x.len: return + indexes[index] -=1 + for ni, i in indexes: + next[ni] = x[ni][i] + var res: seq[T] + shallowCopy(res, next) + result.add(res) + index = 0 + indexes[index] -=1 diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim index f13cadaa2..96afc6f4f 100644 --- a/lib/pure/asyncio.nim +++ b/lib/pure/asyncio.nim @@ -689,5 +689,5 @@ when isMainModule: server.listen() d.register(server) - while d.poll(-1): nil + while d.poll(-1): discard diff --git a/lib/pure/asyncio2.nim b/lib/pure/asyncio2.nim new file mode 100644 index 000000000..cdb4a6f49 --- /dev/null +++ b/lib/pure/asyncio2.nim @@ -0,0 +1,485 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2014 Dominik Picheta +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +import os, oids, tables, strutils + +import winlean + +import sockets2, net + +## Asyncio2 +## -------- +## +## This module implements a brand new asyncio module based on Futures. +## IOCP is used under the hood on Windows and the selectors module is used for +## other operating systems. + +# -- Futures + +type + PFutureVoid* = ref object of PObject + cbVoid: proc () {.closure.} + finished: bool + + PFuture*[T] = ref object of PFutureVoid + value: T + error: ref EBase + cb: proc (future: PFuture[T]) {.closure.} + +proc newFuture*[T](): PFuture[T] = + ## Creates a new future. + new(result) + result.finished = false + +proc complete*[T](future: PFuture[T], val: T) = + ## Completes ``future`` with value ``val``. + assert(not future.finished) + assert(future.error == nil) + future.value = val + future.finished = true + if future.cb != nil: + future.cb(future) + if future.cbVoid != nil: + future.cbVoid() + +proc fail*[T](future: PFuture[T], error: ref EBase) = + ## Completes ``future`` with ``error``. + assert(not future.finished) + future.finished = true + future.error = error + if future.cb != nil: + future.cb(future) + +proc `callback=`*[T](future: PFuture[T], + cb: proc (future: PFuture[T]) {.closure.}) = + ## Sets the callback proc to be called when the future completes. + ## + ## If future has already completed then ``cb`` will be called immediately. + future.cb = cb + if future.finished: + future.cb(future) + +proc `callbackVoid=`*(future: PFutureVoid, cb: proc () {.closure.}) = + ## Sets the **void** callback proc to be called when the future completes. + ## + ## If future has already completed then ``cb`` will be called immediately. + ## + ## **Note**: This is used for the ``await`` functionality, you most likely + ## want to use ``callback``. + future.cbVoid = cb + if future.finished: + future.cbVoid() + +proc read*[T](future: PFuture[T]): T = + ## Retrieves the value of ``future``. Future must be finished otherwise + ## this function will fail with a ``EInvalidValue`` exception. + ## + ## If the result of the future is an error then that error will be raised. + if future.finished: + if future.error != nil: raise future.error + return future.value + else: + # TODO: Make a custom exception type for this? + raise newException(EInvalidValue, "Future still in progress.") + +proc finished*[T](future: PFuture[T]): bool = + ## Determines whether ``future`` has completed. + ## + ## ``True`` may indicate an error or a value. Use ``hasError`` to distinguish. + future.finished + +proc failed*[T](future: PFuture[T]): bool = + ## Determines whether ``future`` completed with an error. + future.error != nil + +when defined(windows): + type + TCompletionKey = dword + + TCompletionData* = object + sock: TSocketHandle + cb: proc (sock: TSocketHandle, errcode: TOSErrorCode) {.closure.} + + PDispatcher* = ref object + ioPort: THandle + + TCustomOverlapped = object + Internal*: DWORD + InternalHigh*: DWORD + Offset*: DWORD + OffsetHigh*: DWORD + hEvent*: THANDLE + data*: TCompletionData + + PCustomOverlapped = ptr TCustomOverlapped + + proc newDispatcher*(): PDispatcher = + ## Creates a new Dispatcher instance. + new result + result.ioPort = CreateIOCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 1) + + proc register*(p: PDispatcher, sock: TSocketHandle) = + ## Registers ``sock`` with the dispatcher ``p``. + if CreateIOCompletionPort(sock.THandle, p.ioPort, + cast[TCompletionKey](sock), 1) == 0: + OSError(OSLastError()) + + proc poll*(p: PDispatcher, timeout = 500) = + ## Waits for completion events and processes them. + let llTimeout = + if timeout == -1: winlean.INFINITE + else: timeout.int32 + var lpNumberOfBytesTransferred: DWORD + var lpCompletionKey: ULONG + var lpOverlapped: POverlapped + let res = GetQueuedCompletionStatus(p.ioPort, addr lpNumberOfBytesTransferred, + addr lpCompletionKey, addr lpOverlapped, llTimeout).bool + + # http://stackoverflow.com/a/12277264/492186 + # TODO: http://www.serverframework.com/handling-multiple-pending-socket-read-and-write-operations.html + var customOverlapped = cast[PCustomOverlapped](lpOverlapped) + if res: + assert customOverlapped.data.sock == lpCompletionKey.TSocketHandle + + customOverlapped.data.cb(customOverlapped.data.sock, TOSErrorCode(-1)) + dealloc(customOverlapped) + else: + let errCode = OSLastError() + if lpOverlapped != nil: + assert customOverlapped.data.sock == lpCompletionKey.TSocketHandle + dealloc(customOverlapped) + customOverlapped.data.cb(customOverlapped.data.sock, errCode) + else: + if errCode.int32 == WAIT_TIMEOUT: + # Timed out + discard + else: OSError(errCode) + + var connectExPtr: pointer = nil + var acceptExPtr: pointer = nil + var getAcceptExSockAddrsPtr: pointer = nil + + proc initPointer(s: TSocketHandle, func: var pointer, guid: var TGUID): bool = + # Ref: https://github.com/powdahound/twisted/blob/master/twisted/internet/iocpreactor/iocpsupport/winsock_pointers.c + var bytesRet: DWord + func = nil + result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, addr guid, + sizeof(TGUID).dword, addr func, sizeof(pointer).DWORD, + addr bytesRet, nil, nil) == 0 + + proc initAll() = + let dummySock = socket() + if not initPointer(dummySock, connectExPtr, WSAID_CONNECTEX): + OSError(OSLastError()) + if not initPointer(dummySock, acceptExPtr, WSAID_ACCEPTEX): + OSError(OSLastError()) + if not initPointer(dummySock, getAcceptExSockAddrsPtr, WSAID_GETACCEPTEXSOCKADDRS): + OSError(OSLastError()) + + proc connectEx(s: TSocketHandle, name: ptr TSockAddr, namelen: cint, + lpSendBuffer: pointer, dwSendDataLength: dword, + lpdwBytesSent: PDWORD, lpOverlapped: POverlapped): bool = + if connectExPtr.isNil: raise newException(EInvalidValue, "Need to initialise ConnectEx().") + let func = + cast[proc (s: TSocketHandle, name: ptr TSockAddr, namelen: cint, + lpSendBuffer: pointer, dwSendDataLength: dword, + lpdwBytesSent: PDWORD, lpOverlapped: POverlapped): bool {.stdcall.}](connectExPtr) + + result = func(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent, + lpOverlapped) + + proc acceptEx(listenSock, acceptSock: TSocketHandle, lpOutputBuffer: pointer, + dwReceiveDataLength, dwLocalAddressLength, + dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD, + lpOverlapped: POverlapped): bool = + if acceptExPtr.isNil: raise newException(EInvalidValue, "Need to initialise AcceptEx().") + let func = + cast[proc (listenSock, acceptSock: TSocketHandle, lpOutputBuffer: pointer, + dwReceiveDataLength, dwLocalAddressLength, + dwRemoteAddressLength: DWORD, lpdwBytesReceived: PDWORD, + lpOverlapped: POverlapped): bool {.stdcall.}](acceptExPtr) + result = func(listenSock, acceptSock, lpOutputBuffer, dwReceiveDataLength, + dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived, + lpOverlapped) + + proc getAcceptExSockaddrs(lpOutputBuffer: pointer, + dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength: DWORD, + LocalSockaddr: ptr ptr TSockAddr, LocalSockaddrLength: lpint, + RemoteSockaddr: ptr ptr TSockAddr, RemoteSockaddrLength: lpint) = + if getAcceptExSockAddrsPtr.isNil: + raise newException(EInvalidValue, "Need to initialise getAcceptExSockAddrs().") + + let func = + cast[proc (lpOutputBuffer: pointer, + dwReceiveDataLength, dwLocalAddressLength, + dwRemoteAddressLength: DWORD, LocalSockaddr: ptr ptr TSockAddr, + LocalSockaddrLength: lpint, RemoteSockaddr: ptr ptr TSockAddr, + RemoteSockaddrLength: lpint) {.stdcall.}](getAcceptExSockAddrsPtr) + + func(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength, + dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength, + RemoteSockaddr, RemoteSockaddrLength) + + proc connect*(p: PDispatcher, socket: TSocketHandle, address: string, port: TPort, + af = AF_INET): PFuture[int] = + ## Connects ``socket`` to server at ``address:port``. + ## + ## Returns a ``PFuture`` which will complete when the connection succeeds + ## or an error occurs. + + var retFuture = newFuture[int]()# TODO: Change to void when that regression is fixed. + # Apparently ``ConnectEx`` expects the socket to be initially bound: + var saddr: Tsockaddr_in + saddr.sin_family = int16(toInt(af)) + saddr.sin_port = 0 + saddr.sin_addr.s_addr = INADDR_ANY + if bindAddr(socket, cast[ptr TSockAddr](addr(saddr)), + sizeof(saddr).TSockLen) < 0'i32: + OSError(OSLastError()) + + var aiList = getAddrInfo(address, port, af) + var success = false + var lastError: TOSErrorCode + var it = aiList + while it != nil: + # "the OVERLAPPED structure must remain valid until the I/O completes" + # http://blogs.msdn.com/b/oldnewthing/archive/2011/02/02/10123392.aspx + var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped))) + ol.data = TCompletionData(sock: socket, cb: + proc (sock: TSocketHandle, errcode: TOSErrorCode) = + if errcode == TOSErrorCode(-1): + retFuture.complete(0) + else: + retFuture.fail(newException(EOS, osErrorMsg(errcode))) + ) + + var ret = connectEx(socket, it.ai_addr, sizeof(TSockAddrIn).cint, + nil, 0, nil, cast[POverlapped](ol)) + if ret: + # Request to connect completed immediately. + success = true + retFuture.complete(0) + dealloc(ol) + break + else: + lastError = OSLastError() + if lastError.int32 == ERROR_IO_PENDING: + # In this case ``ol`` will be deallocated in ``poll``. + success = true + break + else: + dealloc(ol) + success = false + it = it.ai_next + + dealloc(aiList) + if not success: + retFuture.fail(newException(EOS, osErrorMsg(lastError))) + return retFuture + + proc recv*(p: PDispatcher, socket: TSocketHandle, size: int): PFuture[string] = + ## Reads ``size`` bytes from ``socket``. Returned future will complete once + ## all of the requested data is read. + + var retFuture = newFuture[string]() + + var dataBuf: TWSABuf + dataBuf.buf = newString(size) + dataBuf.len = size + + var bytesReceived, flags: DWord + var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped))) + ol.data = TCompletionData(sock: socket, cb: + proc (sock: TSocketHandle, errcode: TOSErrorCode) = + if errcode == TOSErrorCode(-1): + var data = newString(size) + copyMem(addr data[0], addr dataBuf.buf[0], size) + retFuture.complete($data) + else: + retFuture.fail(newException(EOS, osErrorMsg(errcode))) + ) + + let ret = WSARecv(socket, addr dataBuf, 1, addr bytesReceived, + addr flags, cast[POverlapped](ol), nil) + if ret == -1: + let err = OSLastError() + if err.int32 != ERROR_IO_PENDING: + retFuture.fail(newException(EOS, osErrorMsg(err))) + dealloc(ol) + else: + # Request to read completed immediately. + var data = newString(size) + copyMem(addr data[0], addr dataBuf.buf[0], size) + retFuture.complete($data) + dealloc(ol) + return retFuture + + proc send*(p: PDispatcher, socket: TSocketHandle, data: string): PFuture[int] = + ## Sends ``data`` to ``socket``. The returned future will complete once all + ## data has been sent. + var retFuture = newFuture[int]() + + var dataBuf: TWSABuf + dataBuf.buf = data + dataBuf.len = data.len + + var bytesReceived, flags: DWord + var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped))) + ol.data = TCompletionData(sock: socket, cb: + proc (sock: TSocketHandle, errcode: TOSErrorCode) = + if errcode == TOSErrorCode(-1): + retFuture.complete(0) + else: + retFuture.fail(newException(EOS, osErrorMsg(errcode))) + ) + + let ret = WSASend(socket, addr dataBuf, 1, addr bytesReceived, + flags, cast[POverlapped](ol), nil) + if ret == -1: + let err = osLastError() + if err.int32 != ERROR_IO_PENDING: + retFuture.fail(newException(EOS, osErrorMsg(err))) + dealloc(ol) + else: + retFuture.complete(0) + dealloc(ol) + return retFuture + + proc acceptAddr*(p: PDispatcher, socket: TSocketHandle): + PFuture[tuple[address: string, client: TSocketHandle]] = + ## Accepts a new connection. Returns a future containing the client socket + ## corresponding to that connection and the remote address of the client. + ## The future will complete when the connection is successfully accepted. + + var retFuture = newFuture[tuple[address: string, client: TSocketHandle]]() + + var clientSock = socket() + if clientSock == OSInvalidSocket: osError(osLastError()) + + const lpOutputLen = 1024 + var lpOutputBuf = newString(lpOutputLen) + var dwBytesReceived: DWORD + let dwReceiveDataLength = 0.DWORD # We don't want any data to be read. + let dwLocalAddressLength = DWORD(sizeof (TSockaddr_in) + 16) + let dwRemoteAddressLength = DWORD(sizeof(TSockaddr_in) + 16) + + template completeAccept(): stmt {.immediate, dirty.} = + var listenSock = socket + let setoptRet = setsockopt(clientSock, SOL_SOCKET, + SO_UPDATE_ACCEPT_CONTEXT, addr listenSock, + sizeof(listenSock).TSockLen) + if setoptRet != 0: osError(osLastError()) + + var LocalSockaddr, RemoteSockaddr: ptr TSockAddr + var localLen, remoteLen: int32 + getAcceptExSockaddrs(addr lpOutputBuf[0], dwReceiveDataLength, + dwLocalAddressLength, dwRemoteAddressLength, + addr LocalSockaddr, addr localLen, + addr RemoteSockaddr, addr remoteLen) + # TODO: IPv6. Check ``sa_family``. http://stackoverflow.com/a/9212542/492186 + retFuture.complete( + (address: $inet_ntoa(cast[ptr Tsockaddr_in](remoteSockAddr).sin_addr), + client: clientSock) + ) + + var ol = cast[PCustomOverlapped](alloc0(sizeof(TCustomOverlapped))) + ol.data = TCompletionData(sock: socket, cb: + proc (sock: TSocketHandle, errcode: TOSErrorCode) = + if errcode == TOSErrorCode(-1): + completeAccept() + else: + retFuture.fail(newException(EOS, osErrorMsg(errcode))) + ) + + # http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx + let ret = acceptEx(socket, clientSock, addr lpOutputBuf[0], + dwReceiveDataLength, + dwLocalAddressLength, + dwRemoteAddressLength, + addr dwBytesReceived, cast[POverlapped](ol)) + + if not ret: + let err = osLastError() + if err.int32 != ERROR_IO_PENDING: + retFuture.fail(newException(EOS, osErrorMsg(err))) + dealloc(ol) + else: + completeAccept() + dealloc(ol) + + return retFuture + + proc accept*(p: PDispatcher, socket: TSocketHandle): PFuture[TSocketHandle] = + ## Accepts a new connection. Returns a future containing the client socket + ## corresponding to that connection. + ## The future will complete when the connection is successfully accepted. + var retFut = newFuture[TSocketHandle]() + var fut = p.acceptAddr(socket) + fut.callback = + proc (future: PFuture[tuple[address: string, client: TSocketHandle]]) = + assert future.finished + if future.failed: + retFut.fail(future.error) + else: + retFut.complete(future.read.client) + return retFut + + initAll() +else: + # TODO: Selectors. + + +when isMainModule: + + var p = newDispatcher() + var sock = socket() + #sock.setBlocking false + p.register(sock) + + when true: + + var f = p.connect(sock, "irc.freenode.org", TPort(6667)) + f.callback = + proc (future: PFuture[int]) = + echo("Connected in future!") + echo(future.read) + for i in 0 .. 50: + var recvF = p.recv(sock, 10) + recvF.callback = + proc (future: PFuture[string]) = + echo("Read: ", future.read) + + else: + + sock.bindAddr(TPort(6667)) + sock.listen() + proc onAccept(future: PFuture[TSocketHandle]) = + echo "Accepted" + var t = p.send(future.read, "test\c\L") + t.callback = + proc (future: PFuture[int]) = + echo(future.read) + + var f = p.accept(sock) + f.callback = onAccept + + var f = p.accept(sock) + f.callback = onAccept + + while true: + p.poll() + echo "polled" + + + + + + + + \ No newline at end of file diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 3993f1ccc..b2f72ee14 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -276,6 +276,38 @@ template foldr*(sequence, operation: expr): expr = result = operation result +template mapIt*(seq1, typ, pred: expr): expr = + ## Convenience template around the ``map`` proc to reduce typing. + ## + ## The template injects the ``it`` variable which you can use directly in an + ## expression. You also need to pass as `typ` the type of the expression, + ## since the new returned sequence can have a different type than the + ## original. Example: + ## + ## .. code-block:: nimrod + ## let + ## nums = @[1, 2, 3, 4] + ## strings = nums.mapIt(string, $(4 * it)) + var result {.gensym.}: seq[typ] = @[] + for it {.inject.} in items(seq1): + result.add(pred) + result + +template mapIt*(varSeq, pred: expr) = + ## Convenience template around the mutable ``map`` proc to reduce typing. + ## + ## The template injects the ``it`` variable which you can use directly in an + ## expression. The expression has to return the same type as the sequence you + ## are mutating. Example: + ## + ## .. code-block:: nimrod + ## var nums = @[1, 2, 3, 4] + ## nums.mapIt(it * 3) + ## assert nums[0] + nums[3] == 15 + for i in 0 .. <len(varSeq): + let it {.inject.} = varSeq[i] + varSeq[i] = pred + when isMainModule: import strutils block: # concat test @@ -381,4 +413,11 @@ when isMainModule: Inserting [2,2,2,2,2,2] into [1,1,1,1,1,1,1,1] at 3 is [1,1,1,2,2,2,2,2,2,1,1,1,1,1]""" + block: # mapIt tests + var + nums = @[1, 2, 3, 4] + strings = nums.mapIt(string, $(4 * it)) + nums.mapIt(it * 3) + assert nums[0] + nums[3] == 15 + echo "Finished doc tests" diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 7259772aa..e6ab617e5 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -224,3 +224,20 @@ proc toOrderedSet*[A](keys: openArray[A]): TOrderedSet[A] = proc `$`*[A](s: TOrderedSet[A]): string = ## The `$` operator for ordered hash sets. dollarImpl() + +proc `<`*[A](s, t: TSet[A]): bool = + ## Is s a strict subset of t? + s.counter != t.counter and s <= t + +proc `<=`*[A](s, t: TSet[A]): bool = + ## Is s a subset of t? + result = false + if s.counter > t.counter: return + result = true + for item in s: + if not(t.contains(item)): + result = false + return + +proc `==`*[A](s, t: TSet[A]): bool = + s.counter == t.counter and s <= t diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 73da274b9..40ae57b5a 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -189,6 +189,16 @@ template dollarImpl(): stmt {.dirty.} = proc `$`*[A, B](t: TTable[A, B]): string = ## The `$` operator for hash tables. dollarImpl() + +proc `==`*[A, B](s, t: TTable[A, B]): bool = + s.counter == t.counter and s.data == t.data + +proc indexBy*[A, B, C](collection: A, index: proc(x: B): C): TTable[C, B] = + ## Index the collection with the proc provided. + # TODO: As soon as supported, change collection: A to collection: A[B] + result = initTable[C, B]() + for item in collection: + result[index(item)] = item # ------------------------------ ordered table ------------------------------ diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim index a64b7f138..3ed00fdb2 100644 --- a/lib/pure/dynlib.nim +++ b/lib/pure/dynlib.nim @@ -14,15 +14,15 @@ type TLibHandle* = pointer ## a handle to a dynamically loaded library -proc LoadLib*(path: string): TLibHandle +proc loadLib*(path: string): TLibHandle ## loads a library from `path`. Returns nil if the library could not ## be loaded. -proc LoadLib*(): TLibHandle +proc loadLib*(): TLibHandle ## gets the handle from the current executable. Returns nil if the ## library could not be loaded. -proc UnloadLib*(lib: TLibHandle) +proc unloadLib*(lib: TLibHandle) ## unloads the library `lib` proc raiseInvalidLibrary*(name: cstring) {.noinline, noreturn.} = @@ -60,9 +60,9 @@ when defined(posix): proc dlsym(lib: TLibHandle, name: cstring): pointer {. importc, header: "<dlfcn.h>".} - proc LoadLib(path: string): TLibHandle = return dlopen(path, RTLD_NOW) - proc LoadLib(): TLibHandle = return dlopen(nil, RTLD_NOW) - proc UnloadLib(lib: TLibHandle) = dlclose(lib) + proc loadLib(path: string): TLibHandle = return dlopen(path, RTLD_NOW) + proc loadLib(): TLibHandle = return dlopen(nil, RTLD_NOW) + proc unloadLib(lib: TLibHandle) = dlclose(lib) proc symAddr(lib: TLibHandle, name: cstring): pointer = return dlsym(lib, name) @@ -78,14 +78,14 @@ elif defined(windows) or defined(dos): proc FreeLibrary(lib: THINSTANCE) {.importc, header: "<windows.h>", stdcall.} proc winLoadLibrary(path: cstring): THINSTANCE {. importc: "LoadLibraryA", header: "<windows.h>", stdcall.} - proc GetProcAddress(lib: THINSTANCE, name: cstring): pointer {. + proc getProcAddress(lib: THINSTANCE, name: cstring): pointer {. importc: "GetProcAddress", header: "<windows.h>", stdcall.} - proc LoadLib(path: string): TLibHandle = + proc loadLib(path: string): TLibHandle = result = cast[TLibHandle](winLoadLibrary(path)) - proc LoadLib(): TLibHandle = + proc loadLib(): TLibHandle = result = cast[TLibHandle](winLoadLibrary(nil)) - proc UnloadLib(lib: TLibHandle) = FreeLibrary(cast[THINSTANCE](lib)) + proc unloadLib(lib: TLibHandle) = FreeLibrary(cast[THINSTANCE](lib)) proc symAddr(lib: TLibHandle, name: cstring): pointer = result = GetProcAddress(cast[THINSTANCE](lib), name) diff --git a/lib/pure/htmlparser.nim b/lib/pure/htmlparser.nim index 060f0e386..c38eb7063 100644 --- a/lib/pure/htmlparser.nim +++ b/lib/pure/htmlparser.nim @@ -480,7 +480,7 @@ proc untilElementEnd(x: var TXmlParser, result: PXmlNode, if htmlTag(x.elemName) in {tagOption, tagOptgroup}: errors.add(expected(x, result)) break - else: nil + else: discard result.addNode(parse(x, errors)) of xmlElementEnd: if cmpIgnoreCase(x.elemName, result.tag) == 0: @@ -547,7 +547,7 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode = var u = entityToUtf8(x.rawData) if u.len != 0: result = newText(u) next(x) - of xmlEof: nil + of xmlEof: discard proc parseHtml*(s: PStream, filename: string, errors: var seq[string]): PXmlNode = diff --git a/lib/pure/irc.nim b/lib/pure/irc.nim index 750c98516..c1b519b0b 100644 --- a/lib/pure/irc.nim +++ b/lib/pure/irc.nim @@ -476,12 +476,12 @@ when isMainModule: var client = irc("amber.tenthbit.net", nick="TestBot1234", joinChans = @["#flood"]) client.connect() - while True: + while true: var event: TIRCEvent if client.poll(event): case event.typ of EvConnected: - nil + discard of EvDisconnected: break of EvMsg: diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim new file mode 100644 index 000000000..284384b37 --- /dev/null +++ b/lib/pure/logging.nim @@ -0,0 +1,267 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2014 Andreas Rumpf, Dominik Picheta +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements a simple logger. It has been designed to be as simple +## as possible to avoid bloat, if this library does not fullfill your needs, +## write your own. +## +## Format strings support the following variables which must be prefixed with +## the dollar operator (``$``): +## +## ============ ======================= +## Operator Output +## ============ ======================= +## $date Current date +## $time Current time +## $app ``os.getAppFilename()`` +## ============ ======================= +## +## +## The following example demonstrates logging to three different handlers +## simultaneously: +## +## .. code-block:: nimrod +## +## var L = newConsoleLogger() +## var fL = newFileLogger("test.log", fmtStr = verboseFmtStr) +## var rL = newRollingFileLogger("rolling.log", fmtStr = verboseFmtStr) +## handlers.add(L) +## handlers.add(fL) +## handlers.add(rL) +## info("920410:52 accepted") +## warn("4 8 15 16 23 4-- Error") +## error("922044:16 SYSTEM FAILURE") +## fatal("SYSTEM FAILURE SYSTEM FAILURE") + +import strutils, os, times + +type + TLevel* = enum ## logging level + lvlAll, ## all levels active + lvlDebug, ## debug level (and any above) active + lvlInfo, ## info level (and any above) active + lvlWarn, ## warn level (and any above) active + lvlError, ## error level (and any above) active + lvlFatal, ## fatal level (and any above) active + lvlNone ## no levels active + +const + LevelNames*: array [TLevel, string] = [ + "DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE" + ] + + defaultFmtStr* = "" ## default string between log level and message per logger + verboseFmtStr* = "$date $time " + +type + PLogger* = ref object of PObject ## abstract logger; the base type of all loggers + levelThreshold*: TLevel ## only messages of level >= levelThreshold + ## should be processed + fmtStr: string ## = defaultFmtStr by default, see substituteLog for $date etc. + + PConsoleLogger* = ref object of PLogger ## logger that writes the messages to the + ## console + + PFileLogger* = ref object of PLogger ## logger that writes the messages to a file + f: TFile + + PRollingFileLogger* = ref object of PFileLogger ## logger that writes the + ## messages to a file and + ## performs log rotation + maxLines: int # maximum number of lines + curLine : int + baseName: string # initial filename + baseMode: TFileMode # initial file mode + logFiles: int # how many log files already created, e.g. basename.1, basename.2... + +proc substituteLog(frmt: string): string = + ## converts $date to the current date + ## converts $time to the current time + ## converts $app to getAppFilename() + ## converts + result = newStringOfCap(frmt.len + 20) + var i = 0 + while i < frmt.len: + if frmt[i] != '$': + result.add(frmt[i]) + inc(i) + else: + inc(i) + var v = "" + var app = getAppFilename() + while frmt[i] in IdentChars: + v.add(toLower(frmt[i])) + inc(i) + case v + of "date": result.add(getDateStr()) + of "time": result.add(getClockStr()) + of "app": result.add(app) + of "appdir": result.add(app.splitFile.dir) + of "appname": result.add(app.splitFile.name) + +method log*(logger: PLogger, level: TLevel, + frmt: string, args: varargs[string, `$`]) {.raises: [EBase], tags: [FTime, FWriteIO, FReadIO].} = + ## Override this method in custom loggers. Default implementation does + ## nothing. + discard + +method log*(logger: PConsoleLogger, level: TLevel, + frmt: string, args: varargs[string, `$`]) = + ## Logs to the console using ``logger`` only. + if level >= logger.levelThreshold: + writeln(stdout, LevelNames[level], " ", substituteLog(logger.fmtStr), + frmt % args) + +method log*(logger: PFileLogger, level: TLevel, + frmt: string, args: varargs[string, `$`]) = + ## Logs to a file using ``logger`` only. + if level >= logger.levelThreshold: + writeln(logger.f, LevelNames[level], " ", + substituteLog(logger.fmtStr), frmt % args) + +proc defaultFilename*(): string = + ## Returns the default filename for a logger. + var (path, name, ext) = splitFile(getAppFilename()) + result = changeFileExt(path / name, "log") + +proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr): PConsoleLogger = + ## Creates a new console logger. This logger logs to the console. + new result + result.fmtStr = fmtStr + result.levelThreshold = levelThreshold + +proc newFileLogger*(filename = defaultFilename(), + mode: TFileMode = fmAppend, + levelThreshold = lvlAll, + fmtStr = defaultFmtStr): PFileLogger = + ## Creates a new file logger. This logger logs to a file. + new(result) + result.levelThreshold = levelThreshold + result.f = open(filename, mode) + result.fmtStr = fmtStr + +# ------ + +proc countLogLines(logger: PRollingFileLogger): int = + result = 0 + for line in logger.f.lines(): + result.inc() + +proc countFiles(filename: string): int = + # Example: file.log.1 + result = 0 + let (dir, name, ext) = splitFile(filename) + for kind, path in walkDir(dir): + if kind == pcFile: + let llfn = name & ext & ExtSep + if path.extractFilename.startsWith(llfn): + let numS = path.extractFilename[llfn.len .. -1] + try: + let num = parseInt(numS) + if num > result: + result = num + except EInvalidValue: discard + +proc newRollingFileLogger*(filename = defaultFilename(), + mode: TFileMode = fmReadWrite, + levelThreshold = lvlAll, + fmtStr = defaultFmtStr, + maxLines = 1000): PRollingFileLogger = + ## Creates a new rolling file logger. Once a file reaches ``maxLines`` lines + ## a new log file will be started and the old will be renamed. + new(result) + result.levelThreshold = levelThreshold + result.fmtStr = defaultFmtStr + result.maxLines = maxLines + result.f = open(filename, mode) + result.curLine = 0 + result.baseName = filename + result.baseMode = mode + + result.logFiles = countFiles(filename) + + if mode == fmAppend: + # We need to get a line count because we will be appending to the file. + result.curLine = countLogLines(result) + +proc rotate(logger: PRollingFileLogger) = + let (dir, name, ext) = splitFile(logger.baseName) + for i in countdown(logger.logFiles, 0): + let srcSuff = if i != 0: ExtSep & $i else: "" + moveFile(dir / (name & ext & srcSuff), + dir / (name & ext & ExtSep & $(i+1))) + +method log*(logger: PRollingFileLogger, level: TLevel, + frmt: string, args: varargs[string, `$`]) = + ## Logs to a file using rolling ``logger`` only. + if level >= logger.levelThreshold: + if logger.curLine >= logger.maxLines: + logger.f.close() + rotate(logger) + logger.logFiles.inc + logger.curLine = 0 + logger.f = open(logger.baseName, logger.baseMode) + + writeln(logger.f, LevelNames[level], " ", frmt % args) + logger.curLine.inc + +# -------- + +var + level* = lvlAll ## global log filter + handlers*: seq[PLogger] = @[] ## handlers with their own log levels + +proc logLoop(level: TLevel, frmt: string, args: varargs[string, `$`]) = + for logger in items(handlers): + if level >= logger.levelThreshold: + log(logger, level, frmt, args) + +template log*(level: TLevel, frmt: string, args: varargs[string, `$`]) = + ## Logs a message to all registered handlers at the given level. + bind logLoop + bind `%` + bind logging.Level + + if level >= logging.Level: + logLoop(level, frmt, args) + +template debug*(frmt: string, args: varargs[string, `$`]) = + ## Logs a debug message to all registered handlers. + log(lvlDebug, frmt, args) + +template info*(frmt: string, args: varargs[string, `$`]) = + ## Logs an info message to all registered handlers. + log(lvlInfo, frmt, args) + +template warn*(frmt: string, args: varargs[string, `$`]) = + ## Logs a warning message to all registered handlers. + log(lvlWarn, frmt, args) + +template error*(frmt: string, args: varargs[string, `$`]) = + ## Logs an error message to all registered handlers. + log(lvlError, frmt, args) + +template fatal*(frmt: string, args: varargs[string, `$`]) = + ## Logs a fatal error message to all registered handlers. + log(lvlFatal, frmt, args) + + +# -------------- + +when isMainModule: + var L = newConsoleLogger() + var fL = newFileLogger("test.log", fmtStr = verboseFmtStr) + var rL = newRollingFileLogger("rolling.log", fmtStr = verboseFmtStr) + handlers.add(L) + handlers.add(fL) + handlers.add(rL) + for i in 0 .. 25: + info("hello" & $i, []) + + diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim index b57e0c45a..2db7fa660 100644 --- a/lib/pure/matchers.nim +++ b/lib/pure/matchers.nim @@ -54,7 +54,7 @@ proc parseInt*(s: string, value: var int, validRange: TSlice[int]) {. try: discard parseutils.parseInt(s, x, 0) except EOverflow: - nil + discard if x in validRange: value = x when isMainModule: diff --git a/lib/pure/net.nim b/lib/pure/net.nim new file mode 100644 index 000000000..bdcae677e --- /dev/null +++ b/lib/pure/net.nim @@ -0,0 +1,40 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2014 Dominik Picheta +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements a high-level cross-platform sockets interface. + +import sockets2, os + +type + TSocket* = TSocketHandle + +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. + + if address == "": + var name: TSockaddr_in + when defined(windows): + name.sin_family = toInt(AF_INET).int16 + else: + name.sin_family = toInt(AF_INET) + name.sin_port = htons(int16(port)) + name.sin_addr.s_addr = htonl(INADDR_ANY) + if bindAddr(socket, cast[ptr TSockAddr](addr(name)), + sizeof(name).TSocklen) < 0'i32: + osError(osLastError()) + else: + var aiList = getAddrInfo(address, port, AF_INET) + if bindAddr(socket, aiList.ai_addr, aiList.ai_addrlen.TSocklen) < 0'i32: + dealloc(aiList) + osError(osLastError()) + dealloc(aiList) \ No newline at end of file diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index fbe0dda95..b3e74d2a1 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -28,7 +28,7 @@ proc hexbyte*(hex: char): int = of '0'..'9': result = (ord(hex) - ord('0')) of 'a'..'f': result = (ord(hex) - ord('a') + 10) of 'A'..'F': result = (ord(hex) - ord('A') + 10) - else: nil + else: discard proc parseOid*(str: cstring): TOid = ## parses an OID. diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 1f42d0d58..bb70f28b6 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -287,12 +287,18 @@ proc osLastError*(): TOSErrorCode = result = TOSErrorCode(errno) {.pop.} -proc unixToNativePath*(path: string): string {. +proc unixToNativePath*(path: string, drive=""): string {. noSideEffect, rtl, extern: "nos$1".} = ## Converts an UNIX-like path to a native one. ## ## On an UNIX system this does nothing. Else it converts ## '/', '.', '..' to the appropriate things. + ## + ## On systems with a concept of "drives", `drive` is used to determine + ## which drive label to use during absolute path conversion. + ## `drive` defaults to the drive of the current working directory, and is + ## ignored on systems that do not have a concept of "drives". + when defined(unix): result = path else: @@ -300,7 +306,10 @@ proc unixToNativePath*(path: string): string {. if path[0] == '/': # an absolute path when doslike: - result = r"C:\" + if drive != "": + result = drive & ":" & DirSep + else: + result = $DirSep elif defined(macos): result = "" # must not start with ':' else: @@ -387,6 +396,21 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} = var res: TStat return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode) +proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1", + tags: [FReadDir].} = + ## Returns true iff the symlink `link` exists. Will return true + ## regardless of whether the link points to a directory or file. + when defined(windows): + when useWinUnicode: + wrapUnary(a, getFileAttributesW, link) + else: + var a = getFileAttributesA(link) + if a != -1'i32: + result = (a and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32 + else: + var res: TStat + return lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode) + proc fileExists*(filename: string): bool {.inline.} = ## Synonym for existsFile existsFile(filename) @@ -1013,7 +1037,7 @@ proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", ## the process has finished. To execute a program without having a ## shell involved, use the `execProcess` proc of the `osproc` ## module. - result = c_system(command) + result = c_system(command) shr 8 # Environment handling cannot be put into RTL, because the ``envPairs`` # iterator depends on ``environment``. @@ -1054,9 +1078,9 @@ when defined(windows): while true: var eend = strEnd(e) add(environment, $e) - e = cast[CString](cast[TAddress](eend)+1) + e = cast[cstring](cast[TAddress](eend)+1) if eend[1] == '\0': break - discard FreeEnvironmentStringsA(env) + discard freeEnvironmentStringsA(env) envComputed = true else: @@ -1221,6 +1245,8 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {. if not skipFindData(f): if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32: k = pcDir + if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32: + k = succ(k) yield (k, dir / extractFilename(getFilename(f))) if findNextFile(h, f) == 0'i32: break findClose(h) @@ -1245,6 +1271,10 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {. tags: [FReadDir].} = ## walks over the directory `dir` and yields for each file in `dir`. The ## full path for each file is returned. + ## **Warning**: + ## Modifying the directory structure while the iterator + ## is traversing may result in undefined behavior! + ## ## Walking is recursive. `filter` controls the behaviour of the iterator: ## ## --------------------- --------------------------------------------- @@ -1336,6 +1366,46 @@ proc copyDir*(source, dest: string) {.rtl, extern: "nos$1", copyDir(path, dest / noSource) else: discard +proc createSymlink*(src, dest: string) = + ## Create a symbolic link at `dest` which points to the item specified + ## by `src`. On most operating systems, will fail if a lonk + ## + ## **Warning**: + ## Some OS's (such as Microsoft Windows) restrict the creation + ## of symlinks to root users (administrators). + when defined(Windows): + let flag = dirExists(src).int32 + when useWinUnicode: + var wSrc = newWideCString(src) + var wDst = newWideCString(dest) + if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0: + osError(osLastError()) + else: + if createSymbolicLinkA(dest, src, flag) == 0 or getLastError() != 0: + osError(osLastError()) + else: + if symlink(src, dest) != 0: + osError(osLastError()) + +proc createHardlink*(src, dest: string) = + ## Create a hard link at `dest` which points to the item specified + ## by `src`. + ## + ## **Warning**: Most OS's restrict the creation of hard links to + ## root users (administrators) . + when defined(Windows): + when useWinUnicode: + var wSrc = newWideCString(src) + var wDst = newWideCString(dest) + if createHardLinkW(wDst, wSrc, nil) == 0: + osError(osLastError()) + else: + if createHardLinkA(dest, src, nil) == 0: + osError(osLastError()) + else: + if link(src, dest) != 0: + osError(osLastError()) + proc parseCmdLine*(c: string): seq[string] {. noSideEffect, rtl, extern: "nos$1".} = ## Splits a command line into several components; diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 676707abb..6df85bbc6 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -13,7 +13,7 @@ include "system/inclrtl" import - strutils, os, strtabs, streams + strutils, os, strtabs, streams, sequtils when defined(windows): import winlean @@ -36,11 +36,17 @@ type TProcessOption* = enum ## options that can be passed `startProcess` poEchoCmd, ## echo the command before execution - poUseShell, ## use the shell to execute the command; NOTE: This - ## often creates a security hole! + poUsePath, ## Asks system to search for executable using PATH environment + ## variable. + ## On Windows, this is the default. + poEvalCommand, ## Pass `command` directly to the shell, without quoting. + ## Use it only if `command` comes from trused source. poStdErrToStdOut, ## merge stdout and stderr to the stdout stream poParentStreams ## use the parent's streams +template poUseShell*: TProcessOption {.deprecated.} = poUsePath + ## Deprecated alias for poUsePath. + proc quoteShellWindows*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} = ## Quote s, so it can be safely passed to Windows API. ## Based on Python's subprocess.list2cmdline @@ -94,12 +100,17 @@ proc quoteShell*(s: string): string {.noSideEffect, rtl, extern: "nosp$1".} = {.error:"quoteShell is not supported on your system".} proc execProcess*(command: string, + args: openarray[string] = [], + env: PStringTable = nil, options: set[TProcessOption] = {poStdErrToStdOut, - poUseShell}): TaintedString {. + poUsePath, + poEvalCommand}): TaintedString {. rtl, extern: "nosp$1", tags: [FExecIO, FReadIO].} ## A convenience procedure that executes ``command`` with ``startProcess`` ## and returns its output as a string. + ## WARNING: this function uses poEvalCommand by default for backward compatibility. + ## Make sure to pass options explicitly. proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [FExecIO].} ## Executes ``command`` and returns its error code. Standard input, output, @@ -109,8 +120,8 @@ proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [FExecIO].} proc startProcess*(command: string, workingDir: string = "", args: openArray[string] = [], - env: PStringTable = nil, - options: set[TProcessOption] = {poStdErrToStdOut}): + env: PStringTable = nil, + options: set[TProcessOption] = {poStdErrToStdOut}): 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 @@ -127,16 +138,10 @@ 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, 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`. - var c = parseCmdLine(command) - var a: seq[string] - newSeq(a, c.len-1) # avoid slicing for now (still unstable) - for i in 1 .. c.len-1: a[i-1] = c[i] - result = startProcess(command=c[0], args=a, options=options) + poStdErrToStdOut, poUsePath}): PProcess {. + tags: [FExecIO, FReadEnv], deprecated.} = + ## Deprecated - use `startProcess` directly. + result = startProcess(command=command, options=options + {poEvalCommand}) proc close*(p: PProcess) {.rtl, extern: "nosp$1", tags: [].} ## When the process has finished executing, cleanup related handles @@ -157,7 +162,7 @@ proc processID*(p: PProcess): int {.rtl, extern: "nosp$1".} = ## returns `p`'s process ID. return p.id -proc waitForExit*(p: PProcess, timeout: int = -1): int {.rtl, +proc waitForExit*(p: PProcess, timeout: int = -1): int {.rtl, extern: "nosp$1", tags: [].} ## waits for the process to finish and returns `p`'s error code. @@ -167,19 +172,19 @@ proc peekExitCode*(p: PProcess): int {.tags: [].} proc inputStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].} ## returns ``p``'s input stream for writing to. ## - ## **Warning**: The returned `PStream` should not be closed manually as it + ## **Warning**: The returned `PStream` should not be closed manually as it ## is closed when closing the PProcess ``p``. proc outputStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].} ## returns ``p``'s output stream for reading from. ## - ## **Warning**: The returned `PStream` should not be closed manually as it + ## **Warning**: The returned `PStream` should not be closed manually as it ## is closed when closing the PProcess ``p``. proc errorStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].} ## returns ``p``'s error stream for reading from. ## - ## **Warning**: The returned `PStream` should not be closed manually as it + ## **Warning**: The returned `PStream` should not be closed manually as it ## is closed when closing the PProcess ``p``. proc inputHandle*(p: PProcess): TFileHandle {.rtl, extern: "nosp$1", @@ -245,15 +250,15 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} = proc execProcesses*(cmds: openArray[string], options = {poStdErrToStdOut, poParentStreams}, - n = countProcessors()): int {.rtl, extern: "nosp$1", - tags: [FExecIO, FTime, FReadEnv].} = + n = countProcessors()): int {.rtl, extern: "nosp$1", + 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. when defined(posix): # poParentStreams causes problems on Posix, so we simply disable it: var options = options - {poParentStreams} - + assert n > 0 if n > 1: var q: seq[PProcess] @@ -307,13 +312,17 @@ proc select*(readfds: var seq[PProcess], timeout = 500): int when not defined(useNimRtl): proc execProcess(command: string, + args: openarray[string] = [], + env: PStringTable = nil, options: set[TProcessOption] = {poStdErrToStdOut, - poUseShell}): TaintedString = - var p = startCmd(command, options=options) + poUsePath, + poEvalCommand}): TaintedString = + var p = startProcess(command, args=args, env=env, options=options) var outp = outputStream(p) result = TaintedString"" var line = newStringOfCap(120).TaintedString while true: + # FIXME: converts CR-LF to LF. if outp.readLine(line): result.string.add(line.string) result.string.add("\n") @@ -427,8 +436,9 @@ when defined(Windows) and not defined(useNimRtl): result.errHandle = TFileHandle(si.hStdError) var cmdl: cstring - when false: # poUseShell in options: - cmdl = buildCommandLine(getEnv("COMSPEC"), @["/c", command] & args) + if poEvalCommand in options: + cmdl = command + assert args.len == 0 else: cmdl = buildCommandLine(command, args) var wd: cstring = nil @@ -441,11 +451,11 @@ when defined(Windows) and not defined(useNimRtl): var ee = newWideCString(e) var wwd = newWideCString(wd) success = winlean.createProcessW(nil, - tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT, + tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT, ee, wwd, si, procInfo) else: success = winlean.createProcessA(nil, - cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo) + cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, si, procInfo) let lastError = osLastError() if poParentStreams notin options: @@ -455,7 +465,6 @@ when defined(Windows) and not defined(useNimRtl): fileClose(si.hStdError) if e != nil: dealloc(e) - dealloc(cmdl) if success == 0: osError(lastError) # Close the handle now so anyone waiting is woken: discard closeHandle(procInfo.hThread) @@ -495,7 +504,7 @@ when defined(Windows) and not defined(useNimRtl): proc peekExitCode(p: PProcess): int = var b = waitForSingleObject(p.fProcessHandle, 50) == WAIT_TIMEOUT if b: result = -1 - else: + else: var res: int32 discard getExitCodeProcess(p.fProcessHandle, res) return res @@ -525,7 +534,7 @@ when defined(Windows) and not defined(useNimRtl): NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo) else: var res = winlean.createProcessA(nil, command, nil, nil, 0, - NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo) + NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo) if res == 0: osError(osLastError()) else: @@ -538,13 +547,13 @@ when defined(Windows) and not defined(useNimRtl): result = -1 discard closeHandle(process) - proc select(readfds: var seq[PProcess], timeout = 500): int = + proc select(readfds: var seq[PProcess], timeout = 500): int = assert readfds.len <= MAXIMUM_WAIT_OBJECTS var rfds: TWOHandleArray for i in 0..readfds.len()-1: rfds[i] = readfds[i].fProcessHandle - - var ret = waitForMultipleObjects(readfds.len.int32, + + var ret = waitForMultipleObjects(readfds.len.int32, addr(rfds), 0'i32, timeout.int32) case ret of WAIT_TIMEOUT: @@ -561,22 +570,7 @@ elif not defined(useNimRtl): readIdx = 0 writeIdx = 1 - proc addCmdArgs(command: string, args: openArray[string]): string = - result = quoteShell(command) - for i in 0 .. high(args): - add(result, " ") - add(result, quoteShell(args[i])) - - proc toCStringArray(b, a: openArray[string]): cstringArray = - result = cast[cstringArray](alloc0((a.len + b.len + 1) * sizeof(cstring))) - for i in 0..high(b): - result[i] = cast[cstring](alloc(b[i].len+1)) - copyMem(result[i], cstring(b[i]), b[i].len+1) - for i in 0..high(a): - result[i+b.len] = cast[cstring](alloc(a[i].len+1)) - copyMem(result[i+b.len], cstring(a[i]), a[i].len+1) - - proc toCStringArray(t: PStringTable): cstringArray = + proc envToCStringArray(t: PStringTable): cstringArray = result = cast[cstringArray](alloc0((t.len + 1) * sizeof(cstring))) var i = 0 for key, val in pairs(t): @@ -595,7 +589,7 @@ elif not defined(useNimRtl): result[i] = cast[cstring](alloc(x.len+1)) copyMem(result[i], addr(x[0]), x.len+1) inc(i) - + proc startProcess(command: string, workingDir: string = "", args: openArray[string] = [], @@ -609,23 +603,38 @@ elif not defined(useNimRtl): if pipe(pStdin) != 0'i32 or pipe(pStdout) != 0'i32 or pipe(pStderr) != 0'i32: osError(osLastError()) - + + var sys_command: string + var sys_args_raw: seq[string] + if poEvalCommand in options: + sys_command = "/bin/sh" + sys_args_raw = @[sys_command, "-c", command] + assert args.len == 0 + else: + sys_command = command + sys_args_raw = @[command] + for arg in args.items: + sys_args_raw.add arg + + var sys_args = allocCStringArray(sys_args_raw) + finally: deallocCStringArray(sys_args) + var pid: TPid when defined(posix_spawn) and not defined(useFork): var attr: Tposix_spawnattr var fops: Tposix_spawn_file_actions - template chck(e: expr) = + template chck(e: expr) = if e != 0'i32: osError(osLastError()) chck posix_spawn_file_actions_init(fops) chck posix_spawnattr_init(attr) - + var mask: Tsigset chck sigemptyset(mask) chck posix_spawnattr_setsigmask(attr, mask) chck posix_spawnattr_setpgroup(attr, 0'i32) - + chck posix_spawnattr_setflags(attr, POSIX_SPAWN_USEVFORK or POSIX_SPAWN_SETSIGMASK or POSIX_SPAWN_SETPGROUP) @@ -639,27 +648,22 @@ elif not defined(useNimRtl): if poStdErrToStdOut in options: chck posix_spawn_file_actions_adddup2(fops, pStdout[writeIdx], 2) else: - chck posix_spawn_file_actions_adddup2(fops, pStderr[writeIdx], 2) - - var e = if env == nil: envToCStringArray() else: toCStringArray(env) - var a: cstringArray + chck posix_spawn_file_actions_adddup2(fops, p_stderr[writeIdx], 2) + + var sys_env = if env == nil: envToCStringArray() else: envToCStringArray(env) var res: cint + # This is incorrect! if workingDir.len > 0: os.setCurrentDir(workingDir) - if poUseShell notin options: - a = toCStringArray([extractFilename(command)], args) - res = posix_spawn(pid, command, fops, attr, a, e) + if poUsePath in options: + res = posix_spawnp(pid, sys_command, fops, attr, sys_args, sys_env) else: - var x = addCmdArgs(command, args) - a = toCStringArray(["sh", "-c"], [x]) - res = posix_spawn(pid, "/bin/sh", fops, attr, a, e) - deallocCStringArray(a) - deallocCStringArray(e) + res = posix_spawn(pid, sys_command, fops, attr, sys_args, sys_env) + deallocCStringArray(sys_env) discard posix_spawn_file_actions_destroy(fops) discard posix_spawnattr_destroy(attr) chck res else: - pid = fork() if pid < 0: osError(osLastError()) if pid == 0: @@ -680,19 +684,18 @@ elif not defined(useNimRtl): if setpgid(0, 0) == -1: quit("setpgid call failed: " & $strerror(errno)) if workingDir.len > 0: os.setCurrentDir(workingDir) - if poUseShell notin options: - var a = toCStringArray([extractFilename(command)], args) - if env == nil: - discard execv(command, a) + + if env == nil: + if poUsePath in options: + discard execvp(sys_command, sys_args) else: - discard execve(command, a, toCStringArray(env)) + discard execv(sys_command, sys_args) else: - var x = addCmdArgs(command, args) - var a = toCStringArray(["sh", "-c"], [x]) - if env == nil: - discard execv("/bin/sh", a) + var c_env = envToCStringArray(env) + if poUsePath in options: + discard execvpe(sys_command, sys_args, c_env) else: - discard execve("/bin/sh", a, toCStringArray(env)) + discard execve(sys_command, sys_args, c_env) # too risky to raise an exception here: quit("execve call failed: " & $strerror(errno)) # Parent process. Copy process information. @@ -788,15 +791,15 @@ elif not defined(useNimRtl): proc csystem(cmd: cstring): cint {.nodecl, importc: "system".} proc execCmd(command: string): int = - result = csystem(command) + result = csystem(command) shr 8 - proc createFdSet(fd: var TFdSet, s: seq[PProcess], m: var int) = + proc createFdSet(fd: var TFdSet, s: seq[PProcess], m: var int) = FD_ZERO(fd) - for i in items(s): + for i in items(s): m = max(m, int(i.outHandle)) FD_SET(cint(i.outHandle), fd) - - proc pruneProcessSet(s: var seq[PProcess], fd: var TFdSet) = + + proc pruneProcessSet(s: var seq[PProcess], fd: var TFdSet) = var i = 0 var L = s.len while i < L: @@ -807,26 +810,26 @@ elif not defined(useNimRtl): inc(i) setLen(s, L) - proc select(readfds: var seq[PProcess], timeout = 500): int = - var tv: Ttimeval + proc select(readfds: var seq[PProcess], timeout = 500): int = + var tv: TTimeVal tv.tv_sec = 0 tv.tv_usec = timeout * 1000 - + var rd: TFdSet var m = 0 createFdSet((rd), readfds, m) - + if timeout != -1: result = int(select(cint(m+1), addr(rd), nil, nil, addr(tv))) else: result = int(select(cint(m+1), addr(rd), nil, nil, nil)) - + pruneProcessSet(readfds, (rd)) proc execCmdEx*(command: string, options: set[TProcessOption] = { - poStdErrToStdOut, poUseShell}): tuple[ - output: TaintedString, + poStdErrToStdOut, poUsePath}): tuple[ + output: TaintedString, exitCode: int] {.tags: [FExecIO, FReadIO].} = ## a convenience proc that runs the `command`, grabs all its output and ## exit code and returns both. diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim index 5970f2090..4b25babec 100644 --- a/lib/pure/parsecsv.nim +++ b/lib/pure/parsecsv.nim @@ -149,7 +149,7 @@ proc readRow*(my: var TCsvParser, columns = 0): bool = of '\c': my.bufpos = handleCR(my, my.bufpos) of '\l': my.bufpos = handleLF(my, my.bufpos) else: break - of '\0': nil + of '\0': discard else: error(my, my.bufpos, my.sep & " expected") break diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim index 31951e966..3f9686e1e 100644 --- a/lib/pure/parsesql.nim +++ b/lib/pure/parsesql.nim @@ -79,7 +79,7 @@ proc handleHexChar(c: var TSqlLexer, xi: var int) = xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10) inc(c.bufpos) else: - nil + discard proc handleOctChar(c: var TSqlLexer, xi: var int) = if c.buf[c.bufpos] in {'0'..'7'}: @@ -373,7 +373,7 @@ proc getOperator(c: var TSqlLexer, tok: var TToken) = of '+': if not trailingPlusMinus and buf[pos+1] notin operators and tok.literal.len > 0: break - of '*', '<', '>', '=': nil + of '*', '<', '>', '=': discard else: break add(tok.literal, buf[pos]) inc(pos) @@ -1120,7 +1120,7 @@ proc rs(n: PSqlNode, s: var string, indent: int, proc ra(n: PSqlNode, s: var string, indent: int) = if n == nil: return case n.kind - of nkNone: nil + of nkNone: discard of nkIdent: if allCharsInSet(n.strVal, {'\33'..'\127'}): s.add(n.strVal) diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim new file mode 100644 index 000000000..83c158da1 --- /dev/null +++ b/lib/pure/selectors.nim @@ -0,0 +1,249 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2013 Dominik Picheta +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# TODO: Docs. + +import tables, os, unsigned +when defined(windows): + import winlean +else: + import posix + +type + TEvent* = enum + EvRead, EvWrite + + TSelectorKey* = object + fd: cint + events: set[TEvent] + data: PObject + + TReadyInfo* = tuple[key: TSelectorKey, events: set[TEvent]] + + PSelector* = ref object of PObject ## Selector interface. + fds*: TTable[cint, TSelectorKey] + registerImpl*: proc (s: PSelector, fd: cint, events: set[TEvent], + data: PObject): TSelectorKey {.nimcall, tags: [FWriteIO].} + unregisterImpl*: proc (s: PSelector, fd: cint): TSelectorKey {.nimcall, tags: [FWriteIO].} + selectImpl*: proc (s: PSelector, timeout: int): seq[TReadyInfo] {.nimcall, tags: [FReadIO].} + closeImpl*: proc (s: PSelector) {.nimcall.} + +template initSelector(r: expr) = + new r + r.fds = initTable[cint, TSelectorKey]() + +proc register*(s: PSelector, fd: cint, events: set[TEvent], data: PObject): + TSelectorKey = + if not s.registerImpl.isNil: result = s.registerImpl(s, fd, events, data) + +proc unregister*(s: PSelector, fd: cint): TSelectorKey = + ## + ## **Note:** For the ``epoll`` implementation the resulting ``TSelectorKey`` + ## will only have the ``fd`` field set. This is an optimisation and may + ## change in the future if a viable use case is presented. + if not s.unregisterImpl.isNil: result = s.unregisterImpl(s, fd) + +proc select*(s: PSelector, timeout = 500): seq[TReadyInfo] = + ## + ## The ``events`` field of the returned ``key`` contains the original events + ## for which the ``fd`` was bound. This is contrary to the ``events`` field + ## of the ``TReadyInfo`` tuple which determines which events are ready + ## on the ``fd``. + + if not s.selectImpl.isNil: result = s.selectImpl(s, timeout) + +proc close*(s: PSelector) = + if not s.closeImpl.isNil: s.closeImpl(s) + +# ---- Select() ---------------------------------------------------------------- + +type + PSelectSelector* = ref object of PSelector ## Implementation of select() + +proc ssRegister(s: PSelector, fd: cint, events: set[TEvent], + data: PObject): TSelectorKey = + if s.fds.hasKey(fd): + raise newException(EInvalidValue, "FD already exists in selector.") + var sk = TSelectorKey(fd: fd, events: events, data: data) + s.fds[fd] = sk + result = sk + +proc ssUnregister(s: PSelector, fd: cint): TSelectorKey = + result = s.fds[fd] + s.fds.del(fd) + +proc ssClose(s: PSelector) = nil + +proc timeValFromMilliseconds(timeout: int): TTimeVal = + if timeout != -1: + var seconds = timeout div 1000 + result.tv_sec = seconds.int32 + result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 + +proc createFdSet(rd, wr: var TFdSet, fds: TTable[cint, TSelectorKey], + m: var int) = + FD_ZERO(rd); FD_ZERO(wr) + for k, v in pairs(fds): + if EvRead in v.events: + m = max(m, int(k)) + FD_SET(k, rd) + if EvWrite in v.events: + m = max(m, int(k)) + FD_SET(k, wr) + +proc getReadyFDs(rd, wr: var TFdSet, fds: TTable[cint, TSelectorKey]): + seq[TReadyInfo] = + result = @[] + for k, v in pairs(fds): + var events: set[TEvent] = {} + if FD_ISSET(k, rd) != 0'i32: + events = events + {EvRead} + if FD_ISSET(k, wr) != 0'i32: + events = events + {EvWrite} + result.add((v, events)) + +proc select(fds: TTable[cint, TSelectorKey], timeout = 500): + seq[TReadyInfo] = + var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout) + + var rd, wr: TFdSet + var m = 0 + createFdSet(rd, wr, fds, m) + + var retCode = 0 + if timeout != -1: + retCode = int(select(cint(m+1), addr(rd), addr(wr), nil, addr(tv))) + else: + retCode = int(select(cint(m+1), addr(rd), addr(wr), nil, nil)) + + if retCode < 0: + OSError(OSLastError()) + elif retCode == 0: + return @[] + else: + return getReadyFDs(rd, wr, fds) + +proc ssSelect(s: PSelector, timeout: int): seq[TReadyInfo] = + result = select(s.fds, timeout) + +proc newSelectSelector*(): PSelectSelector = + initSelector(result) + result.registerImpl = ssRegister + result.unregisterImpl = ssUnregister + result.selectImpl = ssSelect + result.closeImpl = ssClose + +# ---- Epoll ------------------------------------------------------------------- + +when defined(linux): + import epoll + type + PEpollSelector* = ref object of PSelector + epollFD: cint + events: array[64, ptr epoll_event] + + TDataWrapper = object + fd: cint + boundEvents: set[TEvent] ## The events which ``fd`` listens for. + data: PObject ## User object. + + proc esRegister(s: PSelector, fd: cint, events: set[TEvent], + data: PObject): TSelectorKey = + var es = PEpollSelector(s) + var event: epoll_event + if EvRead in events: + event.events = EPOLLIN + if EvWrite in events: + event.events = event.events or EPOLLOUT + + var dw = cast[ptr TDataWrapper](alloc0(sizeof(TDataWrapper))) # TODO: This needs to be dealloc'd + dw.fd = fd + dw.boundEvents = events + dw.data = data + event.data.thePtr = dw + + if epoll_ctl(es.epollFD, EPOLL_CTL_ADD, fd, addr(event)) != 0: + OSError(OSLastError()) + + result = TSelectorKey(fd: fd, events: events, data: data) + + proc esUnregister(s: PSelector, fd: cint): TSelectorKey = + # We cannot find out the information about this ``fd`` from the epoll + # context. As such I will simply return an almost empty TSelectorKey. + var es = PEpollSelector(s) + if epoll_ctl(es.epollFD, EPOLL_CTL_DEL, fd, nil) != 0: + OSError(OSLastError()) + # We could fill in the ``fds`` TTable to get the info, but that wouldn't + # be nice for our memory. + result = TSelectorKey(fd: fd, events: {}, data: nil) + + proc esClose(s: PSelector) = + var es = PEpollSelector(s) + if es.epollFD.close() != 0: OSError(OSLastError()) + dealloc(addr es.events) # TODO: Test this + + proc esSelect(s: PSelector, timeout: int): seq[TReadyInfo] = + result = @[] + var es = PEpollSelector(s) + + let evNum = epoll_wait(es.epollFD, es.events[0], 64.cint, timeout.cint) + if evNum < 0: OSError(OSLastError()) + if evNum == 0: return @[] + for i in 0 .. <evNum: + var evSet: set[TEvent] = {} + if (es.events[i].events and EPOLLIN) != 0: evSet = evSet + {EvRead} + if (es.events[i].events and EPOLLOUT) != 0: evSet = evSet + {EvWrite} + let dw = cast[ptr TDataWrapper](es.events[i].data.thePtr) + + let selectorKey = TSelectorKey(fd: dw.fd, events: dw.boundEvents, + data: dw.data) + result.add((selectorKey, evSet)) + + proc newEpollSelector*(): PEpollSelector = + new result + result.epollFD = epoll_create(64) + result.events = cast[array[64, ptr epoll_event]](alloc0(sizeof(epoll_event)*64)) + if result.epollFD < 0: + OSError(OSLastError()) + result.registerImpl = esRegister + result.unregisterImpl = esUnregister + result.closeImpl = esClose + result.selectImpl = esSelect + +when isMainModule: + # Select() + import sockets + type + PSockWrapper = ref object of PObject + sock: TSocket + + var sock = socket() + sock.connect("irc.freenode.net", TPort(6667)) + + var selector = newEpollSelector() + var data = PSockWrapper(sock: sock) + let key = selector.register(sock.getFD.cint, {EvRead}, data) + var i = 0 + while true: + let ready = selector.select(1000) + echo ready.len + if ready.len > 0: echo ready[0].events + i.inc + if i == 6: + selector.close() + break + + + + + + + + + \ No newline at end of file diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim index 6a3f65279..88afeb589 100644 --- a/lib/pure/smtp.nim +++ b/lib/pure/smtp.nim @@ -66,13 +66,15 @@ proc checkReply(smtp: var TSMTP, reply: string) = if not line.string.startswith(reply): quitExcpt(smtp, "Expected " & reply & " reply, got: " & line.string) +const compiledWithSsl = defined(ssl) + proc connect*(address: string, port = 25, ssl = false, debug = false): TSMTP = ## Establishes a connection with a SMTP server. ## May fail with EInvalidReply or with a socket error. result.sock = socket() if ssl: - when defined(ssl): + when compiledWithSsl: let ctx = newContext(verifyMode = CVerifyNone) ctx.wrapSocket(result.sock) else: diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index fd6403118..76d37879b 100644 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -311,7 +311,8 @@ when defined(ssl): newCTX.SSLCTXSetVerify(SSLVerifyNone, nil) if newCTX == nil: SSLError() - + + discard newCTX.SSLCTXSetMode(SSL_MODE_AUTO_RETRY) newCTX.loadCertificates(certFile, keyFile) return PSSLContext(newCTX) @@ -1291,14 +1292,14 @@ proc readLine*(socket: TSocket, line: var TaintedString, timeout = -1) {. var c: char discard waitFor(socket, waited, timeout, 1, "readLine") var n = recv(socket, addr(c), 1) - if n < 0: osError(osLastError()) + if n < 0: socket.socketError() elif n == 0: return if c == '\r': discard waitFor(socket, waited, timeout, 1, "readLine") n = peekChar(socket, c) if n > 0 and c == '\L': discard recv(socket, addr(c), 1) - elif n <= 0: osError(osLastError()) + elif n <= 0: socket.socketError() addNLIfEmpty() return elif c == '\L': diff --git a/lib/pure/sockets2.nim b/lib/pure/sockets2.nim new file mode 100644 index 000000000..22624bbad --- /dev/null +++ b/lib/pure/sockets2.nim @@ -0,0 +1,202 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2014 Dominik Picheta +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements a low-level cross-platform sockets interface. Look +## at the ``net`` module for the higher-level version. + +import unsigned, os + +when hostos == "solaris": + {.passl: "-lsocket -lnsl".} + +when defined(Windows): + import winlean +else: + import posix + +export TSocketHandle, TSockaddr_in, TAddrinfo, INADDR_ANY, TSockAddr, TSockLen, + inet_ntoa + +type + + TPort* = distinct uint16 ## port type + + TDomain* = enum ## domain, which specifies the protocol family of the + ## created socket. Other domains than those that are listed + ## here are unsupported. + AF_UNIX, ## for local socket (using a file). Unsupported on Windows. + AF_INET = 2, ## for network protocol IPv4 or + AF_INET6 = 23 ## for network protocol IPv6. + + TType* = enum ## second argument to `socket` proc + SOCK_STREAM = 1, ## reliable stream-oriented service or Stream Sockets + SOCK_DGRAM = 2, ## datagram service or Datagram Sockets + SOCK_RAW = 3, ## raw protocols atop the network layer. + SOCK_SEQPACKET = 5 ## reliable sequenced packet service + + TProtocol* = enum ## third argument to `socket` proc + IPPROTO_TCP = 6, ## Transmission control protocol. + IPPROTO_UDP = 17, ## User datagram protocol. + IPPROTO_IP, ## Internet protocol. Unsupported on Windows. + IPPROTO_IPV6, ## Internet Protocol Version 6. Unsupported on Windows. + IPPROTO_RAW, ## Raw IP Packets Protocol. Unsupported on Windows. + IPPROTO_ICMP ## Control message protocol. Unsupported on Windows. + + TServent* {.pure, final.} = object ## information about a service + name*: string + aliases*: seq[string] + port*: TPort + proto*: string + + Thostent* {.pure, final.} = object ## information about a given host + name*: string + aliases*: seq[string] + addrtype*: TDomain + length*: int + addrList*: seq[string] + +when defined(windows): + let + OSInvalidSocket* = winlean.INVALID_SOCKET +else: + let + OSInvalidSocket* = posix.INVALID_SOCKET + +proc `==`*(a, b: TPort): bool {.borrow.} + ## ``==`` for ports. + +proc `$`*(p: TPort): string {.borrow.} + ## returns the port number as a string + +proc toInt*(domain: TDomain): cint + ## Converts the TDomain enum to a platform-dependent ``cint``. + +proc toInt*(typ: TType): cint + ## Converts the TType enum to a platform-dependent ``cint``. + +proc toInt*(p: TProtocol): cint + ## Converts the TProtocol enum to a platform-dependent ``cint``. + +when defined(posix): + proc toInt(domain: TDomain): cint = + case domain + of AF_UNIX: result = posix.AF_UNIX + of AF_INET: result = posix.AF_INET + of AF_INET6: result = posix.AF_INET6 + else: nil + + proc toInt(typ: TType): cint = + case typ + of SOCK_STREAM: result = posix.SOCK_STREAM + of SOCK_DGRAM: result = posix.SOCK_DGRAM + of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET + of SOCK_RAW: result = posix.SOCK_RAW + else: nil + + proc toInt(p: TProtocol): cint = + case p + of IPPROTO_TCP: result = posix.IPPROTO_TCP + of IPPROTO_UDP: result = posix.IPPROTO_UDP + of IPPROTO_IP: result = posix.IPPROTO_IP + of IPPROTO_IPV6: result = posix.IPPROTO_IPV6 + of IPPROTO_RAW: result = posix.IPPROTO_RAW + of IPPROTO_ICMP: result = posix.IPPROTO_ICMP + else: nil + +else: + proc toInt(domain: TDomain): cint = + result = toU16(ord(domain)) + + proc toInt(typ: TType): cint = + result = cint(ord(typ)) + + proc toInt(p: TProtocol): cint = + result = cint(ord(p)) + + +proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM, + protocol: TProtocol = IPPROTO_TCP): TSocketHandle = + ## Creates a new socket; returns `InvalidSocket` if an error occurs. + + # TODO: The function which will use this will raise EOS. + socket(toInt(domain), toInt(typ), toInt(protocol)) + +proc close*(socket: TSocketHandle) = + ## closes a socket. + when defined(windows): + discard winlean.closeSocket(socket) + else: + discard posix.close(socket) + # TODO: These values should not be discarded. An EOS should be raised. + # http://stackoverflow.com/questions/12463473/what-happens-if-you-call-close-on-a-bsd-socket-multiple-times + +proc bindAddr*(socket: TSocketHandle, name: ptr TSockAddr, namelen: TSockLen): cint = + result = bindSocket(socket, name, namelen) + +proc listen*(socket: TSocketHandle, backlog = SOMAXCONN) {.tags: [FReadIO].} = + ## Marks ``socket`` as accepting connections. + ## ``Backlog`` specifies the maximum length of the + ## queue of pending connections. + when defined(windows): + if winlean.listen(socket, cint(backlog)) < 0'i32: osError(osLastError()) + else: + if posix.listen(socket, cint(backlog)) < 0'i32: osError(osLastError()) + +proc getAddrInfo*(address: string, port: TPort, af: TDomain = AF_INET, typ: TType = SOCK_STREAM, + prot: TProtocol = IPPROTO_TCP): ptr TAddrInfo = + ## + ## + ## **Warning**: The resulting ``ptr TAddrInfo`` must be freed using ``dealloc``! + var hints: TAddrInfo + result = nil + hints.ai_family = toInt(af) + hints.ai_socktype = toInt(typ) + hints.ai_protocol = toInt(prot) + var gaiResult = getAddrInfo(address, $port, addr(hints), result) + if gaiResult != 0'i32: + when defined(windows): + OSError(OSLastError()) + else: + raise newException(EOS, $gai_strerror(gaiResult)) + +proc dealloc*(ai: ptr TAddrInfo) = + freeaddrinfo(ai) + +proc ntohl*(x: int32): int32 = + ## Converts 32-bit integers from network to host byte order. + ## On machines where the host byte order is the same as network byte order, + ## this is a no-op; otherwise, it performs a 4-byte swap operation. + when cpuEndian == bigEndian: result = x + else: result = (x shr 24'i32) or + (x shr 8'i32 and 0xff00'i32) or + (x shl 8'i32 and 0xff0000'i32) or + (x shl 24'i32) + +proc ntohs*(x: int16): int16 = + ## Converts 16-bit integers from network to host byte order. On machines + ## where the host byte order is the same as network byte order, this is + ## a no-op; otherwise, it performs a 2-byte swap operation. + when cpuEndian == bigEndian: result = x + else: result = (x shr 8'i16) or (x shl 8'i16) + +proc htonl*(x: int32): int32 = + ## Converts 32-bit integers from host to network byte order. On machines + ## where the host byte order is the same as network byte order, this is + ## a no-op; otherwise, it performs a 4-byte swap operation. + result = sockets2.ntohl(x) + +proc htons*(x: int16): int16 = + ## Converts 16-bit positive integers from host to network byte order. + ## On machines where the host byte order is the same as network byte + ## order, this is a no-op; otherwise, it performs a 2-byte swap operation. + result = sockets2.ntohs(x) + +when defined(Windows): + var wsa: TWSADATA + if WSAStartup(0x0101'i16, addr wsa) != 0: OSError(OSLastError()) \ No newline at end of file diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index de8dc5e51..b63224cec 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -45,6 +45,16 @@ const NewLines* = {'\13', '\10'} ## the set of characters a newline terminator can start with + AllChars* = {'\x00'..'\xFF'} + ## A set with all the possible characters. Not very useful by its own, you + ## can use it to create *inverted* sets to make the ``find()`` proc find + ## **invalid** characters in strings. Example: + ## + ## .. code-block:: nimrod + ## let invalid = AllChars - Digits + ## doAssert "01234".find(invalid) == -1 + ## doAssert "01A34".find(invalid) == 2 + proc toLower*(c: char): char {.noSideEffect, procvar, rtl, extern: "nsuToLowerChar".} = ## Converts `c` into lower case. This works only for the letters A-Z. diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 6186fcad8..de6c4e4fa 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -211,7 +211,9 @@ proc initInterval*(miliseconds, seconds, minutes, hours, days, months, result.months = months result.years = years -proc isLeapYear(year: int): bool = +proc isLeapYear*(year: int): bool = + ## returns true if ``year`` is a leap year + if year mod 400 == 0: return true elif year mod 100 == 0: @@ -221,7 +223,9 @@ proc isLeapYear(year: int): bool = else: return false -proc getDaysInMonth(month: TMonth, year: int): int = +proc getDaysInMonth*(month: TMonth, year: int): int = + ## gets the amount of days in a ``month`` of a ``year`` + # http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month case month of mFeb: result = if isLeapYear(year): 29 else: 28 diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim index 16bbe1455..8b8bb3b03 100644 --- a/lib/pure/xmlparser.nim +++ b/lib/pure/xmlparser.nim @@ -96,7 +96,7 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode = ## &entity; errors.add(errorMsg(x, "unknown entity: " & x.entityName)) next(x) - of xmlEof: nil + of xmlEof: discard proc parseXml*(s: PStream, filename: string, errors: var seq[string]): PXmlNode = @@ -110,7 +110,7 @@ proc parseXml*(s: PStream, filename: string, of xmlElementOpen, xmlElementStart: result = parse(x, errors) break - of xmlComment, xmlWhitespace, xmlSpecial, xmlPI: nil # just skip it + of xmlComment, xmlWhitespace, xmlSpecial, xmlPI: discard # just skip it of xmlError: errors.add(errorMsg(x)) else: diff --git a/lib/system.nim b/lib/system.nim index 09e44a45a..2acb989c5 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2333,29 +2333,29 @@ when not defined(JS): #and not defined(NimrodVM): elif defined(JS): # Stubs: - proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = nil - - proc GC_disable() = nil - proc GC_enable() = nil - proc GC_fullCollect() = nil - proc GC_setStrategy(strategy: TGC_Strategy) = nil - proc GC_enableMarkAndSweep() = nil - proc GC_disableMarkAndSweep() = nil + proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = discard + + proc GC_disable() = discard + proc GC_enable() = discard + proc GC_fullCollect() = discard + proc GC_setStrategy(strategy: TGC_Strategy) = discard + proc GC_enableMarkAndSweep() = discard + proc GC_disableMarkAndSweep() = discard proc GC_getStatistics(): string = return "" proc getOccupiedMem(): int = return -1 proc getFreeMem(): int = return -1 proc getTotalMem(): int = return -1 - proc dealloc(p: pointer) = nil - proc alloc(size: int): pointer = nil - proc alloc0(size: int): pointer = nil - proc realloc(p: Pointer, newsize: int): pointer = nil + proc dealloc(p: pointer) = discard + proc alloc(size: int): pointer = discard + proc alloc0(size: int): pointer = discard + proc realloc(p: Pointer, newsize: int): pointer = discard - proc allocShared(size: int): pointer = nil - proc allocShared0(size: int): pointer = nil - proc deallocShared(p: pointer) = nil - proc reallocShared(p: pointer, newsize: int): pointer = nil + proc allocShared(size: int): pointer = discard + proc allocShared0(size: int): pointer = discard + proc deallocShared(p: pointer) = discard + proc reallocShared(p: pointer, newsize: int): pointer = discard when defined(JS): include "system/jssys" @@ -2490,11 +2490,11 @@ proc staticRead*(filename: string): string {.magic: "Slurp".} ## ``slurp`` is an alias for ``staticRead``. proc gorge*(command: string, input = ""): string {. - magic: "StaticExec".} = nil + magic: "StaticExec".} = discard ## This is an alias for ``staticExec``. proc staticExec*(command: string, input = ""): string {. - magic: "StaticExec".} = nil + magic: "StaticExec".} = discard ## Executes an external process at compile-time. ## if `input` is not an empty string, it will be passed as a standard input ## to the executed program. @@ -2561,7 +2561,7 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[ ## $pos.line, astToStr(code)] ## assert false, "A test expecting failure succeeded?" ## except exception: - ## nil + ## discard ## ## proc tester(pos: int): int = ## let diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index a3f6669d4..e50ba7b9f 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -23,7 +23,7 @@ else: proc MessageBoxA(hWnd: cint, lpText, lpCaption: cstring, uType: int): int32 {. header: "<windows.h>", nodecl.} - proc writeToStdErr(msg: CString) = + proc writeToStdErr(msg: cstring) = discard MessageBoxA(0, msg, nil, 0) proc showErrorMessage(data: cstring) = diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 820093b3e..b08a6d214 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -802,7 +802,7 @@ when defined(sparc): # For SPARC architecture. # Addresses decrease as the stack grows. while sp <= max: gcMark(gch, sp[]) - sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer)) + sp = cast[PPointer](cast[TAddress](sp) +% sizeof(pointer)) elif defined(ELATE): {.error: "stack marking code is to be written for this architecture".} diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index 2e3596985..e78a4e5cd 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2013 Andreas Rumpf +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -59,11 +59,11 @@ var gch {.rtlThreadVar.}: TGcHeap when not defined(useNimRtl): - InstantiateForRegion(gch.region) + instantiateForRegion(gch.region) template acquire(gch: TGcHeap) = when hasThreadSupport and hasSharedHeap: - AcquireSys(HeapLock) + acquireSys(HeapLock) template release(gch: TGcHeap) = when hasThreadSupport and hasSharedHeap: @@ -90,7 +90,7 @@ proc extGetCellType(c: pointer): PNimType {.compilerproc.} = # used for code generation concerning debugging result = usrToCell(c).typ -proc unsureAsgnRef(dest: ppointer, src: pointer) {.inline.} = +proc unsureAsgnRef(dest: PPointer, src: pointer) {.inline.} = dest[] = src proc internRefcount(p: pointer): int {.exportc: "getRefcount".} = @@ -114,10 +114,10 @@ when BitsPerPage mod (sizeof(int)*8) != 0: # forward declarations: proc collectCT(gch: var TGcHeap) -proc IsOnStack*(p: pointer): bool {.noinline.} +proc isOnStack*(p: pointer): bool {.noinline.} proc forAllChildren(cell: PCell, op: TWalkOp) proc doOperation(p: pointer, op: TWalkOp) -proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) +proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) # we need the prototype here for debugging purposes proc prepareDealloc(cell: PCell) = @@ -162,19 +162,19 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) = if m != nil: forAllSlotsAux(dest, m, op) of nkNone: sysAssert(false, "forAllSlotsAux") -proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) = +proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) = var d = cast[TAddress](dest) if dest == nil: return # nothing to do if ntfNoRefs notin mt.flags: - case mt.Kind + case mt.kind of tyRef, tyString, tySequence: # leaf: - doOperation(cast[ppointer](d)[], op) + doOperation(cast[PPointer](d)[], op) of tyObject, tyTuple: forAllSlotsAux(dest, mt.node, op) of tyArray, tyArrayConstr, tyOpenArray: for i in 0..(mt.size div mt.base.size)-1: forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op) - else: nil + else: discard proc forAllChildren(cell: PCell, op: TWalkOp) = gcAssert(cell != nil, "forAllChildren: 1") @@ -184,7 +184,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) = if marker != nil: marker(cellToUsr(cell), op.int) else: - case cell.typ.Kind + case cell.typ.kind of tyRef: # common case forAllChildrenAux(cellToUsr(cell), cell.typ.base, op) of tySequence: @@ -194,7 +194,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) = for i in 0..s.len-1: forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +% GenericSeqSize), cell.typ.base, op) - else: nil + else: discard proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer = # generates a new object and sets its reference counter to 0 @@ -466,7 +466,7 @@ else: sp = sp +% sizeof(pointer)*8 # last few entries: while sp <=% max: - gcMark(gch, cast[ppointer](sp)[]) + gcMark(gch, cast[PPointer](sp)[]) sp = sp +% sizeof(pointer) # ---------------------------------------------------------------------------- @@ -505,7 +505,7 @@ when not defined(useNimRtl): else: dec(gch.recGcLock) - proc GC_setStrategy(strategy: TGC_Strategy) = nil + proc GC_setStrategy(strategy: TGC_Strategy) = discard proc GC_enableMarkAndSweep() = gch.cycleThreshold = InitialThreshold diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 91c6495ce..6c8fa4882 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -16,8 +16,12 @@ const type THandle* = int LONG* = int32 + ULONG* = int + PULONG* = ptr int WINBOOL* = int32 DWORD* = int32 + PDWORD* = ptr DWORD + LPINT* = ptr int32 HDC* = THandle HGLRC* = THandle @@ -195,16 +199,31 @@ else: importc: "GetCurrentDirectoryA", dynlib: "kernel32", stdcall.} proc setCurrentDirectoryA*(lpPathName: cstring): int32 {. importc: "SetCurrentDirectoryA", dynlib: "kernel32", stdcall.} - proc createDirectoryA*(pathName: cstring, security: Pointer=nil): int32 {. + proc createDirectoryA*(pathName: cstring, security: pointer=nil): int32 {. importc: "CreateDirectoryA", dynlib: "kernel32", stdcall.} proc removeDirectoryA*(lpPathName: cstring): int32 {. importc: "RemoveDirectoryA", dynlib: "kernel32", stdcall.} proc setEnvironmentVariableA*(lpName, lpValue: cstring): int32 {. stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableA".} - proc getModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {. + proc getModuleFileNameA*(handle: THandle, buf: cstring, size: int32): int32 {. importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.} - + +when useWinUnicode: + proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: WideCString, + flags: DWORD): int32 {. + importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall.} + proc createHardLinkW*(lpFileName, lpExistingFileName: WideCString, + security: pointer=nil): int32 {. + importc:"CreateHardLinkW", dynlib: "kernel32", stdcall.} +else: + proc createSymbolicLinkA*(lpSymlinkFileName, lpTargetFileName: cstring, + flags: DWORD): int32 {. + importc:"CreateSymbolicLinkA", dynlib: "kernel32", stdcall.} + proc createHardLinkA*(lpFileName, lpExistingFileName: cstring, + security: pointer=nil): int32 {. + importc:"CreateHardLinkA", dynlib: "kernel32", stdcall.} + const FILE_ATTRIBUTE_ARCHIVE* = 32'i32 FILE_ATTRIBUTE_COMPRESSED* = 2048'i32 @@ -212,6 +231,7 @@ const FILE_ATTRIBUTE_DIRECTORY* = 16'i32 FILE_ATTRIBUTE_HIDDEN* = 2'i32 FILE_ATTRIBUTE_READONLY* = 1'i32 + FILE_ATTRIBUTE_REPARSE_POINT* = 1024'i32 FILE_ATTRIBUTE_SYSTEM* = 4'i32 FILE_ATTRIBUTE_TEMPORARY* = 256'i32 @@ -284,7 +304,7 @@ else: dwFileAttributes: int32): WINBOOL {. stdcall, dynlib: "kernel32", importc: "SetFileAttributesA".} - proc copyFileA*(lpExistingFileName, lpNewFileName: CString, + proc copyFileA*(lpExistingFileName, lpNewFileName: cstring, bFailIfExists: cint): cint {. importc: "CopyFileA", stdcall, dynlib: "kernel32".} @@ -616,3 +636,76 @@ when not useWinUnicode: proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall, dynlib: "kernel32", importc: "UnmapViewOfFile".} +type + TOVERLAPPED* {.final, pure.} = object + Internal*: DWORD + InternalHigh*: DWORD + Offset*: DWORD + OffsetHigh*: DWORD + hEvent*: THANDLE + + POVERLAPPED* = ptr TOVERLAPPED + + POVERLAPPED_COMPLETION_ROUTINE* = proc (para1: DWORD, para2: DWORD, + para3: POVERLAPPED){.stdcall.} + + TGUID* {.final, pure.} = object + D1*: int32 + D2*: int16 + D3*: int16 + D4*: array [0..7, int8] + +const + ERROR_IO_PENDING* = 997 + +proc CreateIoCompletionPort*(FileHandle: THANDLE, ExistingCompletionPort: THANDLE, + CompletionKey: DWORD, + NumberOfConcurrentThreads: DWORD): THANDLE{.stdcall, + dynlib: "kernel32", importc: "CreateIoCompletionPort".} + +proc GetQueuedCompletionStatus*(CompletionPort: THandle, + lpNumberOfBytesTransferred: PDWORD, lpCompletionKey: PULONG, + lpOverlapped: ptr POverlapped, + dwMilliseconds: DWORD): WINBOOL{.stdcall, + dynlib: "kernel32", importc: "GetQueuedCompletionStatus".} + +const + IOC_OUT* = 0x40000000 + IOC_IN* = 0x80000000 + IOC_WS2* = 0x08000000 + IOC_INOUT* = IOC_IN or IOC_OUT + +template WSAIORW*(x,y): expr = (IOC_INOUT or x or y) + +const + SIO_GET_EXTENSION_FUNCTION_POINTER* = WSAIORW(IOC_WS2,6).DWORD + SO_UPDATE_ACCEPT_CONTEXT* = 0x700B + +var + WSAID_CONNECTEX*: TGUID = TGUID(D1: 0x25a207b9, D2: 0xddf3'i16, D3: 0x4660, D4: [ + 0x8e'i8, 0xe9'i8, 0x76'i8, 0xe5'i8, 0x8c'i8, 0x74'i8, 0x06'i8, 0x3e'i8]) + WSAID_ACCEPTEX*: TGUID = TGUID(D1: 0xb5367df1'i32, D2: 0xcbac'i16, D3: 0x11cf, D4: [ + 0x95'i8, 0xca'i8, 0x00'i8, 0x80'i8, 0x5f'i8, 0x48'i8, 0xa1'i8, 0x92'i8]) + WSAID_GETACCEPTEXSOCKADDRS*: TGUID = TGUID(D1: 0xb5367df2'i32, D2: 0xcbac'i16, D3: 0x11cf, D4: [ + 0x95'i8, 0xca'i8, 0x00'i8, 0x80'i8, 0x5f'i8, 0x48'i8, 0xa1'i8, 0x92'i8]) + +proc WSAIoctl*(s: TSocketHandle, dwIoControlCode: DWORD, lpvInBuffer: pointer, + cbInBuffer: DWORD, lpvOutBuffer: pointer, cbOutBuffer: DWORD, + lpcbBytesReturned: PDword, lpOverlapped: POVERLAPPED, + lpCompletionRoutine: POVERLAPPED_COMPLETION_ROUTINE): cint + {.stdcall, importc: "WSAIoctl", dynlib: "Ws2_32.dll".} + +type + TWSABuf* {.importc: "WSABUF", header: "winsock2.h".} = object + len*: ULONG + buf*: cstring + +proc WSARecv*(s: TSocketHandle, buf: ptr TWSABuf, bufCount: DWORD, + bytesReceived, flags: PDWORD, lpOverlapped: POverlapped, + completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {. + stdcall, importc: "WSARecv", dynlib: "Ws2_32.dll".} + +proc WSASend*(s: TSocketHandle, buf: ptr TWSABuf, bufCount: DWORD, + bytesSent: PDWord, flags: DWORD, lpOverlapped: POverlapped, + completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {. + stdcall, importc: "WSASend", dynlib: "Ws2_32.dll".} diff --git a/lib/wrappers/mongo.nim b/lib/wrappers/mongo.nim index 6673e8ddf..098b4f4d3 100644 --- a/lib/wrappers/mongo.nim +++ b/lib/wrappers/mongo.nim @@ -109,11 +109,12 @@ type cur*: cstring dataSize*: cint finished*: TBsonBool - stack*: array[0..32 - 1, cint] + ownsData*: TBsonBool + err*: cint + stackSize*: cint stackPos*: cint - err*: cint ## Bitfield representing errors or warnings on this buffer - errstr*: cstring ## A string representation of the most recent error - ## or warning. + stackPtr*: ptr csize + stack*: array[0..32 - 1, csize] TDate* = int64 @@ -141,6 +142,7 @@ proc print*(TBson: cstring, depth: cint) {.stdcall, importc: "bson_print_raw", dynlib: bsondll.} ## Print a string representation of a BSON object up to `depth`. + proc data*(b: var TBson): cstring{.stdcall, importc: "bson_data", dynlib: bsondll.} ## Return a pointer to the raw buffer stored by this bson object. @@ -590,19 +592,30 @@ type hosts*: ptr THostPort ## List of host/ports given by the replica set name*: cstring ## Name of the replica set. primary_connected*: TBsonBool ## Primary node connection status. + + TWriteConcern*{.pure, final.} = object ## mongo_write_concern + w*: cint + wtimeout*: cint + j*: cint + fsync*: cint + mode*: cstring + cmd*: TBSon TMongo*{.pure, final.} = object ## mongo - primary*: ptr THostPort ## Primary connection info. - replset*: ptr TReplSet ## replset object if connected to a replica set. - sock*: cint ## Socket file descriptor. - flags*: cint ## Flags on this connection object. - conn_timeout_ms*: cint ## Connection timeout in milliseconds. - op_timeout_ms*: cint ## Read and write timeout in milliseconds. - connected*: TBsonBool ## Connection status. - err*: TError ## Most recent driver error code. - errstr*: array[0..128 - 1, char] ## String version of most recent driver error code. - lasterrcode*: cint ## getlasterror code given by the server on error. - lasterrstr*: cstring ## getlasterror string generated by server. + primary*: ptr THostPort ## Primary connection info. + replset*: ptr TReplSet ## replset object if connected to a replica set. + sock*: cint ## Socket file descriptor. + flags*: cint ## Flags on this connection object. + conn_timeout_ms*: cint ## Connection timeout in milliseconds. + op_timeout_ms*: cint ## Read and write timeout in milliseconds. + max_bson_size*: cint ## Largest BSON object allowed on this connection. + connected*: TBsonBool ## Connection status. + write_concern*: TWriteConcern ## The default write concern. + err*: TError ## Most recent driver error code. + errcode*: cint ## Most recent errno or WSAGetLastError(). + errstr*: array[0..128 - 1, char] ## String version of most recent driver error code. + lasterrcode*: cint ## getlasterror code given by the server on error. + lasterrstr*: array[0..128 - 1, char] ## getlasterror string generated by server. TCursor*{.pure, final.} = object ## cursor reply*: ptr TReply ## reply is owned by cursor @@ -654,7 +667,11 @@ proc init*(conn: var TMongo){.stdcall, importc: "mongo_init", dynlib: mongodll.} proc connect*(conn: var TMongo, host: cstring = defaultHost, port: cint = defaultPort): cint {.stdcall, - importc: "mongo_connect", dynlib: mongodll.} + importc: "mongo_connect", dynlib: mongodll, deprecated.} + ## Connect to a single MongoDB server. +proc client*(conn: var TMongo, host: cstring = defaultHost, + port: cint = defaultPort): cint {.stdcall, + importc: "mongo_client", dynlib: mongodll.} ## Connect to a single MongoDB server. proc replsetInit*(conn: var TMongo, name: cstring){.stdcall, @@ -714,7 +731,8 @@ proc destroy*(conn: var TMongo){.stdcall, importc: "mongo_destroy", ## You must always call this function when finished with the connection ## object. -proc insert*(conn: var TMongo, ns: cstring, data: var TBson): cint{.stdcall, +proc insert*(conn: var TMongo, ns: cstring, data: var TBson, + custom_write_concern: ptr TWriteConcern): cint{.stdcall, importc: "mongo_insert", dynlib: mongodll, discardable.} ## Insert a BSON document into a MongoDB server. This function ## will fail if the supplied BSON struct is not UTF-8 or if diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim index af72d04eb..90c398dce 100644 --- a/lib/wrappers/openssl.nim +++ b/lib/wrappers/openssl.nim @@ -268,14 +268,22 @@ proc OpenSSL_add_all_algorithms*(){.cdecl, dynlib: DLLUtilName, importc: "OPENSS proc OPENSSL_config*(configName: cstring){.cdecl, dynlib: DLLSSLName, importc.} -proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, dynlib: DLLSSLName, importc.} +when not defined(windows): + proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, + dynlib: DLLSSLName, importc.} proc CRYPTO_malloc_init*() = when not defined(windows): CRYPTO_set_mem_functions(alloc, realloc, dealloc) -when True: - nil +proc SSL_CTX_ctrl*(ctx: PSSL_CTX, cmd: cInt, larg: int, parg: pointer): int{. + cdecl, dynlib: DLLSSLName, importc.} + +proc SSLCTXSetMode*(ctx: PSSL_CTX, mode: int): int = + result = SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, mode, nil) + +when true: + discard else: proc SslCtxSetCipherList*(arg0: PSSL_CTX, str: cstring): cInt{.cdecl, dynlib: DLLSSLName, importc.} @@ -288,7 +296,6 @@ else: proc SslCTXCtrl*(ctx: PSSL_CTX, cmd: cInt, larg: int, parg: Pointer): int{. cdecl, dynlib: DLLSSLName, importc.} - proc SSLCTXSetMode*(ctx: PSSL_CTX, mode: int): int proc SSLSetMode*(s: PSSL, mode: int): int proc SSLCTXGetMode*(ctx: PSSL_CTX): int proc SSLGetMode*(s: PSSL): int @@ -417,15 +424,12 @@ else: enc: cInt){.cdecl, dynlib: DLLUtilName, importc.} # implementation - proc SSLCTXSetMode(ctx: PSSL_CTX, mode: int): int = - Result = SslCTXCtrl(ctx, SSL_CTRL_MODE, mode, nil) - proc SSLSetMode(s: PSSL, mode: int): int = - Result = SSLctrl(s, SSL_CTRL_MODE, mode, nil) + result = SSLctrl(s, SSL_CTRL_MODE, mode, nil) proc SSLCTXGetMode(ctx: PSSL_CTX): int = - Result = SSLCTXctrl(ctx, SSL_CTRL_MODE, 0, nil) + result = SSLCTXctrl(ctx, SSL_CTRL_MODE, 0, nil) proc SSLGetMode(s: PSSL): int = - Result = SSLctrl(s, SSL_CTRL_MODE, 0, nil) + result = SSLctrl(s, SSL_CTRL_MODE, 0, nil) |