mes: Add with-error-to-file.
[mes.git] / mes / module / mes / guile.mes
1 ;;; -*-scheme-*-
2
3 ;;; GNU Mes --- Maxwell Equations of Software
4 ;;; Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
5 ;;;
6 ;;; This file is part of GNU Mes.
7 ;;;
8 ;;; GNU Mes is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
12 ;;;
13 ;;; GNU Mes is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;;; GNU General Public License for more details.
17 ;;;
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with GNU Mes.  If not, see <http://www.gnu.org/licenses/>.
20
21 ;;; Commentary:
22
23 ;;; Code:
24
25 (mes-use-module (srfi srfi-13))
26
27 (define-macro (cond-expand-provide . rest) #t)
28
29 (mes-use-module (mes catch))
30 (mes-use-module (mes posix))
31 (mes-use-module (srfi srfi-16))
32 (mes-use-module (mes display))
33
34 (define (drain-input port) (read-string))
35
36 (define (make-string n . fill)
37   (list->string (apply make-list n fill)))
38
39 (define (object->string x . rest)
40   (with-output-to-string
41     (lambda () ((if (pair? rest) (car rest) write) x))))
42
43 (define (port-filename p) "<stdin>")
44 (define (port-line p) 0)
45
46 (define (with-input-from-string string thunk)
47   (let ((prev (set-current-input-port (open-input-string string)))
48         (r (thunk)))
49     (set-current-input-port prev)
50     r))
51
52 (define (with-input-from-file file thunk)
53   (let ((port (open-input-file file)))
54     (if (= port -1)
55         (error 'no-such-file file)
56         (let* ((save (current-input-port))
57                (foo (set-current-input-port port))
58                (r (thunk)))
59           (set-current-input-port save)
60           r))))
61
62 (define (with-output-to-file file thunk)
63   (let ((port (open-output-file file)))
64     (if (= port -1)
65         (error 'cannot-open file)
66         (let* ((save (current-output-port))
67                (foo (set-current-output-port port))
68                (r (thunk)))
69           (set-current-output-port save)
70           r))))
71
72 (define (with-error-to-file file thunk)
73   (let ((port (open-output-file file)))
74     (if (= port -1)
75         (error 'cannot-open file)
76         (let* ((save (current-error-port))
77                (foo (set-current-error-port port))
78                (r (thunk)))
79           (set-current-error-port save)
80           r))))
81
82 (define (with-output-to-port port thunk)
83   (let* ((save (current-output-port))
84          (foo (set-current-output-port port))
85          (r (thunk)))
86     (set-current-output-port save)
87     r))
88
89 (define core:open-input-file open-input-file)
90 (define (open-input-file file)
91   (let ((port (core:open-input-file file))
92         (debug (and=> (getenv "MES_DEBUG") string->number)))
93     (when (and debug (> debug 1))
94       (core:display-error (string-append "open-input-file: `" file "'"))
95       (when (> debug 3)
96         (core:display-error " port=")
97         (core:display-error port)))
98     (core:display-error "\n")
99     port))
100
101 (define (dirname file-name)
102   (let ((lst (filter (negate string-null?) (string-split file-name #\/))))
103     (if (<= (length lst) 1) "."
104         (string-join (list-head lst (1- (length lst))) "/"))))
105
106 ;; FIXME: c&p from display
107 (define (with-output-to-string thunk)
108   (define save-write-byte write-byte)
109   (let ((stdout '()))
110     (set! write-byte
111           (lambda (x . rest)
112             (let ((out? (or (null? rest) (eq? (car rest) (current-output-port)))))
113               (if (not out?) (apply save-write-byte (cons x rest))
114                   (begin
115                     (set! stdout (append stdout (list (integer->char x))))
116                     x)))))
117     (thunk)
118     (let ((r (apply string stdout)))
119       (set! write-byte save-write-byte)
120       r)))
121
122 ;; FIXME: c&p from display
123 (define (simple-format destination format . rest)
124   (let ((port (if (boolean? destination) (current-output-port) destination))
125         (lst (string->list format)))
126     (define (simple-format lst args)
127       (if (pair? lst)
128           (let ((c (car lst)))
129             (if (not (eq? c #\~)) (begin (write-char (car lst) port)
130                                          (simple-format (cdr lst) args))
131                 (let ((c (cadr lst)))
132                   (case c
133                     ((#\a) (display (car args) port))
134                     ((#\s) (write (car args) port)))
135                   (simple-format (cddr lst) (cdr args)))))))
136
137     (if destination (simple-format lst rest)
138         (with-output-to-string
139           (lambda () (simple-format lst rest))))))
140 (define format simple-format)