summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xlib/impure/re.nim12
-rwxr-xr-xlib/pure/pegs.nim12
-rwxr-xr-xlib/system.nim11
-rwxr-xr-xlib/system/sysio.nim32
-rwxr-xr-xtests/tester.nim16
-rwxr-xr-xweb/news.txt5
6 files changed, 40 insertions, 48 deletions
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index ccc13248a..eaa712f01 100755
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -342,18 +342,10 @@ proc parallelReplace*(s: string, subs: openArray[
 proc transformFile*(infile, outfile: string,
                     subs: openArray[tuple[pattern: TRegEx, repl: string]]) =
   ## reads in the file `infile`, performs a parallel replacement (calls
-  ## `parallelReplace`) and writes back to `outfile`. Calls ``quit`` if an
+  ## `parallelReplace`) and writes back to `outfile`. Raises ``EIO`` if an
   ## error occurs. This is supposed to be used for quick scripting.
   var x = readFile(infile)
-  if not isNil(x):
-    var f: TFile
-    if open(f, outfile, fmWrite):
-      write(f, x.parallelReplace(subs))
-      close(f)
-    else:
-      quit("cannot open for writing: " & outfile)
-  else:
-    quit("cannot open for reading: " & infile)
+  writeFile(outfile, x.parallelReplace(subs))
   
 iterator split*(s: string, sep: TRegEx): string =
   ## Splits the string `s` into substrings.
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 988e510e3..b7469f65b 100755
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -947,18 +947,10 @@ proc transformFile*(infile, outfile: string,
                     subs: openArray[tuple[pattern: TPeg, repl: string]]) {.
                     rtl, extern: "npegs$1".} =
   ## reads in the file `infile`, performs a parallel replacement (calls
-  ## `parallelReplace`) and writes back to `outfile`. Calls ``quit`` if an
+  ## `parallelReplace`) and writes back to `outfile`. Raises ``EIO`` if an
   ## error occurs. This is supposed to be used for quick scripting.
   var x = readFile(infile)
-  if not isNil(x):
-    var f: TFile
-    if open(f, outfile, fmWrite):
-      write(f, x.parallelReplace(subs))
-      close(f)
-    else:
-      quit("cannot open for writing: " & outfile)
-  else:
-    quit("cannot open for reading: " & infile)
+  writeFile(outfile, x.parallelReplace(subs))
   
 iterator split*(s: string, sep: TPeg): string =
   ## Splits the string `s` into substrings.
diff --git a/lib/system.nim b/lib/system.nim
index 7670288fc..1837959c7 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1582,10 +1582,15 @@ when not defined(EcmaScript) and not defined(NimrodVM):
     ## Flushes `f`'s buffer.
 
   proc readFile*(filename: string): string
-    ## Opens a file name `filename` for reading. Then reads the
+    ## Opens a file named `filename` for reading. Then reads the
     ## file's content completely into a string and
-    ## closes the file afterwards. Returns the string. Returns nil if there was
-    ## an error. Does not throw an IO exception.
+    ## closes the file afterwards. Returns the string. 
+    ## Raises an IO exception in case of an error.
+
+  proc writeFile*(filename, content: string)
+    ## Opens a file named `filename` for writing. Then writes the
+    ## `content` completely to the file and closes the file afterwards.
+    ## Raises an IO exception in case of an error.
 
   proc write*(f: TFile, r: float)
   proc write*(f: TFile, i: int)
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 80d9b1495..af6ba49b2 100755
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -78,20 +78,26 @@ proc write(f: TFile, a: openArray[string]) =
 
 #{.error: "for debugging.".}
 
+proc raiseEIO(msg: string) {.noinline, noreturn.} =
+  raise newException(EIO, msg)
+
 proc readFile(filename: string): string =
-  var f: TFile
+  var f = open(filename)
   try:
-    if open(f, filename):
-      var len = getFileSize(f)
-      if len < high(int):
-        result = newString(int(len))
-        if readBuffer(f, addr(result[0]), int(len)) != len:
-          result = nil
-      close(f)
+    var len = getFileSize(f)
+    if len < high(int):
+      result = newString(int(len))
+      if readBuffer(f, addr(result[0]), int(len)) != len:
+        raiseEIO("error while reading from file")
     else:
-      result = nil
+      raiseEIO("file too big to fit in memory")
   except EIO:
-    result = nil
+    close(f)
+
+proc writeFile(filename, content: string) =
+  var f = open(filename, fmWrite)
+  f.write(content)
+  close(f)
 
 proc EndOfFile(f: TFile): bool =
   # do not blame me; blame the ANSI C standard this is so brain-damaged
@@ -173,15 +179,15 @@ proc writeBuffer(f: TFile, buffer: pointer, len: int): int =
 
 proc write(f: TFile, s: string) =
   if writeBuffer(f, cstring(s), s.len) != s.len:
-    raise newException(EIO, "cannot write string to file")
+    raiseEIO("cannot write string to file")
 
 proc setFilePos(f: TFile, pos: int64) =
   if fseek(f, clong(pos), 0) != 0:
-    raise newException(EIO, "cannot set file position")
+    raiseEIO("cannot set file position")
 
 proc getFilePos(f: TFile): int64 =
   result = ftell(f)
-  if result < 0: raise newException(EIO, "cannot retrieve file position")
+  if result < 0: raiseEIO("cannot retrieve file position")
 
 proc getFileSize(f: TFile): int64 =
   var oldPos = getFilePos(f)
diff --git a/tests/tester.nim b/tests/tester.nim
index 1c8ce6fe2..5908b8e29 100755
--- a/tests/tester.nim
+++ b/tests/tester.nim
@@ -53,7 +53,7 @@ proc extractSpec(filename: string): string =
   var a = x.find(tripleQuote)
   var b = x.find(tripleQuote, a+3)
   if a >= 0 and b > a: 
-    result = x.copy(a+3, b-1).replace("'''", tripleQuote)
+    result = x.substr(a+3, b-1).replace("'''", tripleQuote)
   else:
     #echo "warning: file does not contain spec: " & filename
     result = ""
@@ -181,9 +181,7 @@ proc listResults(reject, compile, run: TResults) =
   s.add($run)
   s.add(TableHeader4 & run.data & TableFooter)
   s.add("</html>")
-  var outp = open(resultsFile, fmWrite)
-  write(outp, s)
-  close(outp)
+  writeFile(resultsFile, s)
 
 proc cmpMsgs(r: var TResults, expected, given: TSpec, test: string) = 
   if strip(expected.msg) notin strip(given.msg):
@@ -263,9 +261,6 @@ proc run(r: var TResults, dir, options: string) =
 proc compileExample(r: var TResults, pattern, options: string) = 
   for test in os.walkFiles(pattern): compileSingleTest(r, test, options)
 
-proc testLib(r: var TResults, options: string) =
-  nil
-
 proc toJson(res: TResults): PJsonNode =
   result = newJObject()
   result["total"] = newJInt(res.total)
@@ -278,10 +273,8 @@ proc outputJSON(reject, compile, run: TResults) =
   doc["compile"] = toJson(compile)
   doc["run"] = toJson(run)
   var s = pretty(doc)
-  var outp = open(jsonFile, fmWrite)
-  write(outp, s)
-  close(outp)
-
+  writeFile(jsonFile, s)
+  
 var options = ""
 var rejectRes = initResults()
 var compileRes = initResults()
@@ -293,6 +286,7 @@ for i in 1.. paramCount():
 
 reject(rejectRes, "tests/reject", options)
 compile(compileRes, "tests/accept/compile/t*.nim", options)
+compileExample(compileRes, "lib/pure/*.nim", options)
 compileExample(compileRes, "examples/*.nim", options)
 compileExample(compileRes, "examples/gtk/*.nim", options)
 run(runRes, "tests/accept/run", options)
diff --git a/web/news.txt b/web/news.txt
index 84cc34487..ca8f701a6 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -43,7 +43,9 @@ Changes affecting backwards compatibility
   ``^p`` in later versions or be dropped entirely since it is rarely used. 
   Use the new notation ``p[]`` in the rare cases where you need to 
   dereference a pointer explicitely.
-  
+- ``system.readFile`` does not return ``nil`` anymore but raises an ``EIO``
+  exception instead.
+
 
 Additions
 ---------
@@ -91,6 +93,7 @@ Additions
 - The compiler now supports array, sequence and string slicing.
 - Added ``system.newStringOfCap``.
 - Added ``system.raiseHook``.
+- Added ``system.writeFile ``.
 - ``system.echo`` is guaranteed to be thread-safe.