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
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 zeroMem(a, size) memset(a, 0, size)
#define equalMem(a, b, size) (memcmp(a, b, size) == 0)
#define STRING_LITERAL(name, str, length) \
static const struct { \
TGenericSeq Sup; \

View File

@@ -257,12 +257,10 @@ type MemSlice* = object ## represent slice of a MemFile for iteration over deli
data*: pointer
size*: int
proc c_memcpy(a, b: pointer, n: int) {.importc: "memcpy", header: "<string.h>".}
proc `$`*(ms: MemSlice): string {.inline.} =
## Return a Nim string built from a MemSlice.
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'
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):
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'
yield buf

View File

@@ -26,7 +26,6 @@ elif defined(posix):
else:
{.error: "OS module not ported to your operating system!".}
include "system/ansi_c"
include ospaths
when defined(posix):
@@ -37,6 +36,23 @@ when defined(posix):
var
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.} =
## Retrieves the operating system's error flag, ``errno``.
## On Windows ``GetLastError`` is checked before ``errno``.
@@ -61,7 +77,7 @@ proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
result = $msgbuf
if msgbuf != nil: localFree(msgbuf)
if errno != 0'i32:
result = $os.strerror(errno)
result = $os.c_strerror(errno)
{.push warning[deprecated]: off.}
proc raiseOSError*(msg: string = "") {.noinline, rtl, extern: "nos$1",
@@ -114,7 +130,7 @@ proc osErrorMsg*(errorCode: OSErrorCode): string =
if msgbuf != nil: localFree(msgbuf)
else:
if errorCode != OSErrorCode(0'i32):
result = $os.strerror(errorCode.int32)
result = $os.c_strerror(errorCode.int32)
proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} =
## Raises an ``OSError`` exception. The ``errorCode`` will determine the

View File

@@ -306,67 +306,67 @@ proc peekLine*(s: Stream): TaintedString =
defer: setPosition(s, pos)
result = readLine(s)
type
StringStream* = ref StringStreamObj ## a stream that encapsulates a string
StringStreamObj* = object of StreamObj
data*: string
pos: int
{.deprecated: [PStringStream: StringStream, TStringStream: StringStreamObj].}
proc ssAtEnd(s: Stream): bool =
var s = StringStream(s)
return s.pos >= s.data.len
proc ssSetPosition(s: Stream, pos: int) =
var s = StringStream(s)
s.pos = clamp(pos, 0, s.data.len)
proc ssGetPosition(s: Stream): int =
var s = StringStream(s)
return s.pos
proc ssReadData(s: Stream, buffer: pointer, bufLen: int): int =
var s = StringStream(s)
result = min(bufLen, s.data.len - s.pos)
if result > 0:
copyMem(buffer, addr(s.data[s.pos]), result)
inc(s.pos, result)
proc ssPeekData(s: Stream, buffer: pointer, bufLen: int): int =
var s = StringStream(s)
result = min(bufLen, s.data.len - s.pos)
if result > 0:
copyMem(buffer, addr(s.data[s.pos]), result)
proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) =
var s = StringStream(s)
if bufLen <= 0:
return
if s.pos + bufLen > s.data.len:
setLen(s.data, s.pos + bufLen)
copyMem(addr(s.data[s.pos]), buffer, bufLen)
inc(s.pos, bufLen)
proc ssClose(s: Stream) =
var s = StringStream(s)
s.data = nil
proc newStringStream*(s: string = ""): StringStream =
## creates a new stream from the string `s`.
new(result)
result.data = s
result.pos = 0
result.closeImpl = ssClose
result.atEndImpl = ssAtEnd
result.setPositionImpl = ssSetPosition
result.getPositionImpl = ssGetPosition
result.readDataImpl = ssReadData
result.peekDataImpl = ssPeekData
result.writeDataImpl = ssWriteData
when not defined(js):
type
StringStream* = ref StringStreamObj ## a stream that encapsulates a string
StringStreamObj* = object of StreamObj
data*: string
pos: int
{.deprecated: [PStringStream: StringStream, TStringStream: StringStreamObj].}
proc ssAtEnd(s: Stream): bool =
var s = StringStream(s)
return s.pos >= s.data.len
proc ssSetPosition(s: Stream, pos: int) =
var s = StringStream(s)
s.pos = clamp(pos, 0, s.data.len)
proc ssGetPosition(s: Stream): int =
var s = StringStream(s)
return s.pos
proc ssReadData(s: Stream, buffer: pointer, bufLen: int): int =
var s = StringStream(s)
result = min(bufLen, s.data.len - s.pos)
if result > 0:
copyMem(buffer, addr(s.data[s.pos]), result)
inc(s.pos, result)
proc ssPeekData(s: Stream, buffer: pointer, bufLen: int): int =
var s = StringStream(s)
result = min(bufLen, s.data.len - s.pos)
if result > 0:
copyMem(buffer, addr(s.data[s.pos]), result)
proc ssWriteData(s: Stream, buffer: pointer, bufLen: int) =
var s = StringStream(s)
if bufLen <= 0:
return
if s.pos + bufLen > s.data.len:
setLen(s.data, s.pos + bufLen)
copyMem(addr(s.data[s.pos]), buffer, bufLen)
inc(s.pos, bufLen)
proc ssClose(s: Stream) =
var s = StringStream(s)
s.data = nil
proc newStringStream*(s: string = ""): StringStream =
## creates a new stream from the string `s`.
new(result)
result.data = s
result.pos = 0
result.closeImpl = ssClose
result.atEndImpl = ssAtEnd
result.setPositionImpl = ssSetPosition
result.getPositionImpl = ssGetPosition
result.readDataImpl = ssReadData
result.peekDataImpl = ssPeekData
result.writeDataImpl = ssWriteData
type
FileStream* = ref FileStreamObj ## a stream that encapsulates a `File`
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:
## or `limit`:idx: a string's length.
when not defined(nimscript):
proc zeroMem*(p: pointer, size: Natural) {.importc, noDecl, benign.}
when not defined(nimscript) and not defined(JS):
proc zeroMem*(p: pointer, size: Natural) {.inline, benign.}
## overwrites the contents of the memory at ``p`` with the value 0.
## Exactly ``size`` bytes will be overwritten. Like any procedure
## dealing with raw memory this is *unsafe*.
proc copyMem*(dest, source: pointer, size: Natural) {.
importc: "memcpy", header: "<string.h>", benign.}
proc copyMem*(dest, source: pointer, size: Natural) {.inline, benign.}
## copies the contents from the memory at ``source`` to the memory
## at ``dest``. Exactly ``size`` bytes will be copied. The memory
## regions may not overlap. Like any procedure dealing with raw
## memory this is *unsafe*.
proc moveMem*(dest, source: pointer, size: Natural) {.
importc: "memmove", header: "<string.h>", benign.}
proc moveMem*(dest, source: pointer, size: Natural) {.inline, benign.}
## copies the contents from the memory at ``source`` to the memory
## at ``dest``. Exactly ``size`` bytes will be copied. The memory
## regions may overlap, ``moveMem`` handles this case appropriately
## and is thus somewhat more safe than ``copyMem``. Like any procedure
## dealing with raw memory this is still *unsafe*, though.
proc equalMem*(a, b: pointer, size: Natural): bool {.
importc: "equalMem", noDecl, noSideEffect.}
proc equalMem*(a, b: pointer, size: Natural): bool {.inline, noSideEffect.}
## compares the memory blocks ``a`` and ``b``. ``size`` bytes will
## be compared. If the blocks are equal, true is returned, false
## otherwise. Like any procedure dealing with raw memory this is
## *unsafe*.
when not defined(nimscript):
when hasAlloc:
proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign.}
## 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].}
when not defined(nimscript):
include "system/ansi_c"
include "system/ansi_c"
when not defined(nimscript):
proc cmp(x, y: string): int =
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:
proc cmp(x, y: string): int =
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.
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:
var
@@ -2670,6 +2662,21 @@ when not defined(JS): #and not defined(nimscript):
stderr* {.importc: "stderr", header: "<stdio.h>".}: File
## 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):
template stdmsg*: File = stdout
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.
proc close*(f: File) {.importc: "fclose", header: "<stdio.h>", tags: [].}
proc close*(f: File) {.tags: [].}
## Closes the file.
proc endOfFile*(f: File): bool {.tags: [], benign.}
## Returns true iff `f` is at the end.
proc readChar*(f: File): char {.
importc: "fgetc", header: "<stdio.h>", tags: [ReadIOEffect].}
proc readChar*(f: File): char {.tags: [ReadIOEffect].}
## 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.
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
## read from the file `f`. The file's first byte has the index zero.
proc getFileHandle*(f: File): FileHandle {.importc: "fileno",
header: "<stdio.h>"}
proc getFileHandle*(f: File): FileHandle
## returns the OS file handle of the file ``f``. This is only useful for
## platform specific programming.

View File

@@ -324,9 +324,9 @@ proc contains[T](list, x: T): bool =
proc writeFreeList(a: MemRegion) =
var it = a.freeChunksList
c_fprintf(c_stdout, "freeChunksList: %p\n", it)
c_fprintf(stdout, "freeChunksList: %p\n", it)
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

View File

@@ -13,60 +13,42 @@
{.push hints:off}
proc c_strcmp(a, b: cstring): cint {.header: "<string.h>",
noSideEffect, importc: "strcmp".}
proc c_memcmp(a, b: cstring, size: int): cint {.header: "<string.h>",
noSideEffect, importc: "memcmp".}
proc c_memcpy(a, b: cstring, size: int) {.header: "<string.h>", importc: "memcpy".}
proc c_strlen(a: cstring): int {.header: "<string.h>",
noSideEffect, importc: "strlen".}
proc c_memset(p: pointer, value: cint, size: int) {.
header: "<string.h>", importc: "memset".}
when not declared(File):
type
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
proc c_memchr(s: pointer, c: cint, n: csize): pointer {.
importc: "memchr", header: "<string.h>".}
proc c_memcmp(a, b: pointer, size: csize): cint {.
importc: "memcmp", header: "<string.h>", noSideEffect.}
proc c_memcpy(a, b: pointer, size: csize): pointer {.
importc: "memcpy", header: "<string.h>", discardable.}
proc c_memmove(a, b: pointer, size: csize): pointer {.
importc: "memmove", header: "<string.h>",discardable.}
proc c_memset(p: pointer, value: cint, size: csize): pointer {.
importc: "memset", header: "<string.h>", discardable.}
proc c_strcmp(a, b: cstring): cint {.
importc: "strcmp", header: "<string.h>", noSideEffect.}
type
C_JmpBuf {.importc: "jmp_buf", header: "<setjmp.h>".} = object
when not defined(vm):
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 defined(windows):
const
SIGABRT = cint(22)
SIGFPE = cint(8)
SIGILL = cint(4)
SIGINT = cint(2)
SIGSEGV = cint(11)
SIGTERM = cint(15)
elif defined(macosx) or defined(linux):
const
SIGABRT = cint(6)
SIGFPE = cint(8)
SIGILL = cint(4)
SIGINT = cint(2)
SIGSEGV = cint(11)
SIGTERM = cint(15)
SIGPIPE = cint(13)
else:
when NoFakeVars:
when defined(windows):
const
SIGABRT = cint(22)
SIGFPE = cint(8)
SIGILL = cint(4)
SIGINT = cint(2)
SIGSEGV = cint(11)
SIGTERM = cint(15)
elif defined(macosx) or defined(linux):
const
SIGABRT = cint(6)
SIGFPE = cint(8)
SIGILL = cint(4)
SIGINT = cint(2)
SIGSEGV = cint(11)
SIGTERM = cint(15)
SIGPIPE = cint(13)
else:
{.error: "SIGABRT not ported to your platform".}
{.error: "SIGABRT not ported to your platform".}
else:
var
SIGINT {.importc: "SIGINT", nodecl.}: cint
@@ -78,10 +60,7 @@ when not declared(SIGINT):
var SIGPIPE {.importc: "SIGPIPE", nodecl.}: cint
when defined(macosx):
when NoFakeVars:
const SIGBUS = cint(10)
else:
var SIGBUS {.importc: "SIGBUS", nodecl.}: cint
const SIGBUS = cint(10)
else:
template SIGBUS: expr = SIGSEGV
@@ -103,72 +82,27 @@ else:
proc c_setjmp(jmpb: C_JmpBuf): cint {.
header: "<setjmp.h>", importc: "setjmp".}
proc c_signal(sign: cint, handler: proc (a: cint) {.noconv.}) {.
importc: "signal", header: "<signal.h>".}
proc c_raise(sign: cint) {.importc: "raise", header: "<signal.h>".}
type c_sighandler_t = proc (a: cint) {.noconv.}
proc c_signal(sign: cint, handler: proc (a: cint) {.noconv.}): c_sighandler_t {.
importc: "signal", header: "<signal.h>", discardable.}
proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs",
header: "<stdio.h>".}
proc c_fgets(c: cstring, n: int, f: C_TextFileStar): cstring {.
importc: "fgets", header: "<stdio.h>".}
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_fprintf(f: File, frmt: cstring): cint {.
importc: "fprintf", header: "<stdio.h>", varargs, discardable.}
proc c_printf(frmt: cstring): cint {.
importc: "printf", header: "<stdio.h>", varargs, discardable.}
proc c_fopen(filename, mode: cstring): C_TextFileStar {.
importc: "fopen", header: "<stdio.h>".}
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.}
proc c_sprintf(buf, frmt: cstring): cint {.
importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.}
# 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 {.
importc: "fread", header: "<stdio.h>".}
proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {.
importc: "fseek", header: "<stdio.h>".}
proc c_fileno(f: File): cint {.
importc: "fileno", header: "<fcntl.h>".}
proc c_fwrite(buf: pointer, size, n: int, f: C_BinaryFileStar): int {.
importc: "fwrite", header: "<stdio.h>".}
proc c_exit(errorcode: cint) {.importc: "exit", header: "<stdlib.h>".}
proc c_ferror(stream: C_TextFileStar): bool {.
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 {.
proc c_malloc(size: csize): pointer {.
importc: "malloc", header: "<stdlib.h>".}
proc c_free(p: pointer) {.
importc: "free", header: "<stdlib.h>".}
proc c_realloc(p: pointer, newsize: csize): pointer {.
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}

View File

@@ -51,7 +51,6 @@ proc chckRangeF(x, a, b: float): float =
proc chckNil(p: pointer) =
if p == nil:
sysFatal(ValueError, "attempt to write to a nil address")
#c_raise(SIGSEGV)
proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
# 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
# is one of: \ / :
# depending on the OS case does not matter!
var blen: int = c_strlen(bp)
var clen: int = c_strlen(c)
var blen: int = bp.len
var clen: int = c.len
if blen > clen: return false
# check for \ / :
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:
result = rawNewStringNoInit(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) =
var

View File

@@ -52,11 +52,14 @@ when defined(posix):
#
# c stuff:
var
RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: int
when defined(linux) or defined(macosx):
const RTLD_NOW = cint(2)
else:
var
RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: cint
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>".}
proc dlsym(lib: LibHandle, name: cstring): ProcAddr {.
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 =
while true:
var c = fgetc(f)
var c = c_fgetc(f)
if c < 0'i32:
if line.len > 0: break
else: return false
if c == 10'i32: break # LF
if c == 13'i32: # CR
c = fgetc(f) # is the next char LF?
if c != 10'i32: ungetc(c, f) # no, put the character back
c = c_fgetc(f) # is the next char LF?
if c != 10'i32: discard c_ungetc(c, f) # no, put the character back
break
add line, chr(int(c))
result = true

View File

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

View File

@@ -152,10 +152,10 @@ proc writeCell(msg: cstring, c: PCell) =
var kind = -1
if c.typ != nil: kind = ord(c.typ.kind)
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)
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)
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.} =
result = rawNewStringNoInit(dr, 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;
dest, src: pointer, mt: PNimType) =
@@ -417,15 +417,15 @@ proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src
proc alloc(size: Natural): pointer =
result = cmalloc(size)
result = c_malloc(size)
if result == nil: raiseOutOfMem()
proc alloc0(size: Natural): pointer =
result = alloc(size)
zeroMem(result, size)
proc realloc(p: pointer, newsize: Natural): pointer =
result = crealloc(p, newsize)
result = c_realloc(p, newsize)
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 =
# 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 allocShared(size: Natural): pointer =
result = cmalloc(size)
result = c_malloc(size)
if result == nil: raiseOutOfMem()
proc allocShared0(size: Natural): pointer =
result = alloc(size)
zeroMem(result, size)
proc reallocShared(p: pointer, newsize: Natural): pointer =
result = crealloc(p, newsize)
result = c_realloc(p, newsize)
if result == nil: raiseOutOfMem()
proc deallocShared(p: pointer) = cfree(p)
proc deallocShared(p: pointer) = c_free(p)
when hasThreadSupport:
proc getFreeSharedMem(): int = 0

View File

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

View File

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

View File

@@ -16,43 +16,43 @@
# of the standard library!
proc fputs(c: cstring, f: File) {.importc: "fputs", header: "<stdio.h>",
tags: [WriteIOEffect].}
proc fgets(c: cstring, n: int, f: File): cstring {.
proc c_fdopen(filehandle: cint, mode: cstring): File {.
importc: "fdopen", header: "<stdio.h>".}
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].}
proc fgetc(stream: File): cint {.importc: "fgetc", header: "<stdio.h>",
tags: [ReadIOEffect].}
proc ungetc(c: cint, f: File) {.importc: "ungetc", header: "<stdio.h>",
tags: [].}
proc putc(c: char, stream: File) {.importc: "putc", header: "<stdio.h>",
tags: [WriteIOEffect].}
proc fprintf(f: File, frmt: cstring) {.importc: "fprintf",
header: "<stdio.h>", varargs, tags: [WriteIOEffect].}
proc strlen(c: cstring): int {.
importc: "strlen", header: "<string.h>", tags: [].}
proc c_fgetc(stream: File): cint {.
importc: "fgetc", header: "<stdio.h>", tags: [ReadIOEffect].}
proc c_ungetc(c: cint, f: File): cint {.
importc: "ungetc", header: "<stdio.h>", tags: [].}
proc c_putc(c: cint, stream: File): cint {.
importc: "putc", header: "<stdio.h>", tags: [WriteIOEffect].}
proc c_fflush(f: File): cint {.
importc: "fflush", header: "<stdio.h>".}
proc c_fclose(f: File): cint {.
importc: "fclose", header: "<stdio.h>".}
# 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].}
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: [].}
proc ftell(f: File): int {.importc: "ftell", header: "<stdio.h>", tags: [].}
proc ferror(f: File): int {.importc: "ferror", header: "<stdio.h>", tags: [].}
proc setvbuf(stream: File, buf: pointer, typ, size: cint): cint {.
importc, header: "<stdio.h>", tags: [].}
proc memchr(s: pointer, c: cint, n: csize): pointer {.
importc: "memchr", header: "<string.h>", tags: [].}
proc memset(s: pointer, c: cint, n: csize) {.
header: "<string.h>", importc: "memset", tags: [].}
proc fwrite(buf: pointer, size, n: int, f: File): int {.
importc: "fwrite", noDecl.}
proc c_ftell(f: File): clong {.
importc: "ftell", header: "<stdio.h>", tags: [].}
proc c_ferror(f: File): cint {.
importc: "ferror", header: "<stdio.h>", tags: [].}
proc c_setvbuf(f: File, buf: pointer, mode: cint, size: csize): cint {.
importc: "setvbuf", header: "<stdio.h>", tags: [].}
proc c_fwrite(buf: pointer, size, n: csize, f: File): cint {.
importc: "fwrite", header: "<stdio.h>".}
proc raiseEIO(msg: string) {.noinline, noreturn.} =
sysFatal(IOError, msg)
{.push stackTrace:off, profiler:off.}
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 =
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")
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 =
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 =
var x = cast[ptr array[0..1000_000_000, int8]](a)
@@ -97,23 +97,28 @@ else:
const
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 =
var pos = 0
# Use the currently reserved space for a first try
when defined(nimscript):
var space = 80
var space: cint = 80
else:
var space = cast[PGenericSeq](line.string).space
var space: cint = cint(cast[PGenericSeq](line.string).space)
line.string.setLen(space)
while true:
# memset to \l so that we can tell how far fgets wrote, even on EOF, where
# fgets doesn't append an \l
memset(addr line.string[pos], '\l'.ord, space)
if fgets(addr line.string[pos], space, f) == nil:
c_memset(addr line.string[pos], '\l'.ord, space)
if c_fgets(addr line.string[pos], space, f) == nil:
line.string.setLen(0)
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:
# \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])
@@ -142,23 +147,23 @@ proc readLine(f: File): TaintedString =
proc write(f: File, i: int) =
when sizeof(int) == 8:
fprintf(f, "%lld", i)
c_fprintf(f, "%lld", i)
else:
fprintf(f, "%ld", i)
c_fprintf(f, "%ld", i)
proc write(f: File, i: BiggestInt) =
when sizeof(BiggestInt) == 8:
fprintf(f, "%lld", i)
c_fprintf(f, "%lld", i)
else:
fprintf(f, "%ld", i)
c_fprintf(f, "%ld", i)
proc write(f: File, b: bool) =
if b: write(f, "true")
else: write(f, "false")
proc write(f: File, r: float32) = fprintf(f, "%g", r)
proc write(f: File, r: BiggestFloat) = fprintf(f, "%g", r)
proc write(f: File, r: float32) = c_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, `$`]) =
for x in items(a): write(f, x)
@@ -178,15 +183,15 @@ proc readAllBuffer(file: File): string =
proc rawFileSize(file: File): int =
# this does not raise an error opposed to `getFileSize`
var oldPos = ftell(file)
discard fseek(file, 0, 2) # seek the end of the file
result = ftell(file)
discard fseek(file, clong(oldPos), 0)
var oldPos = c_ftell(file)
discard c_fseek(file, 0, 2) # seek the end of the file
result = c_ftell(file)
discard c_fseek(file, clong(oldPos), 0)
proc endOfFile(f: File): bool =
# do not blame me; blame the ANSI C standard this is so brain-damaged
var c = fgetc(f)
ungetc(c, f)
var c = c_fgetc(f)
discard c_ungetc(c, f)
return c < 0'i32
proc readAllFile(file: File, len: int): string =
@@ -197,7 +202,7 @@ proc readAllFile(file: File, len: int): string =
if endOfFile(file):
if bytes < len:
result.setLen(bytes)
elif ferror(file) != 0:
elif c_ferror(file) != 0:
raiseEIO("error while reading from file")
else:
# We read all the bytes but did not reach the EOF
@@ -272,17 +277,34 @@ const
# should not be translated.
when defined(posix) and not defined(nimscript):
type
Mode {.importc: "mode_t", header: "<sys/types.h>".} = cint
when defined(linux) and defined(amd64):
type
Mode {.importc: "mode_t", header: "<sys/types.h>".} = cint
Stat {.importc: "struct stat",
header: "<sys/stat.h>", final, pure.} = object ## struct stat
st_mode: Mode ## Mode of file
# 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 {.importc, header: "<sys/stat.h>".}
## Test for a directory.
proc S_ISDIR(m: Mode): bool =
## Test for a directory.
(m and 0o170000) == 0o40000
proc fstat(a1: cint, a2: var Stat): cint {.importc, header: "<sys/stat.h>".}
else:
type
Mode {.importc: "mode_t", header: "<sys/types.h>".} = cint
Stat {.importc: "struct stat",
header: "<sys/stat.h>", final, pure.} = object ## struct stat
st_mode: Mode ## Mode of file
proc S_ISDIR(m: Mode): bool {.importc, header: "<sys/stat.h>".}
## Test for a directory.
proc c_fstat(a1: cint, a2: var Stat): cint {.
importc: "fstat", header: "<sys/stat.h>".}
proc open(f: var File, filename: string,
mode: FileMode = fmRead,
@@ -295,45 +317,38 @@ proc open(f: var File, filename: string,
# be opened.
var f2 = cast[File](p)
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)
return false
result = true
f = cast[File](p)
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:
discard setvbuf(f, nil, IONBF, 0)
discard c_setvbuf(f, nil, IONBF, 0)
proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool =
var p: pointer = freopen(filename, FormatOpen[mode], f)
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 =
f = fdopen(filehandle, FormatOpen[mode])
f = c_fdopen(filehandle, FormatOpen[mode])
result = f != nil
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")
proc getFilePos(f: File): int64 =
result = ftell(f)
result = c_ftell(f)
if result < 0: raiseEIO("cannot retrieve file position")
proc getFileSize(f: File): int64 =
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)
setFilePos(f, oldPos)
when not declared(close):
proc close(f: File) {.
importc: "fclose", header: "<stdio.h>", tags: [].}
proc readFile(filename: string): TaintedString =
var f: File
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 == nil or b == nil: return false
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):
template allocStr(size: expr): expr =
@@ -71,7 +71,7 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.compilerProc.} =
if len > 0:
result = rawNewStringNoInit(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'
else:
result = rawNewString(len)
@@ -82,10 +82,10 @@ proc copyStr(s: NimString, start: int): NimString {.compilerProc.} =
proc toNimStr(str: cstring, len: int): NimString {.compilerProc.} =
result = rawNewStringNoInit(len)
result.len = len
c_memcpy(result.data, str, len + 1)
copyMem(addr(result.data), str, len + 1)
proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} =
result = toNimStr(str, c_strlen(str))
result = toNimStr(str, str.len)
proc copyString(src: NimString): NimString {.compilerRtl.} =
if src != nil:
@@ -94,7 +94,7 @@ proc copyString(src: NimString): NimString {.compilerRtl.} =
else:
result = rawNewStringNoInit(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.} =
if src != nil:
@@ -107,7 +107,7 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
else:
result = rawNewStringNoInit(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.} =
@@ -177,7 +177,7 @@ proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
# DO NOT UPDATE LEN YET: dest.len = newLen
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)
proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} =
@@ -301,8 +301,8 @@ proc nimFloatToStr(f: float): string {.compilerproc.} =
else:
result = $buf
proc strtod(buf: cstring, endptr: ptr cstring): float64 {.importc,
header: "<stdlib.h>", noSideEffect.}
proc c_strtod(buf: cstring, endptr: ptr cstring): float64 {.
importc: "strtod", header: "<stdlib.h>", noSideEffect.}
const
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-3] = ('0'.ord + abs_exponent mod 10).char
number = strtod(t, nil)
number = c_strtod(t, nil)
proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
result = newString(sizeof(x)*4)

View File

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

View File

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

View File

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