summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/impure/dialogs.nim226
-rw-r--r--lib/system.nim44
-rw-r--r--lib/system/alloc.nim33
-rw-r--r--lib/system/cgprocs.nim5
-rw-r--r--lib/system/mmdisp.nim9
-rw-r--r--tests/manyloc/standalone/barebone.nim.cfg1
-rw-r--r--web/news.txt5
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