mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-21 23:05:27 +00:00
--os:standalone works again
This commit is contained in:
@@ -13,25 +13,30 @@
|
||||
|
||||
{.push hints:off}
|
||||
|
||||
proc c_strcmp(a, b: CString): cint {.nodecl, noSideEffect, importc: "strcmp".}
|
||||
proc c_memcmp(a, b: CString, size: int): cint {.
|
||||
nodecl, noSideEffect, importc: "memcmp".}
|
||||
proc c_memcpy(a, b: CString, size: int) {.nodecl, importc: "memcpy".}
|
||||
proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".}
|
||||
proc c_memset(p: pointer, value: cint, size: int) {.nodecl, importc: "memset".}
|
||||
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".}
|
||||
|
||||
type
|
||||
C_TextFile {.importc: "FILE", nodecl, final, incompleteStruct.} = object
|
||||
C_BinaryFile {.importc: "FILE", nodecl, final, incompleteStruct.} = object
|
||||
C_TextFile {.importc: "FILE", header: "<stdio.h>",
|
||||
final, incompleteStruct.} = object
|
||||
C_BinaryFile {.importc: "FILE", header: "<stdio.h>",
|
||||
final, incompleteStruct.} = object
|
||||
C_TextFileStar = ptr CTextFile
|
||||
C_BinaryFileStar = ptr CBinaryFile
|
||||
|
||||
C_JmpBuf {.importc: "jmp_buf".} = array[0..31, int]
|
||||
C_JmpBuf {.importc: "jmp_buf", header: "<setjmp.h>".} = array[0..31, int]
|
||||
|
||||
var
|
||||
c_stdin {.importc: "stdin", noDecl.}: C_TextFileStar
|
||||
c_stdout {.importc: "stdout", noDecl.}: C_TextFileStar
|
||||
c_stderr {.importc: "stderr", noDecl.}: C_TextFileStar
|
||||
c_stdin {.importc: "stdin", header: "<stdio.h>".}: C_TextFileStar
|
||||
c_stdout {.importc: "stdout", header: "<stdio.h>".}: C_TextFileStar
|
||||
c_stderr {.importc: "stderr", header: "<stdio.h>".}: C_TextFileStar
|
||||
|
||||
# constants faked as variables:
|
||||
when not defined(SIGINT):
|
||||
@@ -51,59 +56,70 @@ else:
|
||||
SIGBUS {.importc: "SIGSEGV", nodecl.}: cint
|
||||
# only Mac OS X has this shit
|
||||
|
||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.nodecl, importc: "longjmp".}
|
||||
proc c_setjmp(jmpb: var C_JmpBuf): cint {.nodecl, importc: "setjmp".}
|
||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "longjmp".}
|
||||
proc c_setjmp(jmpb: var C_JmpBuf): cint {.
|
||||
header: "<setjmp.h>", importc: "setjmp".}
|
||||
|
||||
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
|
||||
importc: "signal", header: "<signal.h>".}
|
||||
proc c_raise(sig: cint) {.importc: "raise", header: "<signal.h>".}
|
||||
|
||||
proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs", noDecl.}
|
||||
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", noDecl.}
|
||||
proc c_fgetc(stream: C_TextFileStar): int {.importc: "fgetc", nodecl.}
|
||||
proc c_ungetc(c: int, f: C_TextFileStar) {.importc: "ungetc", nodecl.}
|
||||
proc c_putc(c: Char, stream: C_TextFileStar) {.importc: "putc", nodecl.}
|
||||
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", nodecl, varargs.}
|
||||
importc: "fprintf", header: "<stdio.h>", varargs.}
|
||||
proc c_printf(frmt: CString) {.
|
||||
importc: "printf", nodecl, varargs.}
|
||||
importc: "printf", header: "<stdio.h>", varargs.}
|
||||
|
||||
proc c_fopen(filename, mode: cstring): C_TextFileStar {.
|
||||
importc: "fopen", nodecl.}
|
||||
proc c_fclose(f: C_TextFileStar) {.importc: "fclose", nodecl.}
|
||||
importc: "fopen", header: "<stdio.h>".}
|
||||
proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "<stdio.h>".}
|
||||
|
||||
proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs,
|
||||
noSideEffect.}
|
||||
proc c_sprintf(buf, frmt: CString) {.header: "<stdio.h>",
|
||||
importc: "sprintf", 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", noDecl.}
|
||||
importc: "fread", header: "<stdio.h>".}
|
||||
proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {.
|
||||
importc: "fseek", noDecl.}
|
||||
importc: "fseek", header: "<stdio.h>".}
|
||||
|
||||
proc c_fwrite(buf: Pointer, size, n: int, f: C_BinaryFileStar): int {.
|
||||
importc: "fwrite", noDecl.}
|
||||
importc: "fwrite", header: "<stdio.h>".}
|
||||
|
||||
proc c_exit(errorcode: cint) {.importc: "exit", nodecl.}
|
||||
proc c_ferror(stream: C_TextFileStar): bool {.importc: "ferror", nodecl.}
|
||||
proc c_fflush(stream: C_TextFileStar) {.importc: "fflush", nodecl.}
|
||||
proc c_abort() {.importc: "abort", nodecl.}
|
||||
proc c_feof(stream: C_TextFileStar): bool {.importc: "feof", nodecl.}
|
||||
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", nodecl.}
|
||||
proc c_free(p: pointer) {.importc: "free", nodecl.}
|
||||
proc c_realloc(p: pointer, newsize: int): pointer {.importc: "realloc", nodecl.}
|
||||
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>".}
|
||||
|
||||
when not defined(errno):
|
||||
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", noDecl.}
|
||||
proc c_rename(oldname, newname: CString): cint {.importc: "rename", noDecl.}
|
||||
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", noDecl.}
|
||||
proc c_putenv(env: CString): cint {.importc: "putenv", noDecl.}
|
||||
proc c_getenv(env: CString): CString {.importc: "getenv", header: "<stdlib.h>".}
|
||||
proc c_putenv(env: CString): cint {.importc: "putenv", header: "<stdlib.h>".}
|
||||
|
||||
{.pop}
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
proc raiseOverflow {.compilerproc, noinline, noreturn.} =
|
||||
# a single proc to reduce code size to a minimum
|
||||
raise newException(EOverflow, "over- or underflow")
|
||||
sysFatal(EOverflow, "over- or underflow")
|
||||
|
||||
proc raiseDivByZero {.compilerproc, noinline, noreturn.} =
|
||||
raise newException(EDivByZero, "divison by zero")
|
||||
sysFatal(EDivByZero, "divison by zero")
|
||||
|
||||
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||
result = a +% b
|
||||
@@ -322,16 +322,16 @@ when not defined(mulInt):
|
||||
# written in other languages.
|
||||
|
||||
proc raiseFloatInvalidOp {.noinline, noreturn.} =
|
||||
raise newException(EFloatInvalidOp, "FPU operation caused a NaN result")
|
||||
sysFatal(EFloatInvalidOp, "FPU operation caused a NaN result")
|
||||
|
||||
proc nanCheck(x: float64) {.compilerProc, inline.} =
|
||||
if x != x: raiseFloatInvalidOp()
|
||||
|
||||
proc raiseFloatOverflow(x: float64) {.noinline, noreturn.} =
|
||||
if x > 0.0:
|
||||
raise newException(EFloatOverflow, "FPU operation caused an overflow")
|
||||
sysFatal(EFloatOverflow, "FPU operation caused an overflow")
|
||||
else:
|
||||
raise newException(EFloatUnderflow, "FPU operations caused an underflow")
|
||||
sysFatal(EFloatUnderflow, "FPU operations caused an underflow")
|
||||
|
||||
proc infCheck(x: float64) {.compilerProc, inline.} =
|
||||
if x != 0.0 and x*0.5 == x: raiseFloatOverflow(x)
|
||||
|
||||
@@ -223,6 +223,4 @@ proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int,
|
||||
var oldBranch = selectBranch(oldDiscVal, L, a)
|
||||
var newBranch = selectBranch(newDiscVal, L, a)
|
||||
if newBranch != oldBranch and oldDiscVal != 0:
|
||||
raise newException(EInvalidField,
|
||||
"assignment to discriminant changes object branch")
|
||||
|
||||
sysFatal(EInvalidField, "assignment to discriminant changes object branch")
|
||||
|
||||
@@ -187,7 +187,7 @@ template lockChannel(q: expr, action: stmt) {.immediate.} =
|
||||
|
||||
template sendImpl(q: expr) {.immediate.} =
|
||||
if q.mask == ChannelDeadMask:
|
||||
raise newException(EDeadThread, "cannot send message; thread died")
|
||||
sysFatal(EDeadThread, "cannot send message; thread died")
|
||||
acquireSys(q.lock)
|
||||
var m: TMsg
|
||||
shallowCopy(m, msg)
|
||||
@@ -211,7 +211,7 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
|
||||
q.ready = false
|
||||
if typ != q.elemType:
|
||||
releaseSys(q.lock)
|
||||
raise newException(EInvalidValue, "cannot receive message of wrong type")
|
||||
sysFatal(EInvalidValue, "cannot receive message of wrong type")
|
||||
rawRecv(q, res, typ)
|
||||
releaseSys(q.lock)
|
||||
|
||||
|
||||
77
lib/system/chcks.nim
Normal file
77
lib/system/chcks.nim
Normal file
@@ -0,0 +1,77 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# Implementation of some runtime checks.
|
||||
|
||||
proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn, noinline.} =
|
||||
when hostOs == "standalone":
|
||||
sysFatal(EOutOfRange, "value out of range")
|
||||
else:
|
||||
sysFatal(EOutOfRange, "value out of range: ", $val)
|
||||
|
||||
proc raiseIndexError() {.compilerproc, noreturn, noinline.} =
|
||||
sysFatal(EInvalidIndex, "index out of bounds")
|
||||
|
||||
proc raiseFieldError(f: string) {.compilerproc, noreturn, noinline.} =
|
||||
sysFatal(EInvalidField, f, " is not accessible")
|
||||
|
||||
proc chckIndx(i, a, b: int): int =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseIndexError()
|
||||
|
||||
proc chckRange(i, a, b: int): int =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError(i)
|
||||
|
||||
proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError(i)
|
||||
|
||||
proc chckRangeF(x, a, b: float): float =
|
||||
if x >= a and x <= b:
|
||||
return x
|
||||
else:
|
||||
when hostOS == "standalone":
|
||||
sysFatal(EOutOfRange, "value out of range")
|
||||
else:
|
||||
sysFatal(EOutOfRange, "value out of range: ", $x)
|
||||
|
||||
proc chckNil(p: pointer) =
|
||||
if p == nil:
|
||||
sysFatal(EInvalidValue, "attempt to write to a nil address")
|
||||
#c_raise(SIGSEGV)
|
||||
|
||||
proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
|
||||
# checks if obj is of type subclass:
|
||||
var x = obj
|
||||
if x == subclass: return # optimized fast path
|
||||
while x != subclass:
|
||||
if x == nil:
|
||||
sysFatal(EInvalidObjectConversion, "invalid object conversion")
|
||||
break
|
||||
x = x.base
|
||||
|
||||
proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
|
||||
if a != b:
|
||||
sysFatal(EInvalidObjectAssignment, "invalid object assignment")
|
||||
|
||||
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
|
||||
# checks if obj is of type subclass:
|
||||
var x = obj
|
||||
if x == subclass: return true # optimized fast path
|
||||
while x != subclass:
|
||||
if x == nil: return false
|
||||
x = x.base
|
||||
return true
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
# Bare-bones implementation of some things for embedded targets.
|
||||
|
||||
proc writeToStdErr(msg: CString) = write(stdout, msg)
|
||||
|
||||
proc chckIndx(i, a, b: int): int {.inline, compilerproc.}
|
||||
proc chckRange(i, a, b: int): int {.inline, compilerproc.}
|
||||
proc chckRangeF(x, a, b: float): float {.inline, compilerproc.}
|
||||
@@ -35,72 +33,11 @@ proc quitOrDebug() {.inline.} =
|
||||
quit(1)
|
||||
|
||||
proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
||||
writeToStdErr(ename)
|
||||
|
||||
sysFatal(ENoExceptionToReraise, "exception handling is not available")
|
||||
|
||||
proc reraiseException() {.compilerRtl.} =
|
||||
writeToStdErr("reraise not supported")
|
||||
sysFatal(ENoExceptionToReraise, "no exception to reraise")
|
||||
|
||||
proc WriteStackTrace() = nil
|
||||
|
||||
proc setControlCHook(hook: proc () {.noconv.}) =
|
||||
# ugly cast, but should work on all architectures:
|
||||
type TSignalHandler = proc (sig: cint) {.noconv.}
|
||||
c_signal(SIGINT, cast[TSignalHandler](hook))
|
||||
|
||||
proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn, noinline.} =
|
||||
writeToStdErr("value out of range")
|
||||
|
||||
proc raiseIndexError() {.compilerproc, noreturn, noinline.} =
|
||||
writeToStdErr("index out of bounds")
|
||||
|
||||
proc raiseFieldError(f: string) {.compilerproc, noreturn, noinline.} =
|
||||
writeToStdErr("field is not accessible")
|
||||
|
||||
proc chckIndx(i, a, b: int): int =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseIndexError()
|
||||
|
||||
proc chckRange(i, a, b: int): int =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError(i)
|
||||
|
||||
proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError(i)
|
||||
|
||||
proc chckRangeF(x, a, b: float): float =
|
||||
if x >= a and x <= b:
|
||||
return x
|
||||
else:
|
||||
raise newException(EOutOfRange, "value " & $x & " out of range")
|
||||
|
||||
proc chckNil(p: pointer) =
|
||||
if p == nil: c_raise(SIGSEGV)
|
||||
|
||||
proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
|
||||
# checks if obj is of type subclass:
|
||||
var x = obj
|
||||
if x == subclass: return # optimized fast path
|
||||
while x != subclass:
|
||||
if x == nil:
|
||||
raise newException(EInvalidObjectConversion, "invalid object conversion")
|
||||
x = x.base
|
||||
|
||||
proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
|
||||
if a != b:
|
||||
raise newException(EInvalidObjectAssignment, "invalid object assignment")
|
||||
|
||||
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
|
||||
# checks if obj is of type subclass:
|
||||
var x = obj
|
||||
if x == subclass: return true # optimized fast path
|
||||
while x != subclass:
|
||||
if x == nil: return false
|
||||
x = x.base
|
||||
return true
|
||||
proc setControlCHook(hook: proc () {.noconv.}) = nil
|
||||
|
||||
@@ -249,7 +249,7 @@ proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
||||
|
||||
proc reraiseException() {.compilerRtl.} =
|
||||
if currException == nil:
|
||||
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
||||
sysFatal(ENoExceptionToReraise, "no exception to reraise")
|
||||
else:
|
||||
raiseExceptionAux(currException)
|
||||
|
||||
@@ -324,63 +324,3 @@ proc setControlCHook(hook: proc () {.noconv.}) =
|
||||
# ugly cast, but should work on all architectures:
|
||||
type TSignalHandler = proc (sig: cint) {.noconv.}
|
||||
c_signal(SIGINT, cast[TSignalHandler](hook))
|
||||
|
||||
proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn, noinline.} =
|
||||
raise newException(EOutOfRange, "value " & $val & " out of range")
|
||||
|
||||
proc raiseIndexError() {.compilerproc, noreturn, noinline.} =
|
||||
raise newException(EInvalidIndex, "index out of bounds")
|
||||
|
||||
proc raiseFieldError(f: string) {.compilerproc, noreturn, noinline.} =
|
||||
raise newException(EInvalidField, f & " is not accessible")
|
||||
|
||||
proc chckIndx(i, a, b: int): int =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseIndexError()
|
||||
|
||||
proc chckRange(i, a, b: int): int =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError(i)
|
||||
|
||||
proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError(i)
|
||||
|
||||
proc chckRangeF(x, a, b: float): float =
|
||||
if x >= a and x <= b:
|
||||
return x
|
||||
else:
|
||||
raise newException(EOutOfRange, "value " & $x & " out of range")
|
||||
|
||||
proc chckNil(p: pointer) =
|
||||
if p == nil:
|
||||
raise newException(EInvalidValue, "attempt to write to a nil address")
|
||||
#c_raise(SIGSEGV)
|
||||
|
||||
proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
|
||||
# checks if obj is of type subclass:
|
||||
var x = obj
|
||||
if x == subclass: return # optimized fast path
|
||||
while x != subclass:
|
||||
if x == nil:
|
||||
raise newException(EInvalidObjectConversion, "invalid object conversion")
|
||||
x = x.base
|
||||
|
||||
proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
|
||||
if a != b:
|
||||
raise newException(EInvalidObjectAssignment, "invalid object assignment")
|
||||
|
||||
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
|
||||
# checks if obj is of type subclass:
|
||||
var x = obj
|
||||
if x == subclass: return true # optimized fast path
|
||||
while x != subclass:
|
||||
if x == nil: return false
|
||||
x = x.base
|
||||
return true
|
||||
|
||||
@@ -16,39 +16,44 @@
|
||||
# of the standard library!
|
||||
|
||||
|
||||
proc fputs(c: cstring, f: TFile) {.importc: "fputs", noDecl, tags: [FWriteIO].}
|
||||
proc fgets(c: cstring, n: int, f: TFile): cstring {.importc: "fgets", noDecl,
|
||||
tags: [FReadIO].}
|
||||
proc fgetc(stream: TFile): cint {.importc: "fgetc", nodecl, tags: [FReadIO].}
|
||||
proc ungetc(c: cint, f: TFile) {.importc: "ungetc", nodecl, tags: [].}
|
||||
proc putc(c: Char, stream: TFile) {.importc: "putc", nodecl, tags: [FWriteIO].}
|
||||
proc fprintf(f: TFile, frmt: CString) {.importc: "fprintf", nodecl, varargs,
|
||||
tags: [FWriteIO].}
|
||||
proc strlen(c: cstring): int {.importc: "strlen", nodecl, tags: [].}
|
||||
proc fputs(c: cstring, f: TFile) {.importc: "fputs", header: "<stdio.h>",
|
||||
tags: [FWriteIO].}
|
||||
proc fgets(c: cstring, n: int, f: TFile): cstring {.
|
||||
importc: "fgets", header: "<stdio.h>", tags: [FReadIO].}
|
||||
proc fgetc(stream: TFile): cint {.importc: "fgetc", header: "<stdio.h>",
|
||||
tags: [FReadIO].}
|
||||
proc ungetc(c: cint, f: TFile) {.importc: "ungetc", header: "<stdio.h>",
|
||||
tags: [].}
|
||||
proc putc(c: Char, stream: TFile) {.importc: "putc", header: "<stdio.h>",
|
||||
tags: [FWriteIO].}
|
||||
proc fprintf(f: TFile, frmt: CString) {.importc: "fprintf",
|
||||
header: "<stdio.h>", varargs, tags: [FWriteIO].}
|
||||
proc strlen(c: cstring): int {.
|
||||
importc: "strlen", header: "<string.h>", tags: [].}
|
||||
|
||||
|
||||
# C routine that is used here:
|
||||
proc fread(buf: Pointer, size, n: int, f: TFile): int {.
|
||||
importc: "fread", noDecl, tags: [FReadIO].}
|
||||
importc: "fread", header: "<stdio.h>", tags: [FReadIO].}
|
||||
proc fseek(f: TFile, offset: clong, whence: int): int {.
|
||||
importc: "fseek", noDecl, tags: [].}
|
||||
proc ftell(f: TFile): int {.importc: "ftell", noDecl, tags: [].}
|
||||
importc: "fseek", header: "<stdio.h>", tags: [].}
|
||||
proc ftell(f: TFile): int {.importc: "ftell", header: "<stdio.h>", tags: [].}
|
||||
proc setvbuf(stream: TFile, buf: pointer, typ, size: cint): cint {.
|
||||
importc, nodecl, tags: [].}
|
||||
importc, header: "<stdio.h>", tags: [].}
|
||||
|
||||
{.push stackTrace:off, profiler:off.}
|
||||
proc write(f: TFile, c: cstring) = fputs(c, f)
|
||||
{.pop.}
|
||||
|
||||
var
|
||||
IOFBF {.importc: "_IOFBF", nodecl.}: cint
|
||||
IONBF {.importc: "_IONBF", nodecl.}: cint
|
||||
IOFBF {.importc: "_IOFBF", header: "<stdio.h>".}: cint
|
||||
IONBF {.importc: "_IONBF", header: "<stdio.h>".}: cint
|
||||
|
||||
const
|
||||
buf_size = 4000
|
||||
|
||||
proc raiseEIO(msg: string) {.noinline, noreturn.} =
|
||||
raise newException(EIO, msg)
|
||||
sysFatal(EIO, msg)
|
||||
|
||||
proc readLine(f: TFile, line: var TaintedString): bool =
|
||||
# of course this could be optimized a bit; but IO is slow anyway...
|
||||
@@ -197,7 +202,7 @@ proc Open(f: var TFile, filename: string,
|
||||
f = cast[TFile](p)
|
||||
if bufSize > 0 and bufSize <= high(cint).int:
|
||||
if setvbuf(f, nil, IOFBF, bufSize.cint) != 0'i32:
|
||||
raise newException(EOutOfMemory, "out of memory")
|
||||
sysFatal(EOutOfMemory, "out of memory")
|
||||
elif bufSize == 0:
|
||||
discard setvbuf(f, nil, IONBF, 0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user