--os:standalone works again

This commit is contained in:
Araq
2013-06-30 21:15:28 +02:00
parent 651103ff32
commit 52851b722d
16 changed files with 552 additions and 621 deletions

View File

@@ -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}

View File

@@ -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)

View File

@@ -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")

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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)