diff options
author | A. S. Budden <abudden@gmail.com> | 2016-06-13 16:44:14 +0100 |
---|---|---|
committer | A. S. Budden <abudden@gmail.com> | 2016-06-13 16:44:14 +0100 |
commit | 1095b35a79abfd8c59db8dc92e8aab5951bc4093 (patch) | |
tree | 81eec1c4b2720412edae261de1ceade628877b04 | |
parent | 5327cd0a84df0ad6c29bf534003ba7c97e9bcb73 (diff) | |
parent | 58bb12d5ce431fce70a22fa69b80bf021e2d1ce6 (diff) | |
download | Nim-1095b35a79abfd8c59db8dc92e8aab5951bc4093.tar.gz |
Merged upstream/devel into this branch to resolve conflicts and ensure an easy merge back into upstream/devel
-rw-r--r-- | compiler/installer.ini | 2 | ||||
-rw-r--r-- | lib/impure/re.nim | 11 | ||||
-rw-r--r-- | lib/nimbase.h | 3 | ||||
-rw-r--r-- | lib/pure/memfiles.nim | 6 | ||||
-rw-r--r-- | lib/pure/os.nim | 22 | ||||
-rw-r--r-- | lib/pure/parsecsv.nim | 73 | ||||
-rw-r--r-- | lib/pure/streams.nim | 118 | ||||
-rw-r--r-- | lib/pure/xmldom.nim | 15 | ||||
-rw-r--r-- | lib/system.nim | 71 | ||||
-rw-r--r-- | lib/system/alloc.nim | 4 | ||||
-rw-r--r-- | lib/system/ansi_c.nim | 162 | ||||
-rw-r--r-- | lib/system/chcks.nim | 1 | ||||
-rw-r--r-- | lib/system/debugger.nim | 4 | ||||
-rw-r--r-- | lib/system/deepcopy.nim | 2 | ||||
-rw-r--r-- | lib/system/dyncalls.nim | 9 | ||||
-rw-r--r-- | lib/system/endb.nim | 6 | ||||
-rw-r--r-- | lib/system/excpt.nim | 2 | ||||
-rw-r--r-- | lib/system/gc.nim | 4 | ||||
-rw-r--r-- | lib/system/gc_stack.nim | 14 | ||||
-rw-r--r-- | lib/system/mmdisp.nim | 24 | ||||
-rw-r--r-- | lib/system/osalloc.nim | 4 | ||||
-rw-r--r-- | lib/system/sysio.nim | 153 | ||||
-rw-r--r-- | lib/system/sysstr.nim | 20 | ||||
-rw-r--r-- | lib/system/threads.nim | 9 | ||||
-rw-r--r-- | lib/system/timers.nim | 9 | ||||
-rw-r--r-- | lib/system/widestrs.nim | 7 | ||||
-rw-r--r-- | tools/niminst/niminst.nim | 38 | ||||
-rw-r--r-- | web/news/version_0_15_released.rst | 2 |
28 files changed, 436 insertions, 359 deletions
diff --git a/compiler/installer.ini b/compiler/installer.ini index 96254252f..f9b112d66 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -48,7 +48,6 @@ Start: "doc/overview.html" [Other] Files: "readme.txt;install.txt;contributors.txt;copying.txt" Files: "makefile" -Files: "*.ini" Files: "koch.nim" Files: "icons/nim.ico" @@ -66,7 +65,6 @@ Files: "tools" Files: "web/website.ini" Files: "web/ticker.html" Files: "web/*.nim" -Files: "web/*.txt" Files: "web/*.rst" Files: "web/*.csv" Files: "web/news/*.rst" diff --git a/lib/impure/re.nim b/lib/impure/re.nim index d49c6d1c1..bf397550a 100644 --- a/lib/impure/re.nim +++ b/lib/impure/re.nim @@ -7,8 +7,11 @@ # distribution, for details about the copyright. # -## Regular expression support for Nim. Deprecated. Consider using the ``nre`` -## or ``pegs`` modules instead. +## Regular expression support for Nim. This module still has some +## obscure bugs and limitations, +## consider using the ``nre`` or ``pegs`` modules instead. +## We had to de-deprecate this module since too much code relies on it +## and many people prefer its API over ``nre``'s. ## ## **Note:** The 're' proc defaults to the **extended regular expression ## syntax** which lets you use whitespace freely to make your regexes readable. @@ -28,8 +31,6 @@ import pcre, strutils, rtarrays -{.deprecated.} - const MaxSubpatterns* = 20 ## defines the maximum number of subpatterns that can be captured. @@ -78,7 +79,7 @@ proc finalizeRegEx(x: Regex) = if not isNil(x.e): pcre.free_substring(cast[cstring](x.e)) -proc re*(s: string, flags = {reExtended, reStudy}): Regex {.deprecated.} = +proc re*(s: string, flags = {reExtended, reStudy}): Regex = ## Constructor of regular expressions. Note that Nim's ## extended raw string literals support this syntax ``re"[abc]"`` as ## a short form for ``re(r"[abc]")``. diff --git a/lib/nimbase.h b/lib/nimbase.h index f531f3c49..d5a551352 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -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; \ diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index b9c574944..ff3e74d59 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -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 diff --git a/lib/pure/os.nim b/lib/pure/os.nim index dee227c69..2b1cf7409 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -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 diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim index bb291bcbc..77b145a73 100644 --- a/lib/pure/parsecsv.nim +++ b/lib/pure/parsecsv.nim @@ -25,6 +25,28 @@ ## echo "##", val, "##" ## close(x) ## +## For CSV files with a header row, the header can be read and then used as a +## reference for item access with `rowEntry <#rowEntry.CsvParser.string>`_: +## +## .. code-block:: nim +## import parsecsv +## import os +## # Prepare a file +## var csv_content = """One,Two,Three,Four +## 1,2,3,4 +## 10,20,30,40 +## 100,200,300,400 +## """ +## writeFile("temp.csv", content) +## +## var p: CsvParser +## p.open("temp.csv") +## p.readHeaderRow() +## while p.readRow(): +## echo "new row: " +## for col in items(p.headers): +## echo "##", col, ":", p.rowEntry(col), "##" +## p.close() import lexbase, streams @@ -37,6 +59,9 @@ type sep, quote, esc: char skipWhite: bool currRow: int + headers*: seq[string] ## The columns that are defined in the csv file + ## (read using `readHeaderRow <#readHeaderRow.CsvParser>`_). + ## Used with `rowEntry <#rowEntry.CsvParser.string>`_). CsvError* = object of IOError ## exception that is raised if ## a parsing error occurs @@ -177,6 +202,22 @@ proc close*(my: var CsvParser) {.inline.} = ## closes the parser `my` and its associated input stream. lexbase.close(my) +proc readHeaderRow*(my: var CsvParser) = + ## Reads the first row and creates a look-up table for column numbers + ## See also `rowEntry <#rowEntry.CsvParser.string>`_. + var present = my.readRow() + if present: + my.headers = my.row + +proc rowEntry*(my: var CsvParser, entry: string): string = + ## Reads a specified `entry` from the current row. + ## + ## Assumes that `readHeaderRow <#readHeaderRow.CsvParser>`_ has already been + ## called. + var index = my.headers.find(entry) + if index >= 0: + result = my.row[index] + when not defined(testing) and isMainModule: import os var s = newFileStream(paramStr(1), fmRead) @@ -189,3 +230,35 @@ when not defined(testing) and isMainModule: echo "##", val, "##" close(x) +when isMainModule: + import os + import strutils + block: # Tests for reading the header row + var content = "One,Two,Three,Four\n1,2,3,4\n10,20,30,40,\n100,200,300,400\n" + writeFile("temp.csv", content) + + var p: CsvParser + p.open("temp.csv") + p.readHeaderRow() + while p.readRow(): + var zeros = repeat('0', p.currRow-2) + doAssert p.rowEntry("One") == "1" & zeros + doAssert p.rowEntry("Two") == "2" & zeros + doAssert p.rowEntry("Three") == "3" & zeros + doAssert p.rowEntry("Four") == "4" & zeros + p.close() + + when not defined(testing): + var parser: CsvParser + parser.open("temp.csv") + parser.readHeaderRow() + while parser.readRow(): + echo "new row: " + for col in items(parser.headers): + echo "##", col, ":", parser.rowEntry(col), "##" + parser.close() + removeFile("temp.csv") + + # Tidy up + removeFile("temp.csv") + diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index c606b4680..eea06f4ce 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -306,68 +306,68 @@ 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 f: File diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim index 6cf837f25..559f45348 100644 --- a/lib/pure/xmldom.nim +++ b/lib/pure/xmldom.nim @@ -51,6 +51,9 @@ const # Illegal characters illegalChars = {'>', '<', '&', '"'} + # standard xml: attribute names + # see https://www.w3.org/XML/1998/namespace + stdattrnames = ["lang", "space", "base", "id"] type Feature = tuple[name: string, version: string] @@ -229,12 +232,15 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str raise newException(EInvalidCharacterErr, "Invalid character") # Exceptions if qualifiedName.contains(':'): + let qfnamespaces = qualifiedName.toLower().split(':') if isNil(namespaceURI): raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil") - elif qualifiedName.split(':')[0].toLower() == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace": + elif qfnamespaces[0] == "xml" and + namespaceURI != "http://www.w3.org/XML/1998/namespace" and + qfnamespaces[1] notin stdattrnames: raise newException(ENamespaceErr, "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"") - elif qualifiedName.split(':')[1].toLower() == "xmlns" and namespaceURI != "http://www.w3.org/2000/xmlns/": + elif qfnamespaces[1] == "xmlns" and namespaceURI != "http://www.w3.org/2000/xmlns/": raise newException(ENamespaceErr, "When the namespace prefix is \"xmlns\" namespaceURI has to be \"http://www.w3.org/2000/xmlns/\"") @@ -305,9 +311,12 @@ proc createElement*(doc: PDocument, tagName: string): PElement = proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PElement = ## Creates an element of the given qualified name and namespace URI. if qualifiedName.contains(':'): + let qfnamespaces = qualifiedName.toLower().split(':') if isNil(namespaceURI): raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil") - elif qualifiedName.split(':')[0].toLower() == "xml" and namespaceURI != "http://www.w3.org/XML/1998/namespace": + elif qfnamespaces[0] == "xml" and + namespaceURI != "http://www.w3.org/XML/1998/namespace" and + qfnamespaces[1] notin stdattrnames: raise newException(ENamespaceErr, "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"") diff --git a/lib/system.nim b/lib/system.nim index 504d215ea..a1668cc78 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -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: @@ -2711,17 +2718,16 @@ when not defined(JS): #and not defined(nimscript): proc setStdIoUnbuffered() {.tags: [], benign.} ## Configures `stdin`, `stdout` and `stderr` to be unbuffered. - 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.} @@ -2827,8 +2833,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. diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 00a16e2bb..55326f7f9 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -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 diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 1abd8466d..2f3d56082 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -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_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_fileno(f: File): cint {. + importc: "fileno", header: "<fcntl.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} diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim index 6caf99d27..27a3708ea 100644 --- a/lib/system/chcks.nim +++ b/lib/system/chcks.nim @@ -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: diff --git a/lib/system/debugger.nim b/lib/system/debugger.nim index b18c61755..55f14e982 100644 --- a/lib/system/debugger.nim +++ b/lib/system/debugger.nim @@ -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 {'\\', '/', ':'}: diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index 03230e541..6e512c9b1 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -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 diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim index 61777e514..0a994efac 100644 --- a/lib/system/dyncalls.nim +++ b/lib/system/dyncalls.nim @@ -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>".} diff --git a/lib/system/endb.nim b/lib/system/endb.nim index b2cc5624b..92aae8c71 100644 --- a/lib/system/endb.nim +++ b/lib/system/endb.nim @@ -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 diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 948f87410..526e27c83 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -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() diff --git a/lib/system/gc.nim b/lib/system/gc.nim index ee5eec30b..3e71b4fe0 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -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.} = diff --git a/lib/system/gc_stack.nim b/lib/system/gc_stack.nim index e30d0a720..5f72b8959 100644 --- a/lib/system/gc_stack.nim +++ b/lib/system/gc_stack.nim @@ -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 diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index d7010a1a3..7ef26a7c1 100644 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -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 diff --git a/lib/system/osalloc.nim b/lib/system/osalloc.nim index 8b83e194b..de26f52d9 100644 --- a/lib/system/osalloc.nim +++ b/lib/system/osalloc.nim @@ -68,7 +68,7 @@ when defined(emscripten): mmapDescr.realSize = realSize mmapDescr.realPointer = realPointer - c_fprintf(c_stdout, "[Alloc] size %d %d realSize:%d realPos:%d\n", block_size, cast[int](result), realSize, cast[int](realPointer)) + #c_fprintf(c_stdout, "[Alloc] size %d %d realSize:%d realPos:%d\n", block_size, cast[int](result), realSize, cast[int](realPointer)) proc osTryAllocPages(size: int): pointer = osAllocPages(size) @@ -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 diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index d94220d1b..552213a2d 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -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 = 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 + + # 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] - 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 = + ## Test for a directory. + (m and 0o170000) == 0o40000 + + else: + type + Mode {.importc: "mode_t", header: "<sys/types.h>".} = cint - proc S_ISDIR(m: Mode): bool {.importc, header: "<sys/stat.h>".} - ## Test for a directory. + Stat {.importc: "struct stat", + header: "<sys/stat.h>", final, pure.} = object ## struct stat + st_mode: Mode ## Mode of file - proc fstat(a1: cint, a2: var Stat): cint {.importc, header: "<sys/stat.h>".} + 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): diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index 74fcfd8c5..569470aa2 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -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) diff --git a/lib/system/threads.nim b/lib/system/threads.nim index 99927fbac..8505202b5 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -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].} diff --git a/lib/system/timers.nim b/lib/system/timers.nim index 8aa4505c4..129a7d092 100644 --- a/lib/system/timers.nim +++ b/lib/system/timers.nim @@ -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>".} diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim index 5a30a7c0f..6ad0cfd58 100644 --- a/lib/system/widestrs.nim +++ b/lib/system/widestrs.nim @@ -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) diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index b2983b23b..79e552bde 100644 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -202,14 +202,34 @@ proc parseCmdLine(c: var ConfigData) = if c.infile.len == 0: quit(Usage) if c.mainfile.len == 0: c.mainfile = changeFileExt(c.infile, "nim") -proc ignoreFile(f, root: string, allowHtml: bool): bool = +proc eqT(a, b: string; t: proc (a: char): char{.nimcall.}): bool = + ## equality under a transformation ``t``. candidate for the stdlib? + var i = 0 + var j = 0 + while i < a.len and j < b.len: + let aa = t a[i] + let bb = t b[j] + if aa == '\0': + inc i + if bb == '\0': inc j + elif bb == '\0': inc j + else: + if aa != bb: return false + inc i + inc j + result = i >= a.len and j >= b.len + +proc tPath(c: char): char = + if c == '\\': '/' + else: c + +proc ignoreFile(f, explicit: string, allowHtml: bool): bool = let (_, name, ext) = splitFile(f) let html = if not allowHtml: ".html" else: "" - let explicit = splitPath(root).tail - result = (ext in ["", ".exe", ".idx"] or - ext == html or name[0] == '.') and name & ext != explicit + result = (ext in ["", ".exe", ".idx", ".o", ".obj", ".dylib"] or + ext == html or name[0] == '.') and not eqT(f, explicit, tPath) -proc walkDirRecursively(s: var seq[string], root: string, +proc walkDirRecursively(s: var seq[string], root, explicit: string, allowHtml: bool) = let tail = splitPath(root).tail if tail == "nimcache" or tail[0] == '.': @@ -221,21 +241,21 @@ proc walkDirRecursively(s: var seq[string], root: string, else: case k of pcFile, pcLinkToFile: - if not ignoreFile(f, root, allowHtml): + if not ignoreFile(f, explicit, allowHtml): add(s, unixToNativePath(f)) of pcDir: - walkDirRecursively(s, f, allowHtml) + walkDirRecursively(s, f, explicit, allowHtml) of pcLinkToDir: discard proc addFiles(s: var seq[string], patterns: seq[string]) = for p in items(patterns): if existsDir(p): - walkDirRecursively(s, p, false) + walkDirRecursively(s, p, p, false) else: var i = 0 for f in walkFiles(p): if existsDir(f): - walkDirRecursively(s, f, false) + walkDirRecursively(s, f, p, false) elif not ignoreFile(f, p, false): add(s, unixToNativePath(f)) inc(i) diff --git a/web/news/version_0_15_released.rst b/web/news/version_0_15_released.rst index 9ca8c3ec5..618e57baa 100644 --- a/web/news/version_0_15_released.rst +++ b/web/news/version_0_15_released.rst @@ -14,6 +14,8 @@ Changes affecting backwards compatibility Library Additions ----------------- +- Added ``readHeaderRow`` and ``rowEntry`` to ``parsecsv.nim`` to provide + a lightweight alternative to python's ``csv.DictReader``. - Added ``setStdIoUnbuffered`` proc to ``system.nim`` to enable unbuffered I/O. Compiler Additions |