1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 19:50:24 +02:00

Implement #!fold-case and #!no-fold-case reader directives.

* libguile/read.c (set_port_case_insensitive_p): New function.

  (scm_read_shebang): Handle #!fold-case and #!no-fold-case.

* doc/ref/api-evaluation.texi (Case Sensitivity, Scheme Read): Document
  the #!fold-case and #!no-fold-case reader directives.

* test-suite/tests/reader.test ("per-port-read-options"): Add tests.
This commit is contained in:
Mark H Weaver 2012-10-24 14:37:36 -04:00
parent ea8c976155
commit 9331ffd891
3 changed files with 44 additions and 7 deletions

View file

@ -254,6 +254,8 @@ Encoding of Source Files}.
@node Case Sensitivity @node Case Sensitivity
@subsubsection Case Sensitivity @subsubsection Case Sensitivity
@cindex fold-case
@cindex no-fold-case
@c FIXME::martin: Review me! @c FIXME::martin: Review me!
@ -275,9 +277,9 @@ options, @xref{Scheme Read}.
(read-enable 'case-insensitive) (read-enable 'case-insensitive)
@end lisp @end lisp
Note that this is seldom a problem, because Scheme programmers tend not It is also possible to disable (or enable) case sensitivity within a
to use uppercase letters in their identifiers anyway. single file by placing the reader directives @code{#!fold-case} (or
@code{#!no-fold-case}) within the file itself.
@node Keyword Syntax @node Keyword Syntax
@subsubsection Keyword Syntax @subsubsection Keyword Syntax
@ -315,10 +317,10 @@ its read options.
@cindex options - read @cindex options - read
@cindex read options @cindex read options
@deffn {Scheme Procedure} read-options [setting] @deffn {Scheme Procedure} read-options [setting]
Display the current settings of the read options. If @var{setting} is Display the current settings of the global read options. If
omitted, only a short form of the current read options is printed. @var{setting} is omitted, only a short form of the current read options
Otherwise if @var{setting} is the symbol @code{help}, a complete options is printed. Otherwise if @var{setting} is the symbol @code{help}, a
description is displayed. complete options description is displayed.
@end deffn @end deffn
The set of available options, and their default values, may be had by The set of available options, and their default values, may be had by
@ -338,6 +340,12 @@ hungry-eol-escapes no In strings, consume leading whitespace after an
escaped end-of-line. escaped end-of-line.
@end smalllisp @end smalllisp
Note that Guile also includes a preliminary mechanism for setting read
options on a per-port basis. For instance, the @code{case-insensitive}
read option is set (or unset) on the port when the reader encounters the
@code{#!fold-case} or @code{#!no-fold-case} reader directives. There is
currently no other way to access or set the per-port read options.
The boolean options may be toggled with @code{read-enable} and The boolean options may be toggled with @code{read-enable} and
@code{read-disable}. The non-boolean @code{keywords} option must be set @code{read-disable}. The non-boolean @code{keywords} option must be set
using @code{read-set!}. using @code{read-set!}.

View file

@ -1279,6 +1279,9 @@ scm_read_scsh_block_comment (scm_t_wchar chr, SCM port)
return SCM_UNSPECIFIED; return SCM_UNSPECIFIED;
} }
static void set_port_case_insensitive_p (SCM port, scm_t_read_opts *opts,
int value);
static SCM static SCM
scm_read_shebang (scm_t_wchar chr, SCM port, scm_t_read_opts *opts) scm_read_shebang (scm_t_wchar chr, SCM port, scm_t_read_opts *opts)
{ {
@ -1300,6 +1303,10 @@ scm_read_shebang (scm_t_wchar chr, SCM port, scm_t_read_opts *opts)
name[i] = '\0'; name[i] = '\0';
if (0 == strcmp ("r6rs", name)) if (0 == strcmp ("r6rs", name))
; /* Silently ignore */ ; /* Silently ignore */
else if (0 == strcmp ("fold-case", name))
set_port_case_insensitive_p (port, opts, 1);
else if (0 == strcmp ("no-fold-case", name))
set_port_case_insensitive_p (port, opts, 0);
else else
break; break;
@ -2004,6 +2011,15 @@ set_port_read_option (SCM port, int option, int new_value)
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex); scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
} }
/* Set OPTS and PORT's case-insensitivity according to VALUE. */
static void
set_port_case_insensitive_p (SCM port, scm_t_read_opts *opts, int value)
{
value = !!value;
opts->case_insensitive_p = value;
set_port_read_option (port, READ_OPTION_CASE_INSENSITIVE_P, value);
}
/* Initialize OPTS based on PORT's read options and the global read /* Initialize OPTS based on PORT's read options and the global read
options. */ options. */
static void static void

View file

@ -401,6 +401,19 @@
(lambda () (lambda ()
(read-disable 'hungry-eol-escapes)))))) (read-disable 'hungry-eol-escapes))))))
(with-test-prefix "per-port-read-options"
(pass-if "case-sensitive"
(equal? '(guile GuiLe gUIle)
(with-read-options '(case-insensitive)
(lambda ()
(with-input-from-string "GUIle #!no-fold-case GuiLe gUIle"
(lambda ()
(list (read) (read) (read))))))))
(pass-if "case-insensitive"
(equal? '(GUIle guile guile)
(with-input-from-string "GUIle #!fold-case GuiLe gUIle"
(lambda ()
(list (read) (read) (read)))))))
(with-test-prefix "#;" (with-test-prefix "#;"
(for-each (for-each