Merge pull request #4284 from arnetheduck/system-c-cleanup

System c cleanup
This commit is contained in:
Andreas Rumpf 2016-06-13 12:18:34 +02:00 • committed by GitHub
commit 792b99442a
22 changed files with 313 additions and 339 deletions

View file

@ -347,9 +347,6 @@ static N_INLINE(NI32, float32ToInt32)(float x) {
#define float64ToInt64(x) ((NI64) (x)) #define float64ToInt64(x) ((NI64) (x))
#define zeroMem(a, size) memset(a, 0, size)
#define equalMem(a, b, size) (memcmp(a, b, size) == 0)
#define STRING_LITERAL(name, str, length) \ #define STRING_LITERAL(name, str, length) \
static const struct { \ static const struct { \
TGenericSeq Sup; \ TGenericSeq Sup; \

View file

@ -257,12 +257,10 @@ type MemSlice* = object ## represent slice of a MemFile for iteration over deli
data*: pointer data*: pointer
size*: int size*: int
proc c_memcpy(a, b: pointer, n: int) {.importc: "memcpy", header: "<string.h>".}
proc `$`*(ms: MemSlice): string {.inline.} = proc `$`*(ms: MemSlice): string {.inline.} =
## Return a Nim string built from a MemSlice. ## Return a Nim string built from a MemSlice.
var buf = newString(ms.size) var buf = newString(ms.size)
c_memcpy(addr(buf[0]), ms.data, ms.size) copyMem(addr(buf[0]), ms.data, ms.size)
buf[ms.size] = '\0' buf[ms.size] = '\0'
result = buf result = buf
@ -329,7 +327,7 @@ iterator lines*(mfile: MemFile, buf: var TaintedString, delim='\l', eat='\r'): T
for ms in memSlices(mfile, delim, eat): for ms in memSlices(mfile, delim, eat):
buf.setLen(ms.size) buf.setLen(ms.size)
c_memcpy(addr(buf[0]), ms.data, ms.size) copyMem(addr(buf[0]), ms.data, ms.size)
buf[ms.size] = '\0' buf[ms.size] = '\0'
yield buf yield buf

View file

@ -26,7 +26,6 @@ elif defined(posix):
else: else:
{.error: "OS module not ported to your operating system!".} {.error: "OS module not ported to your operating system!".}
include "system/ansi_c"
include ospaths include ospaths
when defined(posix): when defined(posix):
@ -37,6 +36,23 @@ when defined(posix):
var var
pathMax {.importc: "PATH_MAX", header: "<stdlib.h>".}: cint pathMax {.importc: "PATH_MAX", header: "<stdlib.h>".}: cint
proc c_remove(filename: cstring): cint {.
importc: "remove", header: "<stdio.h>".}
proc c_rename(oldname, newname: cstring): cint {.
importc: "rename", header: "<stdio.h>".}
proc c_system(cmd: cstring): cint {.
importc: "system", header: "<stdlib.h>".}
proc c_strerror(errnum: cint): cstring {.
importc: "strerror", header: "<string.h>".}
proc c_strlen(a: cstring): cint {.
importc: "strlen", header: "<string.h>", noSideEffect.}
proc c_getenv(env: cstring): cstring {.
importc: "getenv", header: "<stdlib.h>".}
proc c_putenv(env: cstring): cint {.
importc: "putenv", header: "<stdlib.h>".}
var errno {.importc, header: "<errno.h>".}: cint
proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} = proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
## Retrieves the operating system's error flag, ``errno``. ## Retrieves the operating system's error flag, ``errno``.
## On Windows ``GetLastError`` is checked before ``errno``. ## On Windows ``GetLastError`` is checked before ``errno``.
@ -61,7 +77,7 @@ proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
result = $msgbuf result = $msgbuf
if msgbuf != nil: localFree(msgbuf) if msgbuf != nil: localFree(msgbuf)
if errno != 0'i32: if errno != 0'i32:
result = $os.strerror(errno) result = $os.c_strerror(errno)
{.push warning[deprecated]: off.} {.push warning[deprecated]: off.}
proc raiseOSError*(msg: string = "") {.noinline, rtl, extern: "nos$1", proc raiseOSError*(msg: string = "") {.noinline, rtl, extern: "nos$1",
@ -114,7 +130,7 @@ proc osErrorMsg*(errorCode: OSErrorCode): string =
if msgbuf != nil: localFree(msgbuf) if msgbuf != nil: localFree(msgbuf)
else: else:
if errorCode != OSErrorCode(0'i32): if errorCode != OSErrorCode(0'i32):
result = $os.strerror(errorCode.int32) result = $os.c_strerror(errorCode.int32)
proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} = proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} =
## Raises an ``OSError`` exception. The ``errorCode`` will determine the ## Raises an ``OSError`` exception. The ``errorCode`` will determine the

View file

@ -306,40 +306,42 @@ proc peekLine*(s: Stream): TaintedString =
defer: setPosition(s, pos) defer: setPosition(s, pos)
result = readLine(s) result = readLine(s)
type when not defined(js):
type
StringStream* = ref StringStreamObj ## a stream that encapsulates a string StringStream* = ref StringStreamObj ## a stream that encapsulates a string
StringStreamObj* = object of StreamObj StringStreamObj* = object of StreamObj
data*: string data*: string
pos: int pos: int
{.deprecated: [PStringStream: StringStream, TStringStream: StringStreamObj].} {.deprecated: [PStringStream: StringStream, TStringStream: StringStreamObj].}
proc ssAtEnd(s: Stream): bool = proc ssAtEnd(s: Stream): bool =
var s = StringStream(s) var s = StringStream(s)
return s.pos >= s.data.len return s.pos >= s.data.len
proc ssSetPosition(s: Stream, pos: int) = proc ssSetPosition(s: Stream, pos: int) =
var s = StringStream(s) var s = StringStream(s)
s.pos = clamp(pos, 0, s.data.len) s.pos = clamp(pos, 0, s.data.len)
proc ssGetPosition(s: Stream): int = proc ssGetPosition(s: Stream): int =
var s = StringStream(s) var s = StringStream(s)
return s.pos return s.pos
proc ssReadData(s: Stream, buffer: pointer, bufLen: int): int = proc ssReadData(s: Stream, buffer: pointer, bufLen: int): int =
var s = StringStream(s) var s = StringStream(s)
result = min(bufLen, s.data.len - s.pos) result = min(bufLen, s.data.len - s.pos)
if result > 0: if result > 0:
copyMem(buffer, addr(s.data[s.pos]), result) copyMem(buffer, addr(s.data[s.pos]), result)
inc(s.pos, result) inc(s.pos, result)
proc ssPeekData(s: Stream, buffer: pointer, bufLen: int): int = proc ssPeekData(s: Stream, buffer: pointer, bufLen: int): int =
var s = StringStream(s) var s = StringStream(s)
result = min(bufLen, s.data.len - s.pos) result = min(bufLen, s.data.len - s.pos)
if result > 0: if result > 0:
copyMem(buffer, addr(s.data[s.pos]), result) copyMem(buffer, addr(s.data[s.pos]), result)
proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) = proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) =
var s = StringStream(s) var s = StringStream(s)
if bufLen <= 0: if bufLen <= 0:
return return
@ -348,11 +350,11 @@ proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) =
copyMem(addr(s.data[s.pos]), buffer, bufLen) copyMem(addr(s.data[s.pos]), buffer, bufLen)
inc(s.pos, bufLen) inc(s.pos, bufLen)
proc ssClose(s: Stream) = proc ssClose(s: Stream) =
var s = StringStream(s) var s = StringStream(s)
s.data = nil s.data = nil
proc newStringStream*(s: string = ""): StringStream = proc newStringStream*(s: string = ""): StringStream =
## creates a new stream from the string `s`. ## creates a new stream from the string `s`.
new(result) new(result)
result.data = s result.data = s
@ -365,8 +367,6 @@ proc newStringStream*(s: string = ""): StringStream =
result.peekDataImpl = ssPeekData result.peekDataImpl = ssPeekData
result.writeDataImpl = ssWriteData result.writeDataImpl = ssWriteData
when not defined(js):
type type
FileStream* = ref FileStreamObj ## a stream that encapsulates a `File` FileStream* = ref FileStreamObj ## a stream that encapsulates a `File`
FileStreamObj* = object of Stream FileStreamObj* = object of Stream

View file

@ -1593,34 +1593,32 @@ proc substr*(s: string, first, last: int): string {.
## is used instead: This means ``substr`` can also be used to `cut`:idx: ## is used instead: This means ``substr`` can also be used to `cut`:idx:
## or `limit`:idx: a string's length. ## or `limit`:idx: a string's length.
when not defined(nimscript): when not defined(nimscript) and not defined(JS):
proc zeroMem*(p: pointer, size: Natural) {.importc, noDecl, benign.} proc zeroMem*(p: pointer, size: Natural) {.inline, benign.}
## overwrites the contents of the memory at ``p`` with the value 0. ## overwrites the contents of the memory at ``p`` with the value 0.
## Exactly ``size`` bytes will be overwritten. Like any procedure ## Exactly ``size`` bytes will be overwritten. Like any procedure
## dealing with raw memory this is *unsafe*. ## dealing with raw memory this is *unsafe*.
proc copyMem*(dest, source: pointer, size: Natural) {. proc copyMem*(dest, source: pointer, size: Natural) {.inline, benign.}
importc: "memcpy", header: "<string.h>", benign.}
## copies the contents from the memory at ``source`` to the memory ## copies the contents from the memory at ``source`` to the memory
## at ``dest``. Exactly ``size`` bytes will be copied. The memory ## at ``dest``. Exactly ``size`` bytes will be copied. The memory
## regions may not overlap. Like any procedure dealing with raw ## regions may not overlap. Like any procedure dealing with raw
## memory this is *unsafe*. ## memory this is *unsafe*.
proc moveMem*(dest, source: pointer, size: Natural) {. proc moveMem*(dest, source: pointer, size: Natural) {.inline, benign.}
importc: "memmove", header: "<string.h>", benign.}
## copies the contents from the memory at ``source`` to the memory ## copies the contents from the memory at ``source`` to the memory
## at ``dest``. Exactly ``size`` bytes will be copied. The memory ## at ``dest``. Exactly ``size`` bytes will be copied. The memory
## regions may overlap, ``moveMem`` handles this case appropriately ## regions may overlap, ``moveMem`` handles this case appropriately
## and is thus somewhat more safe than ``copyMem``. Like any procedure ## and is thus somewhat more safe than ``copyMem``. Like any procedure
## dealing with raw memory this is still *unsafe*, though. ## dealing with raw memory this is still *unsafe*, though.
proc equalMem*(a, b: pointer, size: Natural): bool {. proc equalMem*(a, b: pointer, size: Natural): bool {.inline, noSideEffect.}
importc: "equalMem", noDecl, noSideEffect.}
## compares the memory blocks ``a`` and ``b``. ``size`` bytes will ## compares the memory blocks ``a`` and ``b``. ``size`` bytes will
## be compared. If the blocks are equal, true is returned, false ## be compared. If the blocks are equal, true is returned, false
## otherwise. Like any procedure dealing with raw memory this is ## otherwise. Like any procedure dealing with raw memory this is
## *unsafe*. ## *unsafe*.
when not defined(nimscript):
when hasAlloc: when hasAlloc:
proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign.} proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign.}
## allocates a new memory block with at least ``size`` bytes. The ## allocates a new memory block with at least ``size`` bytes. The
@ -2618,11 +2616,21 @@ when not defined(JS): #and not defined(nimscript):
{.deprecated: [TFile: File, TFileHandle: FileHandle, TFileMode: FileMode].} {.deprecated: [TFile: File, TFileHandle: FileHandle, TFileMode: FileMode].}
when not defined(nimscript):
include "system/ansi_c" include "system/ansi_c"
when not defined(nimscript):
proc cmp(x, y: string): int = proc cmp(x, y: string): int =
result = int(c_strcmp(x, y)) result = int(c_strcmp(x, y))
proc zeroMem(p: pointer, size: Natural) =
c_memset(p, 0, size)
proc copyMem(dest, source: pointer, size: Natural) =
c_memcpy(dest, source, size)
proc moveMem(dest, source: pointer, size: Natural) =
c_memmove(dest, source, size)
proc equalMem(a, b: pointer, size: Natural): bool =
c_memcmp(a, b, size) == 0
else: else:
proc cmp(x, y: string): int = proc cmp(x, y: string): int =
if x < y: result = -1 if x < y: result = -1
@ -2644,22 +2652,6 @@ when not defined(JS): #and not defined(nimscript):
## Raises an IO exception in case of an error. ## Raises an IO exception in case of an error.
when not defined(nimscript) and hostOS != "standalone": when not defined(nimscript) and hostOS != "standalone":
when defined(windows):
# work-around C's sucking abstraction:
# BUGFIX: stdin and stdout should be binary files!
proc setmode(handle, mode: int) {.importc: "setmode",
header: "<io.h>".}
proc fileno(f: C_TextFileStar): int {.importc: "fileno",
header: "<fcntl.h>".}
var
O_BINARY {.importc: "O_BINARY", nodecl.}: int
# we use binary mode on Windows:
setmode(fileno(c_stdin), O_BINARY)
setmode(fileno(c_stdout), O_BINARY)
when defined(endb):
proc endbStep()
# text file handling: # text file handling:
var var
@ -2670,6 +2662,21 @@ when not defined(JS): #and not defined(nimscript):
stderr* {.importc: "stderr", header: "<stdio.h>".}: File stderr* {.importc: "stderr", header: "<stdio.h>".}: File
## The standard error stream. ## The standard error stream.
when defined(windows):
# work-around C's sucking abstraction:
# BUGFIX: stdin and stdout should be binary files!
proc c_setmode(handle, mode: cint) {.importc: "_setmode",
header: "<io.h>".}
var
O_BINARY {.importc: "O_BINARY", nodecl.}: cint
# we use binary mode on Windows:
c_setmode(c_fileno(stdin), O_BINARY)
c_setmode(c_fileno(stdout), O_BINARY)
when defined(endb):
proc endbStep()
when defined(useStdoutAsStdmsg): when defined(useStdoutAsStdmsg):
template stdmsg*: File = stdout template stdmsg*: File = stdout
else: else:
@ -2708,17 +2715,16 @@ when not defined(JS): #and not defined(nimscript):
## ##
## Default mode is readonly. Returns true iff the file could be reopened. ## Default mode is readonly. Returns true iff the file could be reopened.
proc close*(f: File) {.importc: "fclose", header: "<stdio.h>", tags: [].} proc close*(f: File) {.tags: [].}
## Closes the file. ## Closes the file.
proc endOfFile*(f: File): bool {.tags: [], benign.} proc endOfFile*(f: File): bool {.tags: [], benign.}
## Returns true iff `f` is at the end. ## Returns true iff `f` is at the end.
proc readChar*(f: File): char {. proc readChar*(f: File): char {.tags: [ReadIOEffect].}
importc: "fgetc", header: "<stdio.h>", tags: [ReadIOEffect].}
## Reads a single character from the stream `f`. ## Reads a single character from the stream `f`.
proc flushFile*(f: File) {.
importc: "fflush", header: "<stdio.h>", tags: [WriteIOEffect].} proc flushFile*(f: File) {.tags: [WriteIOEffect].}
## Flushes `f`'s buffer. ## Flushes `f`'s buffer.
proc readAll*(file: File): TaintedString {.tags: [ReadIOEffect], benign.} proc readAll*(file: File): TaintedString {.tags: [ReadIOEffect], benign.}
@ -2824,8 +2830,7 @@ when not defined(JS): #and not defined(nimscript):
## retrieves the current position of the file pointer that is used to ## retrieves the current position of the file pointer that is used to
## read from the file `f`. The file's first byte has the index zero. ## read from the file `f`. The file's first byte has the index zero.
proc getFileHandle*(f: File): FileHandle {.importc: "fileno", proc getFileHandle*(f: File): FileHandle
header: "<stdio.h>"}
## returns the OS file handle of the file ``f``. This is only useful for ## returns the OS file handle of the file ``f``. This is only useful for
## platform specific programming. ## platform specific programming.

View file

@ -324,9 +324,9 @@ proc contains[T](list, x: T): bool =
proc writeFreeList(a: MemRegion) = proc writeFreeList(a: MemRegion) =
var it = a.freeChunksList var it = a.freeChunksList
c_fprintf(c_stdout, "freeChunksList: %p\n", it) c_fprintf(stdout, "freeChunksList: %p\n", it)
while it != nil: while it != nil:
c_fprintf(c_stdout, "it: %p, next: %p, prev: %p\n", c_fprintf(stdout, "it: %p, next: %p, prev: %p\n",
it, it.next, it.prev) it, it.next, it.prev)
it = it.next it = it.next

View file

@ -13,42 +13,23 @@
{.push hints:off} {.push hints:off}
proc c_strcmp(a, b: cstring): cint {.header: "<string.h>", proc c_memchr(s: pointer, c: cint, n: csize): pointer {.
noSideEffect, importc: "strcmp".} importc: "memchr", header: "<string.h>".}
proc c_memcmp(a, b: cstring, size: int): cint {.header: "<string.h>", proc c_memcmp(a, b: pointer, size: csize): cint {.
noSideEffect, importc: "memcmp".} importc: "memcmp", header: "<string.h>", noSideEffect.}
proc c_memcpy(a, b: cstring, size: int) {.header: "<string.h>", importc: "memcpy".} proc c_memcpy(a, b: pointer, size: csize): pointer {.
proc c_strlen(a: cstring): int {.header: "<string.h>", importc: "memcpy", header: "<string.h>", discardable.}
noSideEffect, importc: "strlen".} proc c_memmove(a, b: pointer, size: csize): pointer {.
proc c_memset(p: pointer, value: cint, size: int) {. importc: "memmove", header: "<string.h>",discardable.}
header: "<string.h>", importc: "memset".} proc c_memset(p: pointer, value: cint, size: csize): pointer {.
importc: "memset", header: "<string.h>", discardable.}
when not declared(File): proc c_strcmp(a, b: cstring): cint {.
type importc: "strcmp", header: "<string.h>", noSideEffect.}
C_TextFile {.importc: "FILE", header: "<stdio.h>",
final, incompleteStruct.} = object
C_BinaryFile {.importc: "FILE", header: "<stdio.h>",
final, incompleteStruct.} = object
C_TextFileStar = ptr C_TextFile
C_BinaryFileStar = ptr C_BinaryFile
else:
type
C_TextFileStar = File
C_BinaryFileStar = File
type type
C_JmpBuf {.importc: "jmp_buf", header: "<setjmp.h>".} = object C_JmpBuf {.importc: "jmp_buf", header: "<setjmp.h>".} = object
when not defined(vm): when defined(windows):
var
c_stdin {.importc: "stdin", nodecl.}: C_TextFileStar
c_stdout {.importc: "stdout", nodecl.}: C_TextFileStar
c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar
# constants faked as variables:
when not declared(SIGINT):
when NoFakeVars:
when defined(windows):
const const
SIGABRT = cint(22) SIGABRT = cint(22)
SIGFPE = cint(8) SIGFPE = cint(8)
@ -56,7 +37,7 @@ when not declared(SIGINT):
SIGINT = cint(2) SIGINT = cint(2)
SIGSEGV = cint(11) SIGSEGV = cint(11)
SIGTERM = cint(15) SIGTERM = cint(15)
elif defined(macosx) or defined(linux): elif defined(macosx) or defined(linux):
const const
SIGABRT = cint(6) SIGABRT = cint(6)
SIGFPE = cint(8) SIGFPE = cint(8)
@ -65,7 +46,8 @@ when not declared(SIGINT):
SIGSEGV = cint(11) SIGSEGV = cint(11)
SIGTERM = cint(15) SIGTERM = cint(15)
SIGPIPE = cint(13) SIGPIPE = cint(13)
else: else:
when NoFakeVars:
{.error: "SIGABRT not ported to your platform".} {.error: "SIGABRT not ported to your platform".}
else: else:
var var
@ -78,10 +60,7 @@ when not declared(SIGINT):
var SIGPIPE {.importc: "SIGPIPE", nodecl.}: cint var SIGPIPE {.importc: "SIGPIPE", nodecl.}: cint
when defined(macosx): when defined(macosx):
when NoFakeVars:
const SIGBUS = cint(10) const SIGBUS = cint(10)
else:
var SIGBUS {.importc: "SIGBUS", nodecl.}: cint
else: else:
template SIGBUS: expr = SIGSEGV template SIGBUS: expr = SIGSEGV
@ -103,72 +82,27 @@ else:
proc c_setjmp(jmpb: C_JmpBuf): cint {. proc c_setjmp(jmpb: C_JmpBuf): cint {.
header: "<setjmp.h>", importc: "setjmp".} header: "<setjmp.h>", importc: "setjmp".}
proc c_signal(sign: cint, handler: proc (a: cint) {.noconv.}) {. type c_sighandler_t = proc (a: cint) {.noconv.}
importc: "signal", header: "<signal.h>".} proc c_signal(sign: cint, handler: proc (a: cint) {.noconv.}): c_sighandler_t {.
proc c_raise(sign: cint) {.importc: "raise", header: "<signal.h>".} importc: "signal", header: "<signal.h>", discardable.}
proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs", proc c_fprintf(f: File, frmt: cstring): cint {.
header: "<stdio.h>".} importc: "fprintf", header: "<stdio.h>", varargs, discardable.}
proc c_fgets(c: cstring, n: int, f: C_TextFileStar): cstring {. proc c_printf(frmt: cstring): cint {.
importc: "fgets", header: "<stdio.h>".} importc: "printf", header: "<stdio.h>", varargs, discardable.}
proc c_fgetc(stream: C_TextFileStar): int {.importc: "fgetc",
header: "<stdio.h>".}
proc c_ungetc(c: int, f: C_TextFileStar) {.importc: "ungetc",
header: "<stdio.h>".}
proc c_putc(c: char, stream: C_TextFileStar) {.importc: "putc",
header: "<stdio.h>".}
proc c_fprintf(f: C_TextFileStar, frmt: cstring) {.
importc: "fprintf", header: "<stdio.h>", varargs.}
proc c_printf(frmt: cstring) {.
importc: "printf", header: "<stdio.h>", varargs.}
proc c_fopen(filename, mode: cstring): C_TextFileStar {. proc c_sprintf(buf, frmt: cstring): cint {.
importc: "fopen", header: "<stdio.h>".} importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.}
proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "<stdio.h>".}
proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
importc: "sprintf", varargs, noSideEffect.}
# we use it only in a way that cannot lead to security issues # we use it only in a way that cannot lead to security issues
proc c_fread(buf: pointer, size, n: int, f: C_BinaryFileStar): int {. proc c_fileno(f: File): cint {.
importc: "fread", header: "<stdio.h>".} importc: "fileno", header: "<fcntl.h>".}
proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {.
importc: "fseek", header: "<stdio.h>".}
proc c_fwrite(buf: pointer, size, n: int, f: C_BinaryFileStar): int {. proc c_malloc(size: csize): pointer {.
importc: "fwrite", header: "<stdio.h>".} importc: "malloc", header: "<stdlib.h>".}
proc c_free(p: pointer) {.
proc c_exit(errorcode: cint) {.importc: "exit", header: "<stdlib.h>".} importc: "free", header: "<stdlib.h>".}
proc c_ferror(stream: C_TextFileStar): bool {. proc c_realloc(p: pointer, newsize: csize): pointer {.
importc: "ferror", header: "<stdio.h>".}
proc c_fflush(stream: C_TextFileStar) {.importc: "fflush", header: "<stdio.h>".}
proc c_abort() {.importc: "abort", header: "<stdlib.h>".}
proc c_feof(stream: C_TextFileStar): bool {.
importc: "feof", header: "<stdio.h>".}
proc c_malloc(size: int): pointer {.importc: "malloc", header: "<stdlib.h>".}
proc c_free(p: pointer) {.importc: "free", header: "<stdlib.h>".}
proc c_realloc(p: pointer, newsize: int): pointer {.
importc: "realloc", header: "<stdlib.h>".} importc: "realloc", header: "<stdlib.h>".}
when hostOS != "standalone":
when not declared(errno):
when defined(NimrodVM):
var vmErrnoWrapper {.importc.}: ptr cint
template errno: expr =
bind vmErrnoWrapper
vmErrnoWrapper[]
else:
var errno {.importc, header: "<errno.h>".}: cint ## error variable
proc strerror(errnum: cint): cstring {.importc, header: "<string.h>".}
proc c_remove(filename: cstring): cint {.
importc: "remove", header: "<stdio.h>".}
proc c_rename(oldname, newname: cstring): cint {.
importc: "rename", header: "<stdio.h>".}
proc c_system(cmd: cstring): cint {.importc: "system", header: "<stdlib.h>".}
proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
proc c_putenv(env: cstring): cint {.importc: "putenv", header: "<stdlib.h>".}
{.pop} {.pop}

View file

@ -51,7 +51,6 @@ proc chckRangeF(x, a, b: float): float =
proc chckNil(p: pointer) = proc chckNil(p: pointer) =
if p == nil: if p == nil:
sysFatal(ValueError, "attempt to write to a nil address") sysFatal(ValueError, "attempt to write to a nil address")
#c_raise(SIGSEGV)
proc chckObj(obj, subclass: PNimType) {.compilerproc.} = proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
# checks if obj is of type subclass: # checks if obj is of type subclass:

View file

@ -108,8 +108,8 @@ proc fileMatches(c, bp: cstring): bool =
# and the character for the suffix does not exist or # and the character for the suffix does not exist or
# is one of: \ / : # is one of: \ / :
# depending on the OS case does not matter! # depending on the OS case does not matter!
var blen: int = c_strlen(bp) var blen: int = bp.len
var clen: int = c_strlen(c) var clen: int = c.len
if blen > clen: return false if blen > clen: return false
# check for \ / : # check for \ / :
if clen-blen-1 >= 0 and c[clen-blen-1] notin {'\\', '/', ':'}: if clen-blen-1 >= 0 and c[clen-blen-1] notin {'\\', '/', ':'}:

View file

@ -36,7 +36,7 @@ proc copyDeepString(src: NimString): NimString {.inline.} =
if src != nil: if src != nil:
result = rawNewStringNoInit(src.len) result = rawNewStringNoInit(src.len)
result.len = src.len result.len = src.len
c_memcpy(result.data, src.data, src.len + 1) copyMem(addr(result.data), addr(src.data), src.len + 1)
proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
var var

View file

@ -52,11 +52,14 @@ when defined(posix):
# #
# c stuff: # c stuff:
when defined(linux) or defined(macosx):
const RTLD_NOW = cint(2)
else:
var var
RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: int RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: cint
proc dlclose(lib: LibHandle) {.importc, header: "<dlfcn.h>".} proc dlclose(lib: LibHandle) {.importc, header: "<dlfcn.h>".}
proc dlopen(path: cstring, mode: int): LibHandle {. proc dlopen(path: cstring, mode: cint): LibHandle {.
importc, header: "<dlfcn.h>".} importc, header: "<dlfcn.h>".}
proc dlsym(lib: LibHandle, name: cstring): ProcAddr {. proc dlsym(lib: LibHandle, name: cstring): ProcAddr {.
importc, header: "<dlfcn.h>".} importc, header: "<dlfcn.h>".}

View file

@ -329,14 +329,14 @@ proc dbgStackFrame(s: cstring, start: int, currFrame: PFrame) =
proc readLine(f: File, line: var StaticStr): bool = proc readLine(f: File, line: var StaticStr): bool =
while true: while true:
var c = fgetc(f) var c = c_fgetc(f)
if c < 0'i32: if c < 0'i32:
if line.len > 0: break if line.len > 0: break
else: return false else: return false
if c == 10'i32: break # LF if c == 10'i32: break # LF
if c == 13'i32: # CR if c == 13'i32: # CR
c = fgetc(f) # is the next char LF? c = c_fgetc(f) # is the next char LF?
if c != 10'i32: ungetc(c, f) # no, put the character back if c != 10'i32: discard c_ungetc(c, f) # no, put the character back
break break
add line, chr(int(c)) add line, chr(int(c))
result = true result = true

View file

@ -255,7 +255,7 @@ proc raiseExceptionAux(e: ref Exception) =
add(buf, "Error: unhandled exception: ") add(buf, "Error: unhandled exception: ")
if not isNil(e.msg): add(buf, e.msg) if not isNil(e.msg): add(buf, e.msg)
add(buf, " [") add(buf, " [")
xadd(buf, e.name, c_strlen(e.name)) xadd(buf, e.name, e.name.len)
add(buf, "]\n") add(buf, "]\n")
showErrorMessage(buf) showErrorMessage(buf)
quitOrDebug() quitOrDebug()

View file

@ -152,10 +152,10 @@ proc writeCell(msg: cstring, c: PCell) =
var kind = -1 var kind = -1
if c.typ != nil: kind = ord(c.typ.kind) if c.typ != nil: kind = ord(c.typ.kind)
when leakDetector: when leakDetector:
c_fprintf(c_stdout, "[GC] %s: %p %d rc=%ld from %s(%ld)\n", c_fprintf(stdout, "[GC] %s: %p %d rc=%ld from %s(%ld)\n",
msg, c, kind, c.refcount shr rcShift, c.filename, c.line) msg, c, kind, c.refcount shr rcShift, c.filename, c.line)
else: else:
c_fprintf(c_stdout, "[GC] %s: %p %d rc=%ld; color=%ld\n", c_fprintf(stdout, "[GC] %s: %p %d rc=%ld; color=%ld\n",
msg, c, kind, c.refcount shr rcShift, c.color) msg, c, kind, c.refcount shr rcShift, c.color)
template gcTrace(cell, state: expr): stmt {.immediate.} = template gcTrace(cell, state: expr): stmt {.immediate.} =

View file

@ -272,7 +272,7 @@ when false:
proc copyDeepString(dr: var MemRegion; stack: var PointerStackChunk; src: NimString): NimString {.inline.} = proc copyDeepString(dr: var MemRegion; stack: var PointerStackChunk; src: NimString): NimString {.inline.} =
result = rawNewStringNoInit(dr, src.len) result = rawNewStringNoInit(dr, src.len)
result.len = src.len result.len = src.len
c_memcpy(result.data, src.data, src.len + 1) copyMem(result.data, src.data, src.len + 1)
proc genericDeepCopyAux(dr: var MemRegion; stack: var PointerStackChunk; proc genericDeepCopyAux(dr: var MemRegion; stack: var PointerStackChunk;
dest, src: pointer, mt: PNimType) = dest, src: pointer, mt: PNimType) =
@ -417,15 +417,15 @@ proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
proc alloc(size: Natural): pointer = proc alloc(size: Natural): pointer =
result = cmalloc(size) result = c_malloc(size)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc alloc0(size: Natural): pointer = proc alloc0(size: Natural): pointer =
result = alloc(size) result = alloc(size)
zeroMem(result, size) zeroMem(result, size)
proc realloc(p: pointer, newsize: Natural): pointer = proc realloc(p: pointer, newsize: Natural): pointer =
result = crealloc(p, newsize) result = c_realloc(p, newsize)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc dealloc(p: pointer) = cfree(p) proc dealloc(p: pointer) = c_free(p)
proc alloc0(r: var MemRegion; size: Natural): pointer = proc alloc0(r: var MemRegion; size: Natural): pointer =
# ignore the region. That is correct for the channels module # ignore the region. That is correct for the channels module
@ -435,15 +435,15 @@ proc alloc0(r: var MemRegion; size: Natural): pointer =
proc dealloc(r: var MemRegion; p: pointer) = dealloc(p) proc dealloc(r: var MemRegion; p: pointer) = dealloc(p)
proc allocShared(size: Natural): pointer = proc allocShared(size: Natural): pointer =
result = cmalloc(size) result = c_malloc(size)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc allocShared0(size: Natural): pointer = proc allocShared0(size: Natural): pointer =
result = alloc(size) result = alloc(size)
zeroMem(result, size) zeroMem(result, size)
proc reallocShared(p: pointer, newsize: Natural): pointer = proc reallocShared(p: pointer, newsize: Natural): pointer =
result = crealloc(p, newsize) result = c_realloc(p, newsize)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc deallocShared(p: pointer) = cfree(p) proc deallocShared(p: pointer) = c_free(p)
when hasThreadSupport: when hasThreadSupport:
proc getFreeSharedMem(): int = 0 proc getFreeSharedMem(): int = 0

View file

@ -300,7 +300,7 @@ elif defined(gogc):
proc setStackBottom(theStackBottom: pointer) = discard proc setStackBottom(theStackBottom: pointer) = discard
proc alloc(size: Natural): pointer = proc alloc(size: Natural): pointer =
result = cmalloc(size) result = c_malloc(size)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc alloc0(size: Natural): pointer = proc alloc0(size: Natural): pointer =
@ -308,13 +308,13 @@ elif defined(gogc):
zeroMem(result, size) zeroMem(result, size)
proc realloc(p: pointer, newsize: Natural): pointer = proc realloc(p: pointer, newsize: Natural): pointer =
result = crealloc(p, newsize) result = c_realloc(p, newsize)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc dealloc(p: pointer) = cfree(p) proc dealloc(p: pointer) = c_free(p)
proc allocShared(size: Natural): pointer = proc allocShared(size: Natural): pointer =
result = cmalloc(size) result = c_malloc(size)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc allocShared0(size: Natural): pointer = proc allocShared0(size: Natural): pointer =
@ -322,10 +322,10 @@ elif defined(gogc):
zeroMem(result, size) zeroMem(result, size)
proc reallocShared(p: pointer, newsize: Natural): pointer = proc reallocShared(p: pointer, newsize: Natural): pointer =
result = crealloc(p, newsize) result = c_realloc(p, newsize)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc deallocShared(p: pointer) = cfree(p) proc deallocShared(p: pointer) = c_free(p)
when hasThreadSupport: when hasThreadSupport:
proc getFreeSharedMem(): int = discard proc getFreeSharedMem(): int = discard
@ -389,7 +389,7 @@ elif defined(nogc) and defined(useMalloc):
when not defined(useNimRtl): when not defined(useNimRtl):
proc alloc(size: Natural): pointer = proc alloc(size: Natural): pointer =
var x = cmalloc(size + sizeof(size)) var x = c_malloc(size + sizeof(size))
if x == nil: raiseOutOfMem() if x == nil: raiseOutOfMem()
cast[ptr int](x)[] = size cast[ptr int](x)[] = size
@ -402,7 +402,7 @@ elif defined(nogc) and defined(useMalloc):
var x = cast[pointer](cast[int](p) - sizeof(newsize)) var x = cast[pointer](cast[int](p) - sizeof(newsize))
let oldsize = cast[ptr int](x)[] let oldsize = cast[ptr int](x)[]
x = crealloc(x, newsize + sizeof(newsize)) x = c_realloc(x, newsize + sizeof(newsize))
if x == nil: raiseOutOfMem() if x == nil: raiseOutOfMem()
@ -412,18 +412,18 @@ elif defined(nogc) and defined(useMalloc):
if newsize > oldsize: if newsize > oldsize:
zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize) zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
proc dealloc(p: pointer) = cfree(cast[pointer](cast[int](p) - sizeof(int))) proc dealloc(p: pointer) = c_free(cast[pointer](cast[int](p) - sizeof(int)))
proc allocShared(size: Natural): pointer = proc allocShared(size: Natural): pointer =
result = cmalloc(size) result = c_malloc(size)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc allocShared0(size: Natural): pointer = proc allocShared0(size: Natural): pointer =
result = alloc(size) result = alloc(size)
zeroMem(result, size) zeroMem(result, size)
proc reallocShared(p: pointer, newsize: Natural): pointer = proc reallocShared(p: pointer, newsize: Natural): pointer =
result = crealloc(p, newsize) result = c_realloc(p, newsize)
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc deallocShared(p: pointer) = cfree(p) proc deallocShared(p: pointer) = c_free(p)
proc GC_disable() = discard proc GC_disable() = discard
proc GC_enable() = discard proc GC_enable() = discard

View file

@ -87,6 +87,8 @@ elif defined(posix):
const MAP_ANONYMOUS = 0x1000 const MAP_ANONYMOUS = 0x1000
elif defined(solaris): elif defined(solaris):
const MAP_ANONYMOUS = 0x100 const MAP_ANONYMOUS = 0x100
elif defined(linux):
const MAP_ANONYMOUS = 0x20
else: else:
var var
MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint

View file

@ -16,43 +16,43 @@
# of the standard library! # of the standard library!
proc fputs(c: cstring, f: File) {.importc: "fputs", header: "<stdio.h>", proc c_fdopen(filehandle: cint, mode: cstring): File {.
tags: [WriteIOEffect].} importc: "fdopen", header: "<stdio.h>".}
proc fgets(c: cstring, n: int, f: File): cstring {. proc c_fputs(c: cstring, f: File): cint {.
importc: "fputs", header: "<stdio.h>", tags: [WriteIOEffect].}
proc c_fgets(c: cstring, n: cint, f: File): cstring {.
importc: "fgets", header: "<stdio.h>", tags: [ReadIOEffect].} importc: "fgets", header: "<stdio.h>", tags: [ReadIOEffect].}
proc fgetc(stream: File): cint {.importc: "fgetc", header: "<stdio.h>", proc c_fgetc(stream: File): cint {.
tags: [ReadIOEffect].} importc: "fgetc", header: "<stdio.h>", tags: [ReadIOEffect].}
proc ungetc(c: cint, f: File) {.importc: "ungetc", header: "<stdio.h>", proc c_ungetc(c: cint, f: File): cint {.
tags: [].} importc: "ungetc", header: "<stdio.h>", tags: [].}
proc putc(c: char, stream: File) {.importc: "putc", header: "<stdio.h>", proc c_putc(c: cint, stream: File): cint {.
tags: [WriteIOEffect].} importc: "putc", header: "<stdio.h>", tags: [WriteIOEffect].}
proc fprintf(f: File, frmt: cstring) {.importc: "fprintf", proc c_fflush(f: File): cint {.
header: "<stdio.h>", varargs, tags: [WriteIOEffect].} importc: "fflush", header: "<stdio.h>".}
proc strlen(c: cstring): int {. proc c_fclose(f: File): cint {.
importc: "strlen", header: "<string.h>", tags: [].} importc: "fclose", header: "<stdio.h>".}
# C routine that is used here: # C routine that is used here:
proc fread(buf: pointer, size, n: int, f: File): int {. proc c_fread(buf: pointer, size, n: csize, f: File): csize {.
importc: "fread", header: "<stdio.h>", tags: [ReadIOEffect].} importc: "fread", header: "<stdio.h>", tags: [ReadIOEffect].}
proc fseek(f: File, offset: clong, whence: int): int {. proc c_fseek(f: File, offset: clong, whence: cint): cint {.
importc: "fseek", header: "<stdio.h>", tags: [].} importc: "fseek", header: "<stdio.h>", tags: [].}
proc ftell(f: File): int {.importc: "ftell", header: "<stdio.h>", tags: [].} proc c_ftell(f: File): clong {.
proc ferror(f: File): int {.importc: "ferror", header: "<stdio.h>", tags: [].} importc: "ftell", header: "<stdio.h>", tags: [].}
proc setvbuf(stream: File, buf: pointer, typ, size: cint): cint {. proc c_ferror(f: File): cint {.
importc, header: "<stdio.h>", tags: [].} importc: "ferror", header: "<stdio.h>", tags: [].}
proc memchr(s: pointer, c: cint, n: csize): pointer {. proc c_setvbuf(f: File, buf: pointer, mode: cint, size: csize): cint {.
importc: "memchr", header: "<string.h>", tags: [].} importc: "setvbuf", header: "<stdio.h>", tags: [].}
proc memset(s: pointer, c: cint, n: csize) {. proc c_fwrite(buf: pointer, size, n: csize, f: File): cint {.
header: "<string.h>", importc: "memset", tags: [].} importc: "fwrite", header: "<stdio.h>".}
proc fwrite(buf: pointer, size, n: int, f: File): int {.
importc: "fwrite", noDecl.}
proc raiseEIO(msg: string) {.noinline, noreturn.} = proc raiseEIO(msg: string) {.noinline, noreturn.} =
sysFatal(IOError, msg) sysFatal(IOError, msg)
{.push stackTrace:off, profiler:off.} {.push stackTrace:off, profiler:off.}
proc readBuffer(f: File, buffer: pointer, len: Natural): int = proc readBuffer(f: File, buffer: pointer, len: Natural): int =
result = fread(buffer, 1, len, f) result = c_fread(buffer, 1, len, f)
proc readBytes(f: File, a: var openArray[int8|uint8], start, len: Natural): int = proc readBytes(f: File, a: var openArray[int8|uint8], start, len: Natural): int =
result = readBuffer(f, addr(a[start]), len) result = readBuffer(f, addr(a[start]), len)
@ -62,10 +62,10 @@ proc readChars(f: File, a: var openArray[char], start, len: Natural): int =
raiseEIO("buffer overflow: (start+len) > length of openarray buffer") raiseEIO("buffer overflow: (start+len) > length of openarray buffer")
result = readBuffer(f, addr(a[start]), len) result = readBuffer(f, addr(a[start]), len)
proc write(f: File, c: cstring) = fputs(c, f) proc write(f: File, c: cstring) = discard c_fputs(c, f)
proc writeBuffer(f: File, buffer: pointer, len: Natural): int = proc writeBuffer(f: File, buffer: pointer, len: Natural): int =
result = fwrite(buffer, 1, len, f) result = c_fwrite(buffer, 1, len, f)
proc writeBytes(f: File, a: openArray[int8|uint8], start, len: Natural): int = proc writeBytes(f: File, a: openArray[int8|uint8], start, len: Natural): int =
var x = cast[ptr array[0..1000_000_000, int8]](a) var x = cast[ptr array[0..1000_000_000, int8]](a)
@ -97,23 +97,28 @@ else:
const const
BufSize = 4000 BufSize = 4000
proc close*(f: File) = discard c_fclose(f)
proc readChar*(f: File): char = result = cast[char](c_fgetc(f))
proc flushFile*(f: File) = discard c_fflush(f)
proc getFileHandle*(f: File): FileHandle = c_fileno(f)
proc readLine(f: File, line: var TaintedString): bool = proc readLine(f: File, line: var TaintedString): bool =
var pos = 0 var pos = 0
# Use the currently reserved space for a first try # Use the currently reserved space for a first try
when defined(nimscript): when defined(nimscript):
var space = 80 var space: cint = 80
else: else:
var space = cast[PGenericSeq](line.string).space var space: cint = cint(cast[PGenericSeq](line.string).space)
line.string.setLen(space) line.string.setLen(space)
while true: while true:
# memset to \l so that we can tell how far fgets wrote, even on EOF, where # memset to \l so that we can tell how far fgets wrote, even on EOF, where
# fgets doesn't append an \l # fgets doesn't append an \l
memset(addr line.string[pos], '\l'.ord, space) c_memset(addr line.string[pos], '\l'.ord, space)
if fgets(addr line.string[pos], space, f) == nil: if c_fgets(addr line.string[pos], space, f) == nil:
line.string.setLen(0) line.string.setLen(0)
return false return false
let m = memchr(addr line.string[pos], '\l'.ord, space) let m = c_memchr(addr line.string[pos], '\l'.ord, space)
if m != nil: if m != nil:
# \l found: Could be our own or the one by fgets, in any case, we're done # \l found: Could be our own or the one by fgets, in any case, we're done
var last = cast[ByteAddress](m) - cast[ByteAddress](addr line.string[0]) var last = cast[ByteAddress](m) - cast[ByteAddress](addr line.string[0])
@ -142,23 +147,23 @@ proc readLine(f: File): TaintedString =
proc write(f: File, i: int) = proc write(f: File, i: int) =
when sizeof(int) == 8: when sizeof(int) == 8:
fprintf(f, "%lld", i) c_fprintf(f, "%lld", i)
else: else:
fprintf(f, "%ld", i) c_fprintf(f, "%ld", i)
proc write(f: File, i: BiggestInt) = proc write(f: File, i: BiggestInt) =
when sizeof(BiggestInt) == 8: when sizeof(BiggestInt) == 8:
fprintf(f, "%lld", i) c_fprintf(f, "%lld", i)
else: else:
fprintf(f, "%ld", i) c_fprintf(f, "%ld", i)
proc write(f: File, b: bool) = proc write(f: File, b: bool) =
if b: write(f, "true") if b: write(f, "true")
else: write(f, "false") else: write(f, "false")
proc write(f: File, r: float32) = fprintf(f, "%g", r) proc write(f: File, r: float32) = c_fprintf(f, "%g", r)
proc write(f: File, r: BiggestFloat) = fprintf(f, "%g", r) proc write(f: File, r: BiggestFloat) = c_fprintf(f, "%g", r)
proc write(f: File, c: char) = putc(c, f) proc write(f: File, c: char) = discard c_putc(ord(c), f)
proc write(f: File, a: varargs[string, `$`]) = proc write(f: File, a: varargs[string, `$`]) =
for x in items(a): write(f, x) for x in items(a): write(f, x)
@ -178,15 +183,15 @@ proc readAllBuffer(file: File): string =
proc rawFileSize(file: File): int = proc rawFileSize(file: File): int =
# this does not raise an error opposed to `getFileSize` # this does not raise an error opposed to `getFileSize`
var oldPos = ftell(file) var oldPos = c_ftell(file)
discard fseek(file, 0, 2) # seek the end of the file discard c_fseek(file, 0, 2) # seek the end of the file
result = ftell(file) result = c_ftell(file)
discard fseek(file, clong(oldPos), 0) discard c_fseek(file, clong(oldPos), 0)
proc endOfFile(f: File): bool = proc endOfFile(f: File): bool =
# do not blame me; blame the ANSI C standard this is so brain-damaged # do not blame me; blame the ANSI C standard this is so brain-damaged
var c = fgetc(f) var c = c_fgetc(f)
ungetc(c, f) discard c_ungetc(c, f)
return c < 0'i32 return c < 0'i32
proc readAllFile(file: File, len: int): string = proc readAllFile(file: File, len: int): string =
@ -197,7 +202,7 @@ proc readAllFile(file: File, len: int): string =
if endOfFile(file): if endOfFile(file):
if bytes < len: if bytes < len:
result.setLen(bytes) result.setLen(bytes)
elif ferror(file) != 0: elif c_ferror(file) != 0:
raiseEIO("error while reading from file") raiseEIO("error while reading from file")
else: else:
# We read all the bytes but did not reach the EOF # We read all the bytes but did not reach the EOF
@ -272,6 +277,22 @@ const
# should not be translated. # should not be translated.
when defined(posix) and not defined(nimscript): when defined(posix) and not defined(nimscript):
when defined(linux) and defined(amd64):
type
Mode {.importc: "mode_t", header: "<sys/types.h>".} = cint
# fillers ensure correct size & offsets
Stat {.importc: "struct stat",
header: "<sys/stat.h>", final, pure.} = object ## struct stat
filler_1: array[24, char]
st_mode: Mode ## Mode of file
filler_2: array[144 - 24 - 4, char]
proc S_ISDIR(m: Mode): bool =
## Test for a directory.
(m and 0o170000) == 0o40000
else:
type type
Mode {.importc: "mode_t", header: "<sys/types.h>".} = cint Mode {.importc: "mode_t", header: "<sys/types.h>".} = cint
@ -282,7 +303,8 @@ when defined(posix) and not defined(nimscript):
proc S_ISDIR(m: Mode): bool {.importc, header: "<sys/stat.h>".} proc S_ISDIR(m: Mode): bool {.importc, header: "<sys/stat.h>".}
## Test for a directory. ## Test for a directory.
proc fstat(a1: cint, a2: var Stat): cint {.importc, header: "<sys/stat.h>".} proc c_fstat(a1: cint, a2: var Stat): cint {.
importc: "fstat", header: "<sys/stat.h>".}
proc open(f: var File, filename: string, proc open(f: var File, filename: string,
mode: FileMode = fmRead, mode: FileMode = fmRead,
@ -295,45 +317,38 @@ proc open(f: var File, filename: string,
# be opened. # be opened.
var f2 = cast[File](p) var f2 = cast[File](p)
var res: Stat var res: Stat
if fstat(getFileHandle(f2), res) >= 0'i32 and S_ISDIR(res.st_mode): if c_fstat(getFileHandle(f2), res) >= 0'i32 and S_ISDIR(res.st_mode):
close(f2) close(f2)
return false return false
result = true result = true
f = cast[File](p) f = cast[File](p)
if bufSize > 0 and bufSize <= high(cint).int: if bufSize > 0 and bufSize <= high(cint).int:
discard setvbuf(f, nil, IOFBF, bufSize.cint) discard c_setvbuf(f, nil, IOFBF, bufSize.cint)
elif bufSize == 0: elif bufSize == 0:
discard setvbuf(f, nil, IONBF, 0) discard c_setvbuf(f, nil, IONBF, 0)
proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool = proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool =
var p: pointer = freopen(filename, FormatOpen[mode], f) var p: pointer = freopen(filename, FormatOpen[mode], f)
result = p != nil result = p != nil
proc fdopen(filehandle: FileHandle, mode: cstring): File {.
importc: "fdopen", header: "<stdio.h>".}
proc open(f: var File, filehandle: FileHandle, mode: FileMode): bool = proc open(f: var File, filehandle: FileHandle, mode: FileMode): bool =
f = fdopen(filehandle, FormatOpen[mode]) f = c_fdopen(filehandle, FormatOpen[mode])
result = f != nil result = f != nil
proc setFilePos(f: File, pos: int64) = proc setFilePos(f: File, pos: int64) =
if fseek(f, clong(pos), 0) != 0: if c_fseek(f, clong(pos), 0) != 0:
raiseEIO("cannot set file position") raiseEIO("cannot set file position")
proc getFilePos(f: File): int64 = proc getFilePos(f: File): int64 =
result = ftell(f) result = c_ftell(f)
if result < 0: raiseEIO("cannot retrieve file position") if result < 0: raiseEIO("cannot retrieve file position")
proc getFileSize(f: File): int64 = proc getFileSize(f: File): int64 =
var oldPos = getFilePos(f) var oldPos = getFilePos(f)
discard fseek(f, 0, 2) # seek the end of the file discard c_fseek(f, 0, 2) # seek the end of the file
result = getFilePos(f) result = getFilePos(f)
setFilePos(f, oldPos) setFilePos(f, oldPos)
when not declared(close):
proc close(f: File) {.
importc: "fclose", header: "<stdio.h>", tags: [].}
proc readFile(filename: string): TaintedString = proc readFile(filename: string): TaintedString =
var f: File var f: File
if open(f, filename): if open(f, filename):

View file

@ -30,7 +30,7 @@ proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
if a == b: return true if a == b: return true
if a == nil or b == nil: return false if a == nil or b == nil: return false
return a.len == b.len and return a.len == b.len and
c_memcmp(a.data, b.data, a.len) == 0'i32 equalMem(addr(a.data), addr(b.data), a.len)
when declared(allocAtomic): when declared(allocAtomic):
template allocStr(size: expr): expr = template allocStr(size: expr): expr =
@ -71,7 +71,7 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.compilerProc.} =
if len > 0: if len > 0:
result = rawNewStringNoInit(len) result = rawNewStringNoInit(len)
result.len = len result.len = len
c_memcpy(result.data, addr(s.data[start]), len) copyMem(addr(result.data), addr(s.data[start]), len)
result.data[len] = '\0' result.data[len] = '\0'
else: else:
result = rawNewString(len) result = rawNewString(len)
@ -82,10 +82,10 @@ proc copyStr(s: NimString, start: int): NimString {.compilerProc.} =
proc toNimStr(str: cstring, len: int): NimString {.compilerProc.} = proc toNimStr(str: cstring, len: int): NimString {.compilerProc.} =
result = rawNewStringNoInit(len) result = rawNewStringNoInit(len)
result.len = len result.len = len
c_memcpy(result.data, str, len + 1) copyMem(addr(result.data), str, len + 1)
proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} = proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} =
result = toNimStr(str, c_strlen(str)) result = toNimStr(str, str.len)
proc copyString(src: NimString): NimString {.compilerRtl.} = proc copyString(src: NimString): NimString {.compilerRtl.} =
if src != nil: if src != nil:
@ -94,7 +94,7 @@ proc copyString(src: NimString): NimString {.compilerRtl.} =
else: else:
result = rawNewStringNoInit(src.len) result = rawNewStringNoInit(src.len)
result.len = src.len result.len = src.len
c_memcpy(result.data, src.data, src.len + 1) copyMem(addr(result.data), addr(src.data), src.len + 1)
proc copyStringRC1(src: NimString): NimString {.compilerRtl.} = proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
if src != nil: if src != nil:
@ -107,7 +107,7 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
else: else:
result = rawNewStringNoInit(src.len) result = rawNewStringNoInit(src.len)
result.len = src.len result.len = src.len
c_memcpy(result.data, src.data, src.len + 1) copyMem(addr(result.data), addr(src.data), src.len + 1)
proc hashString(s: string): int {.compilerproc.} = proc hashString(s: string): int {.compilerproc.} =
@ -177,7 +177,7 @@ proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
# DO NOT UPDATE LEN YET: dest.len = newLen # DO NOT UPDATE LEN YET: dest.len = newLen
proc appendString(dest, src: NimString) {.compilerproc, inline.} = proc appendString(dest, src: NimString) {.compilerproc, inline.} =
c_memcpy(addr(dest.data[dest.len]), src.data, src.len + 1) copyMem(addr(dest.data[dest.len]), addr(src.data), src.len + 1)
inc(dest.len, src.len) inc(dest.len, src.len)
proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} = proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} =
@ -301,8 +301,8 @@ proc nimFloatToStr(f: float): string {.compilerproc.} =
else: else:
result = $buf result = $buf
proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc, proc c_strtod(buf: cstring, endptr: ptr cstring): float64 {.
header: "<stdlib.h>", noSideEffect.} importc: "strtod", header: "<stdlib.h>", noSideEffect.}
const const
IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'} IdentChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'}
@ -460,7 +460,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
t[ti-2] = ('0'.ord + abs_exponent mod 10).char; abs_exponent = abs_exponent div 10 t[ti-2] = ('0'.ord + abs_exponent mod 10).char; abs_exponent = abs_exponent div 10
t[ti-3] = ('0'.ord + abs_exponent mod 10).char t[ti-3] = ('0'.ord + abs_exponent mod 10).char
number = strtod(t, nil) number = c_strtod(t, nil)
proc nimInt64ToStr(x: int64): string {.compilerRtl.} = proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
result = newString(sizeof(x)*4) result = newString(sizeof(x)*4)

View file

@ -117,6 +117,11 @@ else:
schedh = "#define _GNU_SOURCE\n#include <sched.h>" schedh = "#define _GNU_SOURCE\n#include <sched.h>"
pthreadh = "#define _GNU_SOURCE\n#include <pthread.h>" pthreadh = "#define _GNU_SOURCE\n#include <pthread.h>"
when defined(linux):
type Time = clong
else:
type Time = int
type type
SysThread {.importc: "pthread_t", header: "<sys/types.h>", SysThread {.importc: "pthread_t", header: "<sys/types.h>",
final, pure.} = object final, pure.} = object
@ -125,8 +130,8 @@ else:
Timespec {.importc: "struct timespec", Timespec {.importc: "struct timespec",
header: "<time.h>", final, pure.} = object header: "<time.h>", final, pure.} = object
tv_sec: int tv_sec: Time
tv_nsec: int tv_nsec: clong
{.deprecated: [TSysThread: SysThread, Tpthread_attr: PThreadAttr, {.deprecated: [TSysThread: SysThread, Tpthread_attr: PThreadAttr,
Ttimespec: Timespec].} Ttimespec: Timespec].}

View file

@ -78,11 +78,16 @@ elif defined(posixRealtime):
else: else:
# fallback Posix implementation: # fallback Posix implementation:
when defined(linux):
type Time = clong
else:
type Time = int
type type
Timeval {.importc: "struct timeval", header: "<sys/select.h>", Timeval {.importc: "struct timeval", header: "<sys/select.h>",
final, pure.} = object ## struct timeval final, pure.} = object ## struct timeval
tv_sec: int ## Seconds. tv_sec: Time ## Seconds.
tv_usec: int ## Microseconds. tv_usec: clong ## Microseconds.
{.deprecated: [Ttimeval: Timeval].} {.deprecated: [Ttimeval: Timeval].}
proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {. proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {.
importc: "gettimeofday", header: "<sys/time.h>".} importc: "gettimeofday", header: "<sys/time.h>".}

View file

@ -104,12 +104,7 @@ proc newWideCString*(source: cstring, L: int): WideCString =
proc newWideCString*(s: cstring): WideCString = proc newWideCString*(s: cstring): WideCString =
if s.isNil: return nil if s.isNil: return nil
when not declared(c_strlen): result = newWideCString(s, s.len)
proc c_strlen(a: cstring): int {.
header: "<string.h>", noSideEffect, importc: "strlen".}
let L = c_strlen(s)
result = newWideCString(s, L)
proc newWideCString*(s: string): WideCString = proc newWideCString*(s: string): WideCString =
result = newWideCString(s, s.len) result = newWideCString(s, s.len)