mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-09 21:40:33 +02:00
Merge remote-tracking branch 'origin/stable-2.0'
This commit is contained in:
commit
d31d703fd4
13 changed files with 265 additions and 359 deletions
|
@ -67,7 +67,6 @@ guile_TEXINFOS = preface.texi \
|
||||||
api-deprecated.texi \
|
api-deprecated.texi \
|
||||||
scheme-using.texi \
|
scheme-using.texi \
|
||||||
indices.texi \
|
indices.texi \
|
||||||
script-getopt.texi \
|
|
||||||
data-rep.texi \
|
data-rep.texi \
|
||||||
repl-modules.texi \
|
repl-modules.texi \
|
||||||
srfi-modules.texi \
|
srfi-modules.texi \
|
||||||
|
|
|
@ -13,8 +13,9 @@ The @code{(ice-9 getopt-long)} module exports two procedures:
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
@code{getopt-long} takes a list of strings --- the command line
|
@code{getopt-long} takes a list of strings --- the command line
|
||||||
arguments --- and an @dfn{option specification}. It parses the command
|
arguments --- an @dfn{option specification}, and some optional keyword
|
||||||
line arguments according to the option specification and returns a data
|
parameters. It parses the command line arguments according to the
|
||||||
|
option specification and keyword parameters, and returns a data
|
||||||
structure that encapsulates the results of the parsing.
|
structure that encapsulates the results of the parsing.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
|
@ -254,7 +255,7 @@ as ordinary argument strings.
|
||||||
@node getopt-long Reference
|
@node getopt-long Reference
|
||||||
@subsection Reference Documentation for @code{getopt-long}
|
@subsection Reference Documentation for @code{getopt-long}
|
||||||
|
|
||||||
@deffn {Scheme Procedure} getopt-long args grammar
|
@deffn {Scheme Procedure} getopt-long args grammar [#:stop-at-first-non-option #t]
|
||||||
Parse the command line given in @var{args} (which must be a list of
|
Parse the command line given in @var{args} (which must be a list of
|
||||||
strings) according to the option specification @var{grammar}.
|
strings) according to the option specification @var{grammar}.
|
||||||
|
|
||||||
|
@ -290,6 +291,13 @@ value, and throw an exception if it returns @code{#f}. @var{func}
|
||||||
should be a procedure which accepts a string and returns a boolean
|
should be a procedure which accepts a string and returns a boolean
|
||||||
value; you may need to use quasiquotes to get it into @var{grammar}.
|
value; you may need to use quasiquotes to get it into @var{grammar}.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
The @code{#:stop-at-first-non-option} keyword, if specified with any
|
||||||
|
true value, tells @code{getopt-long} to stop when it gets to the first
|
||||||
|
non-option in the command line. That is, at the first word which is
|
||||||
|
neither an option itself, nor the value of an option. Everything in the
|
||||||
|
command line from that word onwards will be returned as non-option
|
||||||
|
arguments.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@code{getopt-long}'s @var{args} parameter is expected to be a list of
|
@code{getopt-long}'s @var{args} parameter is expected to be a list of
|
||||||
|
@ -323,6 +331,18 @@ happen using the long option @code{--opt=@var{value}} syntax).
|
||||||
An option predicate fails.
|
An option predicate fails.
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
|
@code{#:stop-at-first-non-option} is useful for command line invocations
|
||||||
|
like @code{guile-tools [--help | --version] [script [script-options]]}
|
||||||
|
and @code{cvs [general-options] command [command-options]}, where there
|
||||||
|
are options at two levels: some generic and understood by the outer
|
||||||
|
command, and some that are specific to the particular script or command
|
||||||
|
being invoked. To use @code{getopt-long} in such cases, you would call
|
||||||
|
it twice: firstly with @code{#:stop-at-first-non-option #t}, so as to
|
||||||
|
parse any generic options and identify the wanted script or sub-command;
|
||||||
|
secondly, and after trimming off the initial generic command words, with
|
||||||
|
a script- or sub-command-specific option grammar, so as to process those
|
||||||
|
specific options.
|
||||||
|
|
||||||
|
|
||||||
@node option-ref Reference
|
@node option-ref Reference
|
||||||
@subsection Reference Documentation for @code{option-ref}
|
@subsection Reference Documentation for @code{option-ref}
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
@c -*-texinfo-*-
|
|
||||||
@c This is part of the GNU Guile Reference Manual.
|
|
||||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004
|
|
||||||
@c Free Software Foundation, Inc.
|
|
||||||
@c See the file guile.texi for copying conditions.
|
|
||||||
|
|
||||||
@node Command Line Handling
|
|
||||||
@section Handling Command Line Options and Arguments
|
|
||||||
|
|
||||||
@c This chapter was written and contributed by Martin Grabmueller.
|
|
||||||
|
|
||||||
The ability to accept and handle command line arguments is very
|
|
||||||
important when writing Guile scripts to solve particular problems, such
|
|
||||||
as extracting information from text files or interfacing with existing
|
|
||||||
command line applications. This chapter describes how Guile makes
|
|
||||||
command line arguments available to a Guile script, and the utilities
|
|
||||||
that Guile provides to help with the processing of command line
|
|
||||||
arguments.
|
|
||||||
|
|
||||||
When a Guile script is invoked, Guile makes the command line arguments
|
|
||||||
accessible via the procedure @code{command-line}, which returns the
|
|
||||||
arguments as a list of strings.
|
|
||||||
|
|
||||||
For example, if the script
|
|
||||||
|
|
||||||
@example
|
|
||||||
#! /usr/local/bin/guile -s
|
|
||||||
!#
|
|
||||||
(write (command-line))
|
|
||||||
(newline)
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
is saved in a file @file{cmdline-test.scm} and invoked using the command
|
|
||||||
line @code{./cmdline-test.scm bar.txt -o foo -frumple grob}, the output
|
|
||||||
is
|
|
||||||
|
|
||||||
@example
|
|
||||||
("./cmdline-test.scm" "bar.txt" "-o" "foo" "-frumple" "grob")
|
|
||||||
@end example
|
|
||||||
|
|
||||||
If the script invocation includes a @code{-e} option, specifying a
|
|
||||||
procedure to call after loading the script, Guile will call that
|
|
||||||
procedure with @code{(command-line)} as its argument. So a script that
|
|
||||||
uses @code{-e} doesn't need to refer explicitly to @code{command-line}
|
|
||||||
in its code. For example, the script above would have identical
|
|
||||||
behaviour if it was written instead like this:
|
|
||||||
|
|
||||||
@example
|
|
||||||
#! /usr/local/bin/guile \
|
|
||||||
-e main -s
|
|
||||||
!#
|
|
||||||
(define (main args)
|
|
||||||
(write args)
|
|
||||||
(newline))
|
|
||||||
@end example
|
|
||||||
|
|
||||||
(Note the use of the meta switch @code{\} so that the script invocation
|
|
||||||
can include more than one Guile option: @xref{The Meta Switch}.)
|
|
||||||
|
|
||||||
These scripts use the @code{#!} POSIX convention so that they can be
|
|
||||||
executed using their own file names directly, as in the example command
|
|
||||||
line @code{./cmdline-test.scm bar.txt -o foo -frumple grob}. But they
|
|
||||||
can also be executed by typing out the implied Guile command line in
|
|
||||||
full, as in:
|
|
||||||
|
|
||||||
@example
|
|
||||||
$ guile -s ./cmdline-test.scm bar.txt -o foo -frumple grob
|
|
||||||
@end example
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
or
|
|
||||||
|
|
||||||
@example
|
|
||||||
$ guile -e main -s ./cmdline-test2.scm bar.txt -o foo -frumple grob
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Even when a script is invoked using this longer form, the arguments that
|
|
||||||
the script receives are the same as if it had been invoked using the
|
|
||||||
short form. Guile ensures that the @code{(command-line)} or @code{-e}
|
|
||||||
arguments are independent of how the script is invoked, by stripping off
|
|
||||||
the arguments that Guile itself processes.
|
|
||||||
|
|
||||||
A script is free to parse and handle its command line arguments in any
|
|
||||||
way that it chooses. Where the set of possible options and arguments is
|
|
||||||
complex, however, it can get tricky to extract all the options, check
|
|
||||||
the validity of given arguments, and so on. This task can be greatly
|
|
||||||
simplified by taking advantage of the module @code{(ice-9 getopt-long)},
|
|
||||||
which is distributed with Guile, @xref{getopt-long}.
|
|
||||||
|
|
||||||
@c Local Variables:
|
|
||||||
@c TeX-master: "guile.texi"
|
|
||||||
@c End:
|
|
|
@ -1377,40 +1377,20 @@ scm_internal_hash_fold (scm_t_hash_fold_fn fn, void *closure,
|
||||||
n = SCM_SIMPLE_VECTOR_LENGTH (buckets);
|
n = SCM_SIMPLE_VECTOR_LENGTH (buckets);
|
||||||
for (i = 0; i < n; ++i)
|
for (i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
SCM prev, ls;
|
SCM ls, handle;
|
||||||
|
|
||||||
for (prev = SCM_BOOL_F, ls = SCM_SIMPLE_VECTOR_REF (buckets, i);
|
for (ls = SCM_SIMPLE_VECTOR_REF (buckets, i); !scm_is_null (ls);
|
||||||
!scm_is_null (ls);
|
ls = SCM_CDR (ls))
|
||||||
prev = ls, ls = SCM_CDR (ls))
|
|
||||||
{
|
{
|
||||||
SCM handle;
|
|
||||||
|
|
||||||
if (!scm_is_pair (ls))
|
|
||||||
SCM_WRONG_TYPE_ARG (SCM_ARG3, buckets);
|
|
||||||
|
|
||||||
handle = SCM_CAR (ls);
|
handle = SCM_CAR (ls);
|
||||||
if (!scm_is_pair (handle))
|
|
||||||
SCM_WRONG_TYPE_ARG (SCM_ARG3, buckets);
|
|
||||||
|
|
||||||
if (SCM_HASHTABLE_WEAK_P (table))
|
if (SCM_HASHTABLE_WEAK_P (table) && SCM_WEAK_PAIR_DELETED_P (handle))
|
||||||
{
|
/* Don't try to unlink this weak pair, as we're not within
|
||||||
if (SCM_WEAK_PAIR_DELETED_P (handle))
|
the allocation lock. Instead rely on
|
||||||
{
|
vacuum_weak_hash_table to do its job. */
|
||||||
/* We hit a weak pair whose car/cdr has become
|
continue;
|
||||||
unreachable: unlink it from the bucket. */
|
else
|
||||||
if (scm_is_true (prev))
|
result = fn (closure, SCM_CAR (handle), SCM_CDR (handle), result);
|
||||||
SCM_SETCDR (prev, SCM_CDR (ls));
|
|
||||||
else
|
|
||||||
SCM_SIMPLE_VECTOR_SET (buckets, i, SCM_CDR (ls));
|
|
||||||
|
|
||||||
/* Update the item count. */
|
|
||||||
SCM_HASHTABLE_DECREMENT (table);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = fn (closure, SCM_CAR (handle), SCM_CDR (handle), result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1179,12 +1179,21 @@ tp_flush (SCM port)
|
||||||
scm_t_port *c_port = SCM_PTAB_ENTRY (port);
|
scm_t_port *c_port = SCM_PTAB_ENTRY (port);
|
||||||
size_t count = c_port->write_pos - c_port->write_buf;
|
size_t count = c_port->write_pos - c_port->write_buf;
|
||||||
|
|
||||||
scm_c_write (binary_port, c_port->write_buf, count);
|
/* As the runtime will try to flush all ports upon exit, we test for
|
||||||
|
the underlying port still being open here. Otherwise, when you
|
||||||
|
would explicitly close the underlying port and the transcoded port
|
||||||
|
still had data outstanding, you'd get an exception on Guile exit.
|
||||||
|
|
||||||
|
We just throw away the data when the underlying port is closed. */
|
||||||
|
|
||||||
|
if (SCM_OPOUTPORTP (binary_port))
|
||||||
|
scm_c_write (binary_port, c_port->write_buf, count);
|
||||||
|
|
||||||
c_port->write_pos = c_port->write_buf;
|
c_port->write_pos = c_port->write_buf;
|
||||||
c_port->rw_active = SCM_PORT_NEITHER;
|
c_port->rw_active = SCM_PORT_NEITHER;
|
||||||
|
|
||||||
scm_force_output (binary_port);
|
if (SCM_OPOUTPORTP (binary_port))
|
||||||
|
scm_force_output (binary_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -24,7 +24,7 @@ exec guile $GUILE_FLAGS -e '(@@ (guile-tools) main)' -s "$0" "$@"
|
||||||
;;;; Boston, MA 02110-1301 USA
|
;;;; Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
(define-module (guile-tools)
|
(define-module (guile-tools)
|
||||||
#:use-module ((srfi srfi-1) #:select (fold append-map))
|
#:use-module (ice-9 getopt-long)
|
||||||
#:autoload (ice-9 format) (format))
|
#:autoload (ice-9 format) (format))
|
||||||
|
|
||||||
;; Hack to provide scripts with the bug-report address.
|
;; Hack to provide scripts with the bug-report address.
|
||||||
|
@ -55,146 +55,34 @@ This is free software: you are free to change and redistribute it.
|
||||||
There is NO WARRANTY, to the extent permitted by law.
|
There is NO WARRANTY, to the extent permitted by law.
|
||||||
" (version) (effective-version)))
|
" (version) (effective-version)))
|
||||||
|
|
||||||
(define (directory-files dir)
|
|
||||||
(if (and (file-exists? dir) (file-is-directory? dir))
|
|
||||||
(let ((dir-stream (opendir dir)))
|
|
||||||
(let loop ((new (readdir dir-stream))
|
|
||||||
(acc '()))
|
|
||||||
(if (eof-object? new)
|
|
||||||
(begin
|
|
||||||
(closedir dir-stream)
|
|
||||||
acc)
|
|
||||||
(loop (readdir dir-stream)
|
|
||||||
(if (or (string=? "." new) ; ignore
|
|
||||||
(string=? ".." new)) ; ignore
|
|
||||||
acc
|
|
||||||
(cons new acc))))))
|
|
||||||
'()))
|
|
||||||
|
|
||||||
(define (strip-extensions path)
|
|
||||||
(or-map (lambda (ext)
|
|
||||||
(and
|
|
||||||
(string-suffix? ext path)
|
|
||||||
(substring path 0
|
|
||||||
(- (string-length path) (string-length ext)))))
|
|
||||||
(append %load-compiled-extensions %load-extensions)))
|
|
||||||
|
|
||||||
(define (unique l)
|
|
||||||
(cond ((null? l) l)
|
|
||||||
((null? (cdr l)) l)
|
|
||||||
((equal? (car l) (cadr l)) (unique (cdr l)))
|
|
||||||
(else (cons (car l) (unique (cdr l))))))
|
|
||||||
|
|
||||||
(define (find-submodules head)
|
|
||||||
(let ((shead (map symbol->string head)))
|
|
||||||
(unique
|
|
||||||
(sort
|
|
||||||
(append-map (lambda (path)
|
|
||||||
(fold (lambda (x rest)
|
|
||||||
(let ((stripped (strip-extensions x)))
|
|
||||||
(if stripped (cons stripped rest) rest)))
|
|
||||||
'()
|
|
||||||
(directory-files
|
|
||||||
(fold (lambda (x y) (in-vicinity y x)) path shead))))
|
|
||||||
%load-path)
|
|
||||||
string<?))))
|
|
||||||
|
|
||||||
(define (list-scripts)
|
|
||||||
(for-each (lambda (x)
|
|
||||||
;; would be nice to show a summary.
|
|
||||||
(format #t "~A\n" x))
|
|
||||||
(find-submodules '(scripts))))
|
|
||||||
|
|
||||||
(define (find-script s)
|
(define (find-script s)
|
||||||
(resolve-module (list 'scripts (string->symbol s)) #:ensure #f))
|
(resolve-module (list 'scripts (string->symbol s)) #:ensure #f))
|
||||||
|
|
||||||
(define (getopt args grammar)
|
|
||||||
(define (fail)
|
|
||||||
(format (current-error-port)
|
|
||||||
"Try `guile-tools --help' for more information.~%")
|
|
||||||
(exit 1))
|
|
||||||
|
|
||||||
(define (unrecognized-arg arg)
|
|
||||||
(format (current-error-port)
|
|
||||||
"guile-tools: unrecognized option: `~a'~%" arg)
|
|
||||||
(fail))
|
|
||||||
|
|
||||||
(define (unexpected-value sym val)
|
|
||||||
(format (current-error-port)
|
|
||||||
"guile-tools: option `--~a' does not take an argument (given ~s)~%"
|
|
||||||
sym val)
|
|
||||||
(fail))
|
|
||||||
|
|
||||||
(define (single-char-table grammar)
|
|
||||||
(cond
|
|
||||||
((null? grammar) '())
|
|
||||||
((assq 'single-char (cdar grammar))
|
|
||||||
=> (lambda (form)
|
|
||||||
(acons (cadr form) (car grammar)
|
|
||||||
(single-char-table (cdr grammar)))))
|
|
||||||
(else
|
|
||||||
(single-char-table (cdr grammar)))))
|
|
||||||
|
|
||||||
(let ((single (single-char-table grammar)))
|
|
||||||
(let lp ((args (cdr args)) (options '()))
|
|
||||||
(cond
|
|
||||||
((or (null? args) (equal? (car args) "-"))
|
|
||||||
(values (reverse options) args))
|
|
||||||
((equal? (car args) "--")
|
|
||||||
(values (reverse options) (cdr args)))
|
|
||||||
((string-prefix? "--" (car args))
|
|
||||||
(let* ((str (car args))
|
|
||||||
(eq (string-index str #\= 2))
|
|
||||||
(sym (string->symbol
|
|
||||||
(substring str 2 (or eq (string-length str)))))
|
|
||||||
(val (and eq (substring str (1+ eq))))
|
|
||||||
(spec (assq sym grammar)))
|
|
||||||
(cond
|
|
||||||
((not spec)
|
|
||||||
(unrecognized-arg (substring str 0 (or eq (string-length str)))))
|
|
||||||
(val
|
|
||||||
;; no values for now
|
|
||||||
(unexpected-value sym val))
|
|
||||||
((assq-ref (cdr spec) 'value)
|
|
||||||
(error "options with values not supported right now"))
|
|
||||||
(else
|
|
||||||
(lp (cdr args) (acons sym #f options))))))
|
|
||||||
((string-prefix? "-" (car args))
|
|
||||||
(let lp* ((chars (cdr (string->list (car args)))) (options options))
|
|
||||||
(if (null? chars)
|
|
||||||
(lp (cdr args) options)
|
|
||||||
(let ((spec (assv-ref single (car chars))))
|
|
||||||
(cond
|
|
||||||
((not spec)
|
|
||||||
(unrecognized-arg (string #\- (car chars))))
|
|
||||||
((assq-ref (cdr spec) 'value)
|
|
||||||
(error "options with values not supported right now"))
|
|
||||||
(else
|
|
||||||
(lp* (cdr chars) (acons (car spec) #f options))))))))
|
|
||||||
(else (values (reverse options) args))))))
|
|
||||||
|
|
||||||
(define (main args)
|
(define (main args)
|
||||||
(if (defined? 'setlocale)
|
(if (defined? 'setlocale)
|
||||||
(setlocale LC_ALL ""))
|
(setlocale LC_ALL ""))
|
||||||
|
|
||||||
(call-with-values (lambda () (getopt args *option-grammar*))
|
(let ((options (getopt-long args *option-grammar*
|
||||||
(lambda (options args)
|
#:stop-at-first-non-option #t)))
|
||||||
(cond
|
(cond
|
||||||
((assq 'help options)
|
((option-ref options 'help #f)
|
||||||
(display-help)
|
(display-help)
|
||||||
(exit 0))
|
(exit 0))
|
||||||
((assq 'version options)
|
((option-ref options 'version #f)
|
||||||
(display-version)
|
(display-version)
|
||||||
(exit 0))
|
(exit 0))
|
||||||
((or (equal? args '())
|
(else
|
||||||
(equal? args '("list")))
|
(let ((args (option-ref options '() '())))
|
||||||
(list-scripts))
|
(cond ((find-script (if (null? args)
|
||||||
((find-script (car args))
|
"list"
|
||||||
=> (lambda (mod)
|
(car args)))
|
||||||
(exit (apply (module-ref mod 'main) (cdr args)))))
|
=> (lambda (mod)
|
||||||
(else
|
(exit (apply (module-ref mod 'main) (if (null? args)
|
||||||
(format (current-error-port)
|
'()
|
||||||
"guile-tools: unknown script ~s~%" (car args))
|
(cdr args))))))
|
||||||
(format (current-error-port)
|
(else
|
||||||
"Try `guile-tools --help' for more information.~%")
|
(format (current-error-port)
|
||||||
(exit 1))))))
|
"guile-tools: unknown script ~s~%" (car args))
|
||||||
|
(format (current-error-port)
|
||||||
|
"Try `guile-tools --help' for more information.~%")
|
||||||
|
(exit 1))))))))
|
||||||
|
|
|
@ -155,6 +155,7 @@ SCRIPTS_SOURCES = \
|
||||||
scripts/frisk.scm \
|
scripts/frisk.scm \
|
||||||
scripts/generate-autoload.scm \
|
scripts/generate-autoload.scm \
|
||||||
scripts/lint.scm \
|
scripts/lint.scm \
|
||||||
|
scripts/list.scm \
|
||||||
scripts/punify.scm \
|
scripts/punify.scm \
|
||||||
scripts/read-scheme-source.scm \
|
scripts/read-scheme-source.scm \
|
||||||
scripts/read-text-outline.scm \
|
scripts/read-text-outline.scm \
|
||||||
|
|
|
@ -682,7 +682,7 @@ If there is no handler at all, Guile prints an error and then exits."
|
||||||
(let ((filename (or (cadr source) "<unnamed port>"))
|
(let ((filename (or (cadr source) "<unnamed port>"))
|
||||||
(line (caddr source))
|
(line (caddr source))
|
||||||
(col (cdddr source)))
|
(col (cdddr source)))
|
||||||
(format port "~a:~a:~a: " filename line col))
|
(format port "~a:~a:~a: " filename (1+ line) col))
|
||||||
(format port "ERROR: "))))
|
(format port "ERROR: "))))
|
||||||
|
|
||||||
(set! set-exception-printer!
|
(set! set-exception-printer!
|
||||||
|
|
|
@ -161,6 +161,7 @@
|
||||||
#:use-module (srfi srfi-9)
|
#:use-module (srfi srfi-9)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (ice-9 regex)
|
#:use-module (ice-9 regex)
|
||||||
|
#:use-module (ice-9 optargs)
|
||||||
#:export (getopt-long option-ref))
|
#:export (getopt-long option-ref))
|
||||||
|
|
||||||
(define %program-name (make-fluid))
|
(define %program-name (make-fluid))
|
||||||
|
@ -179,8 +180,6 @@
|
||||||
option-spec?
|
option-spec?
|
||||||
(name
|
(name
|
||||||
option-spec->name set-option-spec-name!)
|
option-spec->name set-option-spec-name!)
|
||||||
(value
|
|
||||||
option-spec->value set-option-spec-value!)
|
|
||||||
(required?
|
(required?
|
||||||
option-spec->required? set-option-spec-required?!)
|
option-spec->required? set-option-spec-required?!)
|
||||||
(option-spec->single-char
|
(option-spec->single-char
|
||||||
|
@ -228,33 +227,12 @@
|
||||||
(define long-opt-no-value-rx (make-regexp "^--([^=]+)$"))
|
(define long-opt-no-value-rx (make-regexp "^--([^=]+)$"))
|
||||||
(define long-opt-with-value-rx (make-regexp "^--([^=]+)=(.*)"))
|
(define long-opt-with-value-rx (make-regexp "^--([^=]+)=(.*)"))
|
||||||
|
|
||||||
(define (expand-clumped-singles opt-ls)
|
|
||||||
;; example: ("--xyz" "-abc5d") => ("--xyz" "-a" "-b" "-c" "5d")
|
|
||||||
(let loop ((opt-ls opt-ls) (ret-ls '()))
|
|
||||||
(cond ((null? opt-ls)
|
|
||||||
(reverse ret-ls)) ;;; retval
|
|
||||||
((regexp-exec short-opt-rx (car opt-ls))
|
|
||||||
=> (lambda (match)
|
|
||||||
(let ((singles (reverse
|
|
||||||
(map (lambda (c)
|
|
||||||
(string-append "-" (make-string 1 c)))
|
|
||||||
(string->list
|
|
||||||
(match:substring match 1)))))
|
|
||||||
(extra (match:substring match 2)))
|
|
||||||
(loop (cdr opt-ls)
|
|
||||||
(append (if (string=? "" extra)
|
|
||||||
singles
|
|
||||||
(cons extra singles))
|
|
||||||
ret-ls)))))
|
|
||||||
(else (loop (cdr opt-ls)
|
|
||||||
(cons (car opt-ls) ret-ls))))))
|
|
||||||
|
|
||||||
(define (looks-like-an-option string)
|
(define (looks-like-an-option string)
|
||||||
(or (regexp-exec short-opt-rx string)
|
(or (regexp-exec short-opt-rx string)
|
||||||
(regexp-exec long-opt-with-value-rx string)
|
(regexp-exec long-opt-with-value-rx string)
|
||||||
(regexp-exec long-opt-no-value-rx string)))
|
(regexp-exec long-opt-no-value-rx string)))
|
||||||
|
|
||||||
(define (process-options specs argument-ls)
|
(define (process-options specs argument-ls stop-at-first-non-option)
|
||||||
;; Use SPECS to scan ARGUMENT-LS; return (FOUND . ETC).
|
;; Use SPECS to scan ARGUMENT-LS; return (FOUND . ETC).
|
||||||
;; FOUND is an unordered list of option specs for found options, while ETC
|
;; FOUND is an unordered list of option specs for found options, while ETC
|
||||||
;; is an order-maintained list of elements in ARGUMENT-LS that are neither
|
;; is an order-maintained list of elements in ARGUMENT-LS that are neither
|
||||||
|
@ -266,32 +244,22 @@
|
||||||
(cons (make-string 1 (option-spec->single-char spec))
|
(cons (make-string 1 (option-spec->single-char spec))
|
||||||
spec))
|
spec))
|
||||||
(remove-if-not option-spec->single-char specs))))
|
(remove-if-not option-spec->single-char specs))))
|
||||||
(let loop ((argument-ls argument-ls) (found '()) (etc '()))
|
(let loop ((unclumped 0) (argument-ls argument-ls) (found '()) (etc '()))
|
||||||
(define (eat! spec ls)
|
(define (eat! spec ls)
|
||||||
(define (val!loop val n-ls n-found n-etc)
|
|
||||||
(set-option-spec-value!
|
|
||||||
spec
|
|
||||||
;; handle multiple occurrances
|
|
||||||
(cond ((option-spec->value spec)
|
|
||||||
=> (lambda (cur)
|
|
||||||
((if (list? cur) cons list)
|
|
||||||
val cur)))
|
|
||||||
(else val)))
|
|
||||||
(loop n-ls n-found n-etc))
|
|
||||||
(cond
|
(cond
|
||||||
((eq? 'optional (option-spec->value-policy spec))
|
((eq? 'optional (option-spec->value-policy spec))
|
||||||
(if (or (null? ls)
|
(if (or (null? ls)
|
||||||
(looks-like-an-option (car ls)))
|
(looks-like-an-option (car ls)))
|
||||||
(val!loop #t ls (cons spec found) etc)
|
(loop (- unclumped 1) ls (acons spec #t found) etc)
|
||||||
(val!loop (car ls) (cdr ls) (cons spec found) etc)))
|
(loop (- unclumped 2) (cdr ls) (acons spec (car ls) found) etc)))
|
||||||
((eq? #t (option-spec->value-policy spec))
|
((eq? #t (option-spec->value-policy spec))
|
||||||
(if (or (null? ls)
|
(if (or (null? ls)
|
||||||
(looks-like-an-option (car ls)))
|
(looks-like-an-option (car ls)))
|
||||||
(fatal-error "option must be specified with argument: --~a"
|
(fatal-error "option must be specified with argument: --~a"
|
||||||
(option-spec->name spec))
|
(option-spec->name spec))
|
||||||
(val!loop (car ls) (cdr ls) (cons spec found) etc)))
|
(loop (- unclumped 2) (cdr ls) (acons spec (car ls) found) etc)))
|
||||||
(else
|
(else
|
||||||
(val!loop #t ls (cons spec found) etc))))
|
(loop (- unclumped 1) ls (acons spec #t found) etc))))
|
||||||
|
|
||||||
(match argument-ls
|
(match argument-ls
|
||||||
(()
|
(()
|
||||||
|
@ -300,10 +268,24 @@
|
||||||
(cond
|
(cond
|
||||||
((regexp-exec short-opt-rx opt)
|
((regexp-exec short-opt-rx opt)
|
||||||
=> (lambda (match)
|
=> (lambda (match)
|
||||||
(let* ((c (match:substring match 1))
|
(if (> unclumped 0)
|
||||||
(spec (or (assoc-ref sc-idx c)
|
;; Next option is known not to be clumped.
|
||||||
(fatal-error "no such option: -~a" c))))
|
(let* ((c (match:substring match 1))
|
||||||
(eat! spec rest))))
|
(spec (or (assoc-ref sc-idx c)
|
||||||
|
(fatal-error "no such option: -~a" c))))
|
||||||
|
(eat! spec rest))
|
||||||
|
;; Expand a clumped group of short options.
|
||||||
|
(let* ((extra (match:substring match 2))
|
||||||
|
(unclumped-opts
|
||||||
|
(append (map (lambda (c)
|
||||||
|
(string-append "-" (make-string 1 c)))
|
||||||
|
(string->list
|
||||||
|
(match:substring match 1)))
|
||||||
|
(if (string=? "" extra) '() (list extra)))))
|
||||||
|
(loop (length unclumped-opts)
|
||||||
|
(append unclumped-opts rest)
|
||||||
|
found
|
||||||
|
etc)))))
|
||||||
((regexp-exec long-opt-no-value-rx opt)
|
((regexp-exec long-opt-no-value-rx opt)
|
||||||
=> (lambda (match)
|
=> (lambda (match)
|
||||||
(let* ((opt (match:substring match 1))
|
(let* ((opt (match:substring match 1))
|
||||||
|
@ -319,10 +301,14 @@
|
||||||
(eat! spec (cons (match:substring match 2) rest))
|
(eat! spec (cons (match:substring match 2) rest))
|
||||||
(fatal-error "option does not support argument: --~a"
|
(fatal-error "option does not support argument: --~a"
|
||||||
opt)))))
|
opt)))))
|
||||||
|
((and stop-at-first-non-option
|
||||||
|
(<= unclumped 0))
|
||||||
|
(cons found (append (reverse etc) argument-ls)))
|
||||||
(else
|
(else
|
||||||
(loop rest found (cons opt etc)))))))))
|
(loop (- unclumped 1) rest found (cons opt etc)))))))))
|
||||||
|
|
||||||
(define (getopt-long program-arguments option-desc-list)
|
(define* (getopt-long program-arguments option-desc-list
|
||||||
|
#:key stop-at-first-non-option)
|
||||||
"Process options, handling both long and short options, similar to
|
"Process options, handling both long and short options, similar to
|
||||||
the glibc function 'getopt_long'. PROGRAM-ARGUMENTS should be a value
|
the glibc function 'getopt_long'. PROGRAM-ARGUMENTS should be a value
|
||||||
similar to what (program-arguments) returns. OPTION-DESC-LIST is a
|
similar to what (program-arguments) returns. OPTION-DESC-LIST is a
|
||||||
|
@ -356,44 +342,27 @@ to add a `single-char' clause to the option description."
|
||||||
(with-fluids ((%program-name (car program-arguments)))
|
(with-fluids ((%program-name (car program-arguments)))
|
||||||
(let* ((specifications (map parse-option-spec option-desc-list))
|
(let* ((specifications (map parse-option-spec option-desc-list))
|
||||||
(pair (split-arg-list (cdr program-arguments)))
|
(pair (split-arg-list (cdr program-arguments)))
|
||||||
(split-ls (expand-clumped-singles (car pair)))
|
(split-ls (car pair))
|
||||||
(non-split-ls (cdr pair))
|
(non-split-ls (cdr pair))
|
||||||
(found/etc (process-options specifications split-ls))
|
(found/etc (process-options specifications split-ls
|
||||||
|
stop-at-first-non-option))
|
||||||
(found (car found/etc))
|
(found (car found/etc))
|
||||||
(rest-ls (append (cdr found/etc) non-split-ls)))
|
(rest-ls (append (cdr found/etc) non-split-ls)))
|
||||||
(for-each (lambda (spec)
|
(for-each (lambda (spec)
|
||||||
(let ((name (option-spec->name spec))
|
(let ((name (option-spec->name spec))
|
||||||
(val (option-spec->value spec)))
|
(val (assq-ref found spec)))
|
||||||
(and (option-spec->required? spec)
|
(and (option-spec->required? spec)
|
||||||
(or (memq spec found)
|
(or val
|
||||||
(fatal-error "option must be specified: --~a"
|
(fatal-error "option must be specified: --~a"
|
||||||
name)))
|
name)))
|
||||||
(and (memq spec found)
|
|
||||||
(eq? #t (option-spec->value-policy spec))
|
|
||||||
(or val
|
|
||||||
(fatal-error
|
|
||||||
"option must be specified with argument: --~a"
|
|
||||||
name)))
|
|
||||||
(let ((pred (option-spec->predicate spec)))
|
(let ((pred (option-spec->predicate spec)))
|
||||||
(and pred (pred name val)))))
|
(and pred (pred name val)))))
|
||||||
specifications)
|
specifications)
|
||||||
(cons (cons '() rest-ls)
|
(for-each (lambda (spec+val)
|
||||||
(let ((multi-count (map (lambda (desc)
|
(set-car! spec+val
|
||||||
(cons (car desc) 0))
|
(string->symbol (option-spec->name (car spec+val)))))
|
||||||
option-desc-list)))
|
found)
|
||||||
(map (lambda (spec)
|
(cons (cons '() rest-ls) found))))
|
||||||
(let ((name (string->symbol (option-spec->name spec))))
|
|
||||||
(cons name
|
|
||||||
;; handle multiple occurrances
|
|
||||||
(let ((maybe-ls (option-spec->value spec)))
|
|
||||||
(if (list? maybe-ls)
|
|
||||||
(let* ((look (assq name multi-count))
|
|
||||||
(idx (cdr look))
|
|
||||||
(val (list-ref maybe-ls idx)))
|
|
||||||
(set-cdr! look (1+ idx)) ; ugh!
|
|
||||||
val)
|
|
||||||
maybe-ls)))))
|
|
||||||
found))))))
|
|
||||||
|
|
||||||
(define (option-ref options key default)
|
(define (option-ref options key default)
|
||||||
"Return value in alist OPTIONS using KEY, a symbol; or DEFAULT if not found.
|
"Return value in alist OPTIONS using KEY, a symbol; or DEFAULT if not found.
|
||||||
|
|
|
@ -311,7 +311,9 @@ read from/written to in @var{port}."
|
||||||
(buffer-mode (buffer-mode block))
|
(buffer-mode (buffer-mode block))
|
||||||
maybe-transcoder)
|
maybe-transcoder)
|
||||||
(let ((port (with-i/o-filename-conditions filename
|
(let ((port (with-i/o-filename-conditions filename
|
||||||
(lambda () (open filename O_RDONLY)))))
|
(lambda ()
|
||||||
|
(with-fluids ((%default-port-encoding #f))
|
||||||
|
(open filename O_RDONLY))))))
|
||||||
(cond (maybe-transcoder
|
(cond (maybe-transcoder
|
||||||
(set-port-encoding! port (transcoder-codec maybe-transcoder))))
|
(set-port-encoding! port (transcoder-codec maybe-transcoder))))
|
||||||
port))
|
port))
|
||||||
|
@ -340,7 +342,9 @@ as a string, and a thunk to retrieve the characters associated with that port."
|
||||||
0
|
0
|
||||||
O_EXCL)))
|
O_EXCL)))
|
||||||
(port (with-i/o-filename-conditions filename
|
(port (with-i/o-filename-conditions filename
|
||||||
(lambda () (open filename flags)))))
|
(lambda ()
|
||||||
|
(with-fluids ((%default-port-encoding #f))
|
||||||
|
(open filename flags))))))
|
||||||
(cond (maybe-transcoder
|
(cond (maybe-transcoder
|
||||||
(set-port-encoding! port (transcoder-codec maybe-transcoder))))
|
(set-port-encoding! port (transcoder-codec maybe-transcoder))))
|
||||||
port))
|
port))
|
||||||
|
|
83
module/scripts/list.scm
Normal file
83
module/scripts/list.scm
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
;;; List --- List scripts that can be invoked by guile-tools -*- coding: iso-8859-1 -*-
|
||||||
|
|
||||||
|
;;;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
|
;;;;
|
||||||
|
;;;; This library is free software; you can redistribute it and/or
|
||||||
|
;;;; modify it under the terms of the GNU Lesser General Public
|
||||||
|
;;;; License as published by the Free Software Foundation; either
|
||||||
|
;;;; version 3 of the License, or (at your option) any later version.
|
||||||
|
;;;;
|
||||||
|
;;;; This library is distributed in the hope that it will be useful,
|
||||||
|
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
;;;; Lesser General Public License for more details.
|
||||||
|
;;;;
|
||||||
|
;;;; You should have received a copy of the GNU Lesser General Public
|
||||||
|
;;;; License along with this library; if not, write to the Free
|
||||||
|
;;;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
;;;; Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; Usage: list
|
||||||
|
;;
|
||||||
|
;; List scripts that can be invoked by guile-tools.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(define-module (scripts list)
|
||||||
|
#:use-module ((srfi srfi-1) #:select (fold append-map))
|
||||||
|
#:export (list-scripts))
|
||||||
|
|
||||||
|
|
||||||
|
(define (directory-files dir)
|
||||||
|
(if (and (file-exists? dir) (file-is-directory? dir))
|
||||||
|
(let ((dir-stream (opendir dir)))
|
||||||
|
(let loop ((new (readdir dir-stream))
|
||||||
|
(acc '()))
|
||||||
|
(if (eof-object? new)
|
||||||
|
(begin
|
||||||
|
(closedir dir-stream)
|
||||||
|
acc)
|
||||||
|
(loop (readdir dir-stream)
|
||||||
|
(if (or (string=? "." new) ; ignore
|
||||||
|
(string=? ".." new)) ; ignore
|
||||||
|
acc
|
||||||
|
(cons new acc))))))
|
||||||
|
'()))
|
||||||
|
|
||||||
|
(define (strip-extensions path)
|
||||||
|
(or-map (lambda (ext)
|
||||||
|
(and
|
||||||
|
(string-suffix? ext path)
|
||||||
|
(substring path 0
|
||||||
|
(- (string-length path) (string-length ext)))))
|
||||||
|
(append %load-compiled-extensions %load-extensions)))
|
||||||
|
|
||||||
|
(define (unique l)
|
||||||
|
(cond ((null? l) l)
|
||||||
|
((null? (cdr l)) l)
|
||||||
|
((equal? (car l) (cadr l)) (unique (cdr l)))
|
||||||
|
(else (cons (car l) (unique (cdr l))))))
|
||||||
|
|
||||||
|
(define (find-submodules head)
|
||||||
|
(let ((shead (map symbol->string head)))
|
||||||
|
(unique
|
||||||
|
(sort
|
||||||
|
(append-map (lambda (path)
|
||||||
|
(fold (lambda (x rest)
|
||||||
|
(let ((stripped (strip-extensions x)))
|
||||||
|
(if stripped (cons stripped rest) rest)))
|
||||||
|
'()
|
||||||
|
(directory-files
|
||||||
|
(fold (lambda (x y) (in-vicinity y x)) path shead))))
|
||||||
|
%load-path)
|
||||||
|
string<?))))
|
||||||
|
|
||||||
|
(define (list-scripts . args)
|
||||||
|
(for-each (lambda (x)
|
||||||
|
;; would be nice to show a summary.
|
||||||
|
(format #t "~A\n" x))
|
||||||
|
(find-submodules '(scripts))))
|
||||||
|
|
||||||
|
(define main list-scripts)
|
|
@ -252,7 +252,7 @@
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
(with-test-prefix "multiple occurrances"
|
(with-test-prefix "multiple occurrences"
|
||||||
|
|
||||||
(define (test9 . args)
|
(define (test9 . args)
|
||||||
(equal? (getopt-long (cons "foo" args)
|
(equal? (getopt-long (cons "foo" args)
|
||||||
|
@ -288,4 +288,15 @@
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(with-test-prefix "stop-at-first-non-option"
|
||||||
|
|
||||||
|
(pass-if "guile-tools compile example"
|
||||||
|
(equal? (getopt-long '("guile-tools" "compile" "-Wformat" "eval.scm" "-o" "eval.go")
|
||||||
|
'((help (single-char #\h))
|
||||||
|
(version (single-char #\v)))
|
||||||
|
#:stop-at-first-non-option #t)
|
||||||
|
'((() "compile" "-Wformat" "eval.scm" "-o" "eval.go"))))
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
;;; getopt-long.test ends here
|
;;; getopt-long.test ends here
|
||||||
|
|
|
@ -27,12 +27,6 @@
|
||||||
#:use-module (rnrs exceptions)
|
#:use-module (rnrs exceptions)
|
||||||
#:use-module (rnrs bytevectors))
|
#:use-module (rnrs bytevectors))
|
||||||
|
|
||||||
;;; All these tests assume Guile 1.8's port system, where characters are
|
|
||||||
;;; treated as octets.
|
|
||||||
|
|
||||||
;; Set the default encoding of future ports to be Latin-1.
|
|
||||||
(fluid-set! %default-port-encoding #f)
|
|
||||||
|
|
||||||
(define-syntax pass-if-condition
|
(define-syntax pass-if-condition
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((_ name predicate body0 body ...)
|
((_ name predicate body0 body ...)
|
||||||
|
@ -72,6 +66,12 @@
|
||||||
(lambda () #t)) ;; close-port
|
(lambda () #t)) ;; close-port
|
||||||
"rw")))
|
"rw")))
|
||||||
|
|
||||||
|
(define (call-with-bytevector-output-port/transcoded transcoder receiver)
|
||||||
|
(call-with-bytevector-output-port
|
||||||
|
(lambda (bv-port)
|
||||||
|
(call-with-port (transcoded-port bv-port transcoder)
|
||||||
|
receiver))))
|
||||||
|
|
||||||
|
|
||||||
(with-test-prefix "7.2.5 End-of-File Object"
|
(with-test-prefix "7.2.5 End-of-File Object"
|
||||||
|
|
||||||
|
@ -316,6 +316,22 @@
|
||||||
|
|
||||||
(with-test-prefix "7.2.7 Input Ports"
|
(with-test-prefix "7.2.7 Input Ports"
|
||||||
|
|
||||||
|
(let ((filename (test-file))
|
||||||
|
(contents (string->utf8 "GNU λ")))
|
||||||
|
|
||||||
|
;; Create file
|
||||||
|
(call-with-output-file filename
|
||||||
|
(lambda (port) (put-bytevector port contents)))
|
||||||
|
|
||||||
|
(pass-if "open-file-input-port [opens binary port]"
|
||||||
|
(with-fluids ((%default-port-encoding "UTF-8"))
|
||||||
|
(call-with-port (open-file-input-port filename)
|
||||||
|
(lambda (port)
|
||||||
|
(and (binary-port? port)
|
||||||
|
(bytevector=? contents (get-bytevector-all port)))))))
|
||||||
|
|
||||||
|
(delete-file filename))
|
||||||
|
|
||||||
;; This section appears here so that it can use the binary input
|
;; This section appears here so that it can use the binary input
|
||||||
;; primitives.
|
;; primitives.
|
||||||
|
|
||||||
|
@ -463,11 +479,12 @@
|
||||||
(with-test-prefix "8.2.10 Output ports"
|
(with-test-prefix "8.2.10 Output ports"
|
||||||
|
|
||||||
(let ((filename (test-file)))
|
(let ((filename (test-file)))
|
||||||
(pass-if "open-file-output-port [opens binary port]"
|
(with-fluids ((%default-port-encoding "UTF-8"))
|
||||||
(call-with-port (open-file-output-port filename)
|
(pass-if "open-file-output-port [opens binary port]"
|
||||||
(lambda (port)
|
(call-with-port (open-file-output-port filename)
|
||||||
(put-bytevector port '#vu8(1 2 3))
|
(lambda (port)
|
||||||
(binary-port? port))))
|
(put-bytevector port '#vu8(1 2 3))
|
||||||
|
(binary-port? port)))))
|
||||||
|
|
||||||
(pass-if-condition "open-file-output-port [exception: already-exists]"
|
(pass-if-condition "open-file-output-port [exception: already-exists]"
|
||||||
i/o-file-already-exists-error?
|
i/o-file-already-exists-error?
|
||||||
|
@ -620,11 +637,9 @@
|
||||||
(let ((s "Hello\nÄÖÜ"))
|
(let ((s "Hello\nÄÖÜ"))
|
||||||
(bytevector=?
|
(bytevector=?
|
||||||
(string->utf8 s)
|
(string->utf8 s)
|
||||||
(call-with-bytevector-output-port
|
(call-with-bytevector-output-port/transcoded (make-transcoder (utf-8-codec))
|
||||||
(lambda (bv-port)
|
(lambda (utf8-port)
|
||||||
(call-with-port (transcoded-port bv-port (make-transcoder (utf-8-codec)))
|
(put-string utf8-port s))))))
|
||||||
(lambda (utf8-port)
|
|
||||||
(put-string utf8-port s))))))))
|
|
||||||
|
|
||||||
(pass-if "transcoded-port [input]"
|
(pass-if "transcoded-port [input]"
|
||||||
(let ((s "Hello\nÄÖÜ"))
|
(let ((s "Hello\nÄÖÜ"))
|
||||||
|
@ -720,6 +735,11 @@
|
||||||
(pass-if-condition "get-datum" i/o-read-error?
|
(pass-if-condition "get-datum" i/o-read-error?
|
||||||
(get-datum (make-failing-port)))))
|
(get-datum (make-failing-port)))))
|
||||||
|
|
||||||
|
(define (encoding-error-predicate char)
|
||||||
|
(lambda (c)
|
||||||
|
(and (i/o-encoding-error? c)
|
||||||
|
(char=? char (i/o-encoding-error-char c)))))
|
||||||
|
|
||||||
(with-test-prefix "8.2.12 Textual Output"
|
(with-test-prefix "8.2.12 Textual Output"
|
||||||
|
|
||||||
(with-test-prefix "write error"
|
(with-test-prefix "write error"
|
||||||
|
@ -728,7 +748,22 @@
|
||||||
(pass-if-condition "put-string" i/o-write-error?
|
(pass-if-condition "put-string" i/o-write-error?
|
||||||
(put-string (make-failing-port) "Hello World!"))
|
(put-string (make-failing-port) "Hello World!"))
|
||||||
(pass-if-condition "put-datum" i/o-write-error?
|
(pass-if-condition "put-datum" i/o-write-error?
|
||||||
(put-datum (make-failing-port) '(hello world!)))))
|
(put-datum (make-failing-port) '(hello world!))))
|
||||||
|
(with-test-prefix "encoding error"
|
||||||
|
(pass-if-condition "put-char" (encoding-error-predicate #\λ)
|
||||||
|
(call-with-bytevector-output-port/transcoded
|
||||||
|
(make-transcoder (latin-1-codec)
|
||||||
|
(native-eol-style)
|
||||||
|
(error-handling-mode raise))
|
||||||
|
(lambda (port)
|
||||||
|
(put-char port #\λ))))
|
||||||
|
(pass-if-condition "put-string" (encoding-error-predicate #\λ)
|
||||||
|
(call-with-bytevector-output-port/transcoded
|
||||||
|
(make-transcoder (latin-1-codec)
|
||||||
|
(native-eol-style)
|
||||||
|
(error-handling-mode raise))
|
||||||
|
(lambda (port)
|
||||||
|
(put-string port "FooλBar"))))))
|
||||||
|
|
||||||
(with-test-prefix "8.3 Simple I/O"
|
(with-test-prefix "8.3 Simple I/O"
|
||||||
(with-test-prefix "read error"
|
(with-test-prefix "read error"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue