diff options
-rw-r--r-- | lib/impure/dialogs.nim | 226 | ||||
-rw-r--r-- | lib/system.nim | 44 | ||||
-rw-r--r-- | lib/system/alloc.nim | 33 | ||||
-rw-r--r-- | lib/system/cgprocs.nim | 5 | ||||
-rw-r--r-- | lib/system/mmdisp.nim | 9 | ||||
-rw-r--r-- | tests/manyloc/standalone/barebone.nim.cfg | 1 | ||||
-rw-r--r-- | web/news.txt | 5 |
7 files changed, 62 insertions, 261 deletions
diff --git a/lib/impure/dialogs.nim b/lib/impure/dialogs.nim deleted file mode 100644 index 4ea66a6e6..000000000 --- a/lib/impure/dialogs.nim +++ /dev/null @@ -1,226 +0,0 @@ -# -# -# Nim's Runtime Library -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - - -## This module implements portable dialogs for Nim; the implementation -## builds on the GTK interface. On Windows, native dialogs are shown instead. - -import - glib2, gtk2 - -when defined(Windows): - import windows, ShellAPI, os - -proc info*(window: PWindow, msg: string) = - ## Shows an information message to the user. The process waits until the - ## user presses the OK button. - when defined(Windows): - discard MessageBoxA(0, msg, "Information", MB_OK or MB_ICONINFORMATION) - else: - var dialog = message_dialog_new(window, - DIALOG_MODAL or DIALOG_DESTROY_WITH_PARENT, - MESSAGE_INFO, BUTTONS_OK, "%s", cstring(msg)) - setTitle(dialog, "Information") - discard run(dialog) - destroy(PWidget(dialog)) - -proc warning*(window: PWindow, msg: string) = - ## Shows a warning message to the user. The process waits until the user - ## presses the OK button. - when defined(Windows): - discard MessageBoxA(0, msg, "Warning", MB_OK or MB_ICONWARNING) - else: - var dialog = DIALOG(message_dialog_new(window, - DIALOG_MODAL or DIALOG_DESTROY_WITH_PARENT, - MESSAGE_WARNING, BUTTONS_OK, "%s", cstring(msg))) - setTitle(dialog, "Warning") - discard run(dialog) - destroy(PWidget(dialog)) - -proc error*(window: PWindow, msg: string) = - ## Shows an error message to the user. The process waits until the user - ## presses the OK button. - when defined(Windows): - discard MessageBoxA(0, msg, "Error", MB_OK or MB_ICONERROR) - else: - var dialog = DIALOG(message_dialog_new(window, - DIALOG_MODAL or DIALOG_DESTROY_WITH_PARENT, - MESSAGE_ERROR, BUTTONS_OK, "%s", cstring(msg))) - setTitle(dialog, "Error") - discard run(dialog) - destroy(PWidget(dialog)) - - -proc chooseFileToOpen*(window: PWindow, root: string = ""): string = - ## Opens a dialog that requests a filename from the user. Returns "" - ## if the user closed the dialog without selecting a file. On Windows, - ## the native dialog is used, else the GTK dialog is used. - when defined(Windows): - var - opf: TOPENFILENAME - buf: array [0..2047, char] - opf.lStructSize = sizeof(opf).int32 - if root.len > 0: - opf.lpstrInitialDir = root - opf.lpstrFilter = "All Files\0*.*\0\0" - opf.flags = OFN_FILEMUSTEXIST - opf.lpstrFile = buf - opf.nMaxFile = sizeof(buf).int32 - var res = GetOpenFileName(addr(opf)) - if res != 0: - result = $buf - else: - result = "" - else: - var chooser = file_chooser_dialog_new("Open File", window, - FILE_CHOOSER_ACTION_OPEN, - STOCK_CANCEL, RESPONSE_CANCEL, - STOCK_OPEN, RESPONSE_OK, nil) - if root.len > 0: - discard set_current_folder(chooser, root) - if run(chooser) == cint(RESPONSE_OK): - var x = get_filename(chooser) - result = $x - g_free(x) - else: - result = "" - destroy(PWidget(chooser)) - -proc chooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] = - ## Opens a dialog that requests filenames from the user. Returns ``@[]`` - ## if the user closed the dialog without selecting a file. On Windows, - ## the native dialog is used, else the GTK dialog is used. - when defined(Windows): - var - opf: TOPENFILENAME - buf: array [0..2047*4, char] - opf.lStructSize = sizeof(opf).int32 - if root.len > 0: - opf.lpstrInitialDir = root - opf.lpstrFilter = "All Files\0*.*\0\0" - opf.flags = OFN_FILEMUSTEXIST or OFN_ALLOWMULTISELECT or OFN_EXPLORER - opf.lpstrFile = buf - opf.nMaxFile = sizeof(buf).int32 - var res = GetOpenFileName(addr(opf)) - result = @[] - if res != 0: - # parsing the result is horrible: - var - i = 0 - s: string - path = "" - while buf[i] != '\0': - add(path, buf[i]) - inc(i) - inc(i) - if buf[i] != '\0': - while true: - s = "" - while buf[i] != '\0': - add(s, buf[i]) - inc(i) - add(result, s) - inc(i) - if buf[i] == '\0': break - for i in 0..result.len-1: result[i] = os.joinPath(path, result[i]) - else: - # only one file selected --> gosh, what an ungly thing - # the windows API is - add(result, path) - else: - var chooser = file_chooser_dialog_new("Open Files", window, - FILE_CHOOSER_ACTION_OPEN, - STOCK_CANCEL, RESPONSE_CANCEL, - STOCK_OPEN, RESPONSE_OK, nil) - if root.len > 0: - discard set_current_folder(chooser, root) - set_select_multiple(chooser, true) - result = @[] - if run(chooser) == cint(RESPONSE_OK): - var L = get_filenames(chooser) - var it = L - while it != nil: - add(result, $cast[cstring](it.data)) - g_free(it.data) - it = it.next - free(L) - destroy(PWidget(chooser)) - - -proc chooseFileToSave*(window: PWindow, root: string = ""): string = - ## Opens a dialog that requests a filename to save to from the user. - ## Returns "" if the user closed the dialog without selecting a file. - ## On Windows, the native dialog is used, else the GTK dialog is used. - when defined(Windows): - var - opf: TOPENFILENAME - buf: array [0..2047, char] - opf.lStructSize = sizeof(opf).int32 - if root.len > 0: - opf.lpstrInitialDir = root - opf.lpstrFilter = "All Files\0*.*\0\0" - opf.flags = OFN_OVERWRITEPROMPT - opf.lpstrFile = buf - opf.nMaxFile = sizeof(buf).int32 - var res = GetSaveFileName(addr(opf)) - if res != 0: - result = $buf - else: - result = "" - else: - var chooser = file_chooser_dialog_new("Save File", window, - FILE_CHOOSER_ACTION_SAVE, - STOCK_CANCEL, RESPONSE_CANCEL, - STOCK_SAVE, RESPONSE_OK, nil) - if root.len > 0: - discard set_current_folder(chooser, root) - set_do_overwrite_confirmation(chooser, true) - if run(chooser) == cint(RESPONSE_OK): - var x = get_filename(chooser) - result = $x - g_free(x) - else: - result = "" - destroy(PWidget(chooser)) - - -proc chooseDir*(window: PWindow, root: string = ""): string = - ## Opens a dialog that requests a directory from the user. - ## Returns "" if the user closed the dialog without selecting a directory. - ## On Windows, the native dialog is used, else the GTK dialog is used. - when defined(Windows): - var - lpItemID: PItemIDList - BrowseInfo: TBrowseInfo - DisplayName: array [0..MAX_PATH, char] - TempPath: array [0..MAX_PATH, char] - result = "" - #BrowseInfo.hwndOwner = Application.Handle - BrowseInfo.pszDisplayName = DisplayName - BrowseInfo.ulFlags = 1 #BIF_RETURNONLYFSDIRS - lpItemID = SHBrowseForFolder(cast[LPBrowseInfo](addr(BrowseInfo))) - if lpItemId != nil: - discard SHGetPathFromIDList(lpItemID, TempPath) - result = $TempPath - discard GlobalFreePtr(lpItemID) - else: - var chooser = file_chooser_dialog_new("Select Directory", window, - FILE_CHOOSER_ACTION_SELECT_FOLDER, - STOCK_CANCEL, RESPONSE_CANCEL, - STOCK_OPEN, RESPONSE_OK, nil) - if root.len > 0: - discard set_current_folder(chooser, root) - if run(chooser) == cint(RESPONSE_OK): - var x = get_filename(chooser) - result = $x - g_free(x) - else: - result = "" - destroy(PWidget(chooser)) - diff --git a/lib/system.nim b/lib/system.nim index 3d92c6f05..e11722ae0 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1196,8 +1196,13 @@ template sysAssert(cond: bool, msg: string) = echo "[SYSASSERT] ", msg quit 1 +const hasAlloc = hostOS != "standalone" or not defined(nogc) + when not defined(JS) and not defined(nimrodVm) and hostOS != "standalone": include "system/cgprocs" +when not defined(JS) and not defined(nimrodVm) and hasAlloc: + proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline, benign.} + proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.} proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.} proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} = @@ -1404,7 +1409,7 @@ when not defined(nimrodVM): ## otherwise. Like any procedure dealing with raw memory this is ## *unsafe*. - when hostOS != "standalone": + when hasAlloc: proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign.} ## allocates a new memory block with at least ``size`` bytes. The ## block has to be freed with ``realloc(block, 0)`` or @@ -1540,7 +1545,7 @@ proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.} ## converted to a decimal string. when not defined(NimrodVM): - when not defined(JS) and hostOS != "standalone": + when not defined(JS) and hasAlloc: proc `$` *(x: uint64): string {.noSideEffect.} ## The stringify operator for an unsigned integer argument. Returns `x` ## converted to a decimal string. @@ -1607,7 +1612,7 @@ const # GC interface: -when not defined(nimrodVM) and hostOS != "standalone": +when not defined(nimrodVM) and hasAlloc: proc getOccupiedMem*(): int {.rtl.} ## returns the number of bytes that are owned by the process and hold data. @@ -2163,7 +2168,7 @@ when false: # ----------------- GC interface --------------------------------------------- -when not defined(nimrodVM) and hostOS != "standalone": +when not defined(nimrodVM) and hasAlloc: proc GC_disable*() {.rtl, inl, benign.} ## disables the GC. If called n-times, n calls to `GC_enable` are needed to ## reactivate the GC. Note that in most circumstances one should only disable @@ -2288,7 +2293,7 @@ when defined(JS): """ proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".} -elif hostOS != "standalone": +elif hasAlloc: {.push stack_trace:off, profiler:off.} proc add*(x: var string, y: cstring) = var i = 0 @@ -2382,7 +2387,7 @@ else: when not defined(JS): #and not defined(NimrodVM): {.push stack_trace: off, profiler:off.} - when not defined(NimrodVM) and hostOS != "standalone": + when not defined(NimrodVM) and not defined(nogc): proc initGC() when not defined(boehmgc) and not defined(useMalloc) and not defined(gogc): proc initAllocator() {.inline.} @@ -2402,6 +2407,7 @@ when not defined(JS): #and not defined(NimrodVM): when declared(setStackBottom): setStackBottom(locals) + when hasAlloc: var strDesc: TNimType @@ -2625,6 +2631,7 @@ when not defined(JS): #and not defined(NimrodVM): when not defined(nimfix): {.deprecated: [fileHandle: getFileHandle].} + when declared(newSeq): proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] = ## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be ## of length ``len``. @@ -2640,12 +2647,12 @@ when not defined(JS): #and not defined(NimrodVM): # ------------------------------------------------------------------------- - when not defined(NimrodVM) and hostOS != "standalone": + when declared(alloc0) and declared(dealloc): proc allocCStringArray*(a: openArray[string]): cstringArray = ## creates a NULL terminated cstringArray from `a`. The result has to ## be freed with `deallocCStringArray` after it's not needed anymore. result = cast[cstringArray](alloc0((a.len+1) * sizeof(cstring))) - let x = cast[ptr array[0..20_000, string]](a) + let x = cast[ptr array[0..ArrayDummySize, string]](a) for i in 0 .. a.high: result[i] = cast[cstring](alloc0(x[i].len+1)) copyMem(result[i], addr(x[i][0]), x[i].len) @@ -2685,9 +2692,9 @@ when not defined(JS): #and not defined(NimrodVM): when hasThreadSupport: include "system/syslocks" when hostOS != "standalone": include "system/threads" - elif not defined(nogc) and not defined(NimrodVM) and hostOS != "standalone": + elif not defined(nogc) and not defined(NimrodVM): when not defined(useNimRtl) and not defined(createNimRtl): initStackBottom() - initGC() + when declared(initGC): initGC() when not defined(NimrodVM): proc setControlCHook*(hook: proc () {.noconv.} not nil) @@ -2748,9 +2755,9 @@ when not defined(JS): #and not defined(NimrodVM): else: result = n.sons[n.len] - when hostOS != "standalone": include "system/mmdisp" + when hasAlloc: include "system/mmdisp" {.push stack_trace: off, profiler:off.} - when hostOS != "standalone": include "system/sysstr" + when hasAlloc: include "system/sysstr" {.pop.} when hostOS != "standalone": include "system/sysio" @@ -2759,7 +2766,7 @@ when not defined(JS): #and not defined(NimrodVM): else: include "system/sysio" - when hostOS != "standalone": + when declared(open) and declared(close) and declared(readline): iterator lines*(filename: string): TaintedString {.tags: [ReadIOEffect].} = ## Iterates over any line in the file named `filename`. ## @@ -2795,10 +2802,11 @@ when not defined(JS): #and not defined(NimrodVM): var res = TaintedString(newStringOfCap(80)) while f.readLine(res): yield res - when hostOS != "standalone" and not defined(NimrodVM): + when not defined(NimrodVM) and hasAlloc: include "system/assign" include "system/repr" + when hostOS != "standalone" and not defined(NimrodVM): proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} = ## retrieves the current exception; if there is none, nil is returned. result = currException @@ -2949,7 +2957,7 @@ template spliceImpl(s, a, L, b: expr): stmt {.immediate.} = # fill the hole: for i in 0 .. <b.len: s[i+a] = b[i] -when hostOS != "standalone": +when hasAlloc: proc `[]`*(s: string, x: Slice[int]): string {.inline.} = ## slice operation for strings. result = s.substr(x.a, x.b) @@ -3242,7 +3250,7 @@ when false: macro payload: stmt {.gensym.} = blk payload() -when hostOS != "standalone": +when hasAlloc: proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} = ## inserts `item` into `x` at position `i`. var xl = x.len @@ -3269,7 +3277,7 @@ proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} = when declared(initDebugger): initDebugger() -when hostOS != "standalone": +when hasAlloc: # XXX: make these the default (or implement the NilObject optimization) proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect.} = if x == nil: x = @[y] @@ -3307,7 +3315,7 @@ proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} = ## # -> B is 1 discard -when hostOS != "standalone" and not defined(NimrodVM) and not defined(JS): +when hasAlloc and not defined(NimrodVM) and not defined(JS): proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} = ## performs a deep copy of `x`. This is also used by the code generator ## for the implementation of ``spawn``. diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index d877cda2c..13a10e46f 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -13,6 +13,15 @@ # - make searching for block O(1) {.push profiler:off.} +proc roundup(x, v: int): int {.inline.} = + result = (x + (v-1)) and not (v-1) + sysAssert(result >= x, "roundup: result < x") + #return ((-x) and (v-1)) +% x + +sysAssert(roundup(14, PageSize) == PageSize, "invalid PageSize") +sysAssert(roundup(15, 8) == 16, "roundup broken") +sysAssert(roundup(65, 8) == 72, "roundup broken 2") + # ------------ platform specific chunk allocation code ----------------------- # some platforms have really weird unmap behaviour: unmap(blockStart, PageSize) @@ -82,6 +91,21 @@ elif defined(windows): when reallyOsDealloc: virtualFree(p, 0, MEM_RELEASE) #VirtualFree(p, size, MEM_DECOMMIT) +elif hostOS == "standalone": + var + theHeap: array[1024*PageSize, float64] # 'float64' for alignment + bumpPointer = cast[int](addr theHeap) + + proc osAllocPages(size: int): pointer {.inline.} = + if size+bumpPointer < cast[int](addr theHeap) + sizeof(theHeap): + result = cast[pointer](bumpPointer) + inc bumpPointer, size + else: + raiseOutOfMem() + + proc osDeallocPages(p: pointer, size: int) {.inline.} = + if bumpPointer-size == cast[int](p): + dec bumpPointer, size else: {.error: "Port memory manager to your platform".} @@ -142,15 +166,6 @@ type template smallChunkOverhead(): expr = sizeof(SmallChunk)-sizeof(AlignType) template bigChunkOverhead(): expr = sizeof(BigChunk)-sizeof(AlignType) -proc roundup(x, v: int): int {.inline.} = - result = (x + (v-1)) and not (v-1) - sysAssert(result >= x, "roundup: result < x") - #return ((-x) and (v-1)) +% x - -sysAssert(roundup(14, PageSize) == PageSize, "invalid PageSize") -sysAssert(roundup(15, 8) == 16, "roundup broken") -sysAssert(roundup(65, 8) == 72, "roundup broken 2") - # ------------- chunk table --------------------------------------------------- # We use a PtrSet of chunk starts and a table[Page, chunksize] for chunk # endings of big chunks. This is needed by the merging operation. The only diff --git a/lib/system/cgprocs.nim b/lib/system/cgprocs.nim index 6cd2ef08c..660c68116 100644 --- a/lib/system/cgprocs.nim +++ b/lib/system/cgprocs.nim @@ -9,8 +9,6 @@ # Headers for procs that the code generator depends on ("compilerprocs") -proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.} - type LibHandle = pointer # private type ProcAddr = pointer # library loading and loading of procs: @@ -21,6 +19,3 @@ proc nimUnloadLibrary(lib: LibHandle) {.compilerproc.} proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.compilerproc.} proc nimLoadLibraryError(path: string) {.compilerproc, noinline.} - -proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline, benign.} - diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index 50f4cb4dc..8a946716d 100644 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -34,7 +34,7 @@ const type PPointer = ptr pointer - ByteArray = array[0..1000_0000, byte] + ByteArray = array[0..ArrayDummySize, byte] PByte = ptr ByteArray PString = ptr string {.deprecated: [TByteArray: ByteArray].} @@ -42,7 +42,7 @@ type # Page size of the system; in most cases 4096 bytes. For exotic OS or # CPU this needs to be changed: const - PageShift = 12 + PageShift = when defined(cpu16): 8 else: 12 PageSize = 1 shl PageShift PageMask = PageSize-1 @@ -270,7 +270,10 @@ elif defined(gogc): # Statistics about allocation size classes. by_size: array[goNumSizeClasses, goMStats_inner_struct] - proc goRuntime_ReadMemStats(a2: ptr goMStats) {.cdecl, importc: "runtime_ReadMemStats", codegenDecl: "$1 $2$3 __asm__ (\"runtime.ReadMemStats\");\n$1 $2$3", dynlib: goLib.} + proc goRuntime_ReadMemStats(a2: ptr goMStats) {.cdecl, + importc: "runtime_ReadMemStats", + codegenDecl: "$1 $2$3 __asm__ (\"runtime.ReadMemStats\");\n$1 $2$3", + dynlib: goLib.} proc GC_getStatistics(): string = var mstats: goMStats diff --git a/tests/manyloc/standalone/barebone.nim.cfg b/tests/manyloc/standalone/barebone.nim.cfg index 52ec64e3f..bb350ff55 100644 --- a/tests/manyloc/standalone/barebone.nim.cfg +++ b/tests/manyloc/standalone/barebone.nim.cfg @@ -1,2 +1,3 @@ --os:standalone --deadCodeElim:on +--gc:none diff --git a/web/news.txt b/web/news.txt index be27d83e5..2d5b75207 100644 --- a/web/news.txt +++ b/web/news.txt @@ -23,6 +23,11 @@ News used: ``import "scene/2d/sprite"``. The former code never was valid Nim. - The Windows API wrapper (``windows.nim``) is now not part of the official distribution anymore. Instead use the ``oldwinapi`` Nimble package. + - There is now a clear distinction between ``--os:standalone`` + and ``--gc:none``. So if you use ``--os:standalone`` ensure you also use + ``--gc:none``. ``--os:standalone`` without ``--gc:none`` is now a version + that doesn't depend on any OS but includes the GC. However this version + is currently untested! Library additions |