   This file documents the MIT Scheme system.

   Copyright (C) 1988-2002 Massachusetts Institute of Technology

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
Texts.  A copy of the license is included in the section entitled "GNU
Free Documentation License".

External Representation of Characters
=====================================

   Characters are written using the notation `#\CHARACTER' or
`#\CHARACTER-NAME'.  For example:

     #\a                     ; lowercase letter
     #\A                     ; uppercase letter
     #\(                     ; left parenthesis
     #\space                 ; the space character
     #\newline               ; the newline character

Case is significant in `#\CHARACTER', but not in `#\CHARACTER-NAME'.
If CHARACTER in `#\CHARACTER' is a letter, CHARACTER must be followed
by a delimiter character such as a space or parenthesis.  Characters
written in the `#\' notation are self-evaluating; you don't need to
quote them.

   A character name may include one or more "bucky bit" prefixes to
indicate that the character includes one or more of the keyboard shift
keys Control, Meta, Super, Hyper, or Top (note that the Control bucky
bit prefix is not the same as the ASCII control key).  The bucky bit
prefixes and their meanings are as follows (case is not significant):

     Key             Bucky bit prefix        Bucky bit
     ---             ----------------        ---------

     Meta            M- or Meta-                 1
     Control         C- or Control-              2
     Super           S- or Super-                4
     Hyper           H- or Hyper-                8
     Top             T- or Top-                 16

For example,

     #\c-a                   ; Control-a
     #\meta-b                ; Meta-b
     #\c-s-m-h-a             ; Control-Meta-Super-Hyper-A

   The following CHARACTER-NAMEs are supported, shown here with their
ASCII equivalents:

     Character Name          ASCII Name
     --------------          ----------

     altmode                 ESC
     backnext                US
     backspace               BS
     call                    SUB
     linefeed                LF
     page                    FF
     return                  CR
     rubout                  DEL
     space
     tab                     HT

In addition, `#\newline' is the same as `#\linefeed' (but this may
change in the future, so you should not depend on it).  All of the
standard ASCII names for non-printing characters are supported:

     NUL     SOH     STX     ETX     EOT     ENQ     ACK     BEL
     BS      HT      LF      VT      FF      CR      SO      SI
     DLE     DC1     DC2     DC3     DC4     NAK     SYN     ETB
     CAN     EM      SUB     ESC     FS      GS      RS      US
     DEL

 - procedure: char->name char [slashify?]
     Returns a string corresponding to the printed representation of
     CHAR.  This is the CHARACTER or CHARACTER-NAME component of the
     external representation, combined with the appropriate bucky bit
     prefixes.

          (char->name #\a)                        =>  "a"
          (char->name #\space)                    =>  "Space"
          (char->name #\c-a)                      =>  "C-a"
          (char->name #\control-a)                =>  "C-a"

     SLASHIFY?, if specified and true, says to insert the necessary
     backslash characters in the result so that `read' will parse it
     correctly.  In other words, the following generates the external
     representation of CHAR:

          (string-append "#\\" (char->name CHAR #t))

     If SLASHIFY? is not specified, it defaults to `#f'.

 - procedure: name->char string
     Converts a string that names a character into the character
     specified.  If STRING does not name any character, `name->char'
     signals an error.

          (name->char "a")                        =>  #\a
          (name->char "space")                    =>  #\Space
          (name->char "c-a")                      =>  #\C-a
          (name->char "control-a")                =>  #\C-a

Comparison of Characters
========================

 - procedure: char=? char1 char2
 - procedure: char<? char1 char2
 - procedure: char>? char1 char2
 - procedure: char<=? char1 char2
 - procedure: char>=? char1 char2
 - procedure: char-ci=? char1 char2
 - procedure: char-ci<? char1 char2
 - procedure: char-ci>? char1 char2
 - procedure: char-ci<=? char1 char2
 - procedure: char-ci>=? char1 char2
     Returns `#t' if the specified characters are have the appropriate
     order relationship to one another; otherwise returns `#f'.  The
     `-ci' procedures don't distinguish uppercase and lowercase letters.

     Character ordering follows these rules:

        * The digits are in order; for example, `(char<? #\0 #\9)'
          returns `#t'.

        * The uppercase characters are in order; for example, `(char<?
          #\A #\B)' returns `#t'.

        * The lowercase characters are in order; for example, `(char<?
          #\a #\b)' returns `#t'.

     In addition, MIT Scheme orders those characters that satisfy
     `char-standard?' the same way that ISO-8859-1 does.

     Characters are ordered by first comparing their bucky bits part
     and then their code part.  In particular, characters without bucky
     bits come before characters with bucky bits.

Miscellaneous Character Operations
==================================

 - procedure: char? object
     Returns `#t' if OBJECT is a character; otherwise returns `#f'.

 - procedure: char-upcase char
 - procedure: char-downcase char
     Returns the uppercase or lowercase equivalent of CHAR if CHAR is a
     letter; otherwise returns CHAR.  These procedures return a
     character CHAR2 such that `(char-ci=? CHAR CHAR2)'.

 - procedure: char->digit char [radix]
     If CHAR is a character representing a digit in the given RADIX,
     returns the corresponding integer value.  If you specify RADIX
     (which must be an exact integer between 2 and 36 inclusive), the
     conversion is done in that base, otherwise it is done in base 10.
     If CHAR doesn't represent a digit in base RADIX, `char->digit'
     returns `#f'.

     Note that this procedure is insensitive to the alphabetic case of
     CHAR.

          (char->digit #\8)                       =>  8
          (char->digit #\e 16)                    =>  14
          (char->digit #\e)                       =>  #f

 - procedure: digit->char digit [radix]
     Returns a character that represents DIGIT in the radix given by
     RADIX.  RADIX must be an exact integer between 2 and 36
     (inclusive), and defaults to 10.  DIGIT, which must be an exact
     non-negative integer, should be less than RADIX; if DIGIT is
     greater than or equal to RADIX, `digit->char' returns `#f'.

          (digit->char 8)                         =>  #\8
          (digit->char 14 16)                     =>  #\E

Internal Representation of Characters
=====================================

   An MIT Scheme character consists of a "code" part and a "bucky bits"
part.  The MIT Scheme set of characters can represent more characters
than ASCII can; it includes characters with Super, Hyper, and Top bucky
bits, as well as Control and Meta.  Every ASCII character corresponds
to some MIT Scheme character, but not vice versa.(1)

   MIT Scheme uses a 16-bit character code with 5 bucky bits.  Normally,
Scheme uses the least significant 8 bits of the character code to
contain the ISO-8859-1 representation for the character.  The
representation is expanded in order to allow for the use of UTF-16 in
the future.

 - procedure: make-char code bucky-bits
     Builds a character from CODE and BUCKY-BITS.  Both CODE and
     BUCKY-BITS must be exact non-negative integers in the appropriate
     range.  Use `char-code' and `char-bits' to extract the code and
     bucky bits from the character.  If `0' is specified for
     BUCKY-BITS, `make-char' produces an ordinary character; otherwise,
     the appropriate bits are turned on as follows:

          1               Meta
          2               Control
          4               Super
          8               Hyper
          16              Top

     For example,

          (make-char 97 0)                        =>  #\a
          (make-char 97 1)                        =>  #\M-a
          (make-char 97 2)                        =>  #\C-a
          (make-char 97 3)                        =>  #\C-M-a

 - procedure: char-bits char
     Returns the exact integer representation of CHAR's bucky bits.
     For example,

          (char-bits #\a)                         =>  0
          (char-bits #\m-a)                       =>  1
          (char-bits #\c-a)                       =>  2
          (char-bits #\c-m-a)                     =>  3

 - procedure: char-code char
     Returns the character code of CHAR, an exact integer.  For example,

          (char-code #\a)                         =>  97
          (char-code #\c-a)                       =>  97

 - variable: char-code-limit
 - variable: char-bits-limit
     These variables define the (exclusive) upper limits for the
     character code and bucky bits (respectively).  The character code
     and bucky bits are always exact non-negative integers, and are
     strictly less than the value of their respective limit variable.

 - procedure: char->integer char
 - procedure: integer->char k
     `char->integer' returns the character code representation for
     CHAR.  `integer->char' returns the character whose character code
     representation is K.

     In MIT Scheme, if `(char-ascii? CHAR)' is true, then

          (eqv? (char->ascii CHAR) (char->integer CHAR))

     However, this behavior is not required by the Scheme standard, and
     code that depends on it is not portable to other implementations.

     These procedures implement order isomorphisms between the set of
     characters under the `char<=?' ordering and some subset of the
     integers under the `<=' ordering.  That is, if

          (char<=? a b)  =>  #t    and    (<= x y)  =>  #t

     and `x' and `y' are in the range of `char->integer', then

          (<= (char->integer a)
              (char->integer b))                  =>  #t
          (char<=? (integer->char x)
                   (integer->char y))             =>  #t

     Note: If the argument to `char->integer' or `integer->char' is a
     constant, the compiler will constant-fold the call, replacing it
     with the corresponding result.  This is a very useful way to
     denote unusual character constants or ASCII codes.

 - variable: char-integer-limit
     The range of `char->integer' is defined to be the exact
     non-negative integers that are less than the value of this variable
     (exclusive).

   ---------- Footnotes ----------

   (1) Note that the Control bucky bit is different from the ASCII
control key.  This means that `#\SOH' (ASCII ctrl-A) is different from
`#\C-A'.  In fact, the Control bucky bit is completely orthogonal to
the ASCII control key, making possible such characters as `#\C-SOH'.

ISO-8859-1 Characters
=====================

   MIT Scheme internally uses ISO-8859-1 codes for I/O, and stores
character objects in a fashion that makes it convenient to convert
between ISO-8859-1 codes and characters.  Also, character strings are
implemented as byte vectors whose elements are ISO-8859-1 codes; these
codes are converted to character objects when accessed.  For these
reasons it is sometimes desirable to be able to convert between
ISO-8859-1 codes and characters.

   Not all characters can be represented as ISO-8859-1 codes.  A
character that has an equivalent ISO-8859-1 representation is called an
"ISO-8859-1 character".

   For historical reasons, the procedures that manipulate ISO-8859-1
characters use the word "ASCII" rather than "ISO-8859-1".

 - procedure: char-ascii? char
     Returns the ISO-8859-1 code for CHAR if CHAR has an ISO-8859-1
     representation; otherwise returns `#f'.

     In the current implementation, the characters that satisfy this
     predicate are those in which the bucky bits are turned off, and for
     which the character code is less than 256.

 - procedure: char->ascii char
     Returns the ISO-8859-1 code for CHAR.  An error
     `condition-type:bad-range-argument' is signalled if CHAR doesn't
     have an ISO-8859-1 representation.

 - procedure: ascii->char code
     CODE must be the exact integer representation of an ISO-8859-1
     code.  This procedure returns the character corresponding to CODE.

Character Sets
==============

   MIT Scheme's character-set abstraction is used to represent groups of
characters, such as the letters or digits.  Character sets may contain
only ISO-8859-1 characters; in the future this may be changed to allow
the full range of characters.

   There is no meaningful external representation for character sets;
use `char-set-members' to examine their contents.  There is (at
present) no specific equivalence predicate for character sets; use
`equal?' for this purpose.

 - procedure: char-set? object
     Returns `#t' if OBJECT is a character set; otherwise returns `#f'.

 - variable: char-set:upper-case
 - variable: char-set:lower-case
 - variable: char-set:alphabetic
 - variable: char-set:numeric
 - variable: char-set:alphanumeric
 - variable: char-set:whitespace
 - variable: char-set:not-whitespace
 - variable: char-set:graphic
 - variable: char-set:not-graphic
 - variable: char-set:standard
     These variables contain predefined character sets.  To see the
     contents of one of these sets, use `char-set-members'.

     "Alphabetic" characters are the 52 upper and lower case letters.
     "Numeric" characters are the 10 decimal digits.  "Alphanumeric"
     characters are those in the union of these two sets.  "Whitespace"
     characters are `#\space', `#\tab', `#\page', `#\linefeed', and
     `#\return'.  GRAPHIC characters are the printing characters and
     `#\space'.  STANDARD characters are the printing characters,
     `#\space', and `#\newline'.  These are the printing characters:

          ! " # $ % & ' ( ) * + , - . /
          0 1 2 3 4 5 6 7 8 9
          : ; < = > ? @
          A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
          [ \ ] ^ _ `
          a b c d e f g h i j k l m n o p q r s t u v w x y z
          { | } ~

 - procedure: char-upper-case? char
 - procedure: char-lower-case? char
 - procedure: char-alphabetic? char
 - procedure: char-numeric? char
 - procedure: char-alphanumeric? char
 - procedure: char-whitespace? char
 - procedure: char-graphic? char
 - procedure: char-standard? object
     These predicates are defined in terms of the respective character
     sets defined above.

 - procedure: char-set-members char-set
     Returns a newly allocated list of the characters in CHAR-SET.

 - procedure: char-set-member? char-set char
     Returns `#t' if CHAR is in CHAR-SET; otherwise returns `#f'.

 - procedure: char-set char ...
     Returns a character set consisting of the specified ISO-8859-1
     characters.  With no arguments, `char-set' returns an empty
     character set.

 - procedure: chars->char-set chars
     Returns a character set consisting of CHARS, which must be a list
     of ISO-8859-1 characters.  This is equivalent to `(apply char-set
     CHARS)'.

 - procedure: string->char-set string
     Returns a character set consisting of all the characters that
     occur in STRING.

 - procedure: ascii-range->char-set lower upper
     LOWER and UPPER must be exact non-negative integers representing
     ISO-8859-1 character codes, and LOWER must be less than or equal
     to UPPER.  This procedure creates and returns a new character set
     consisting of the characters whose ISO-8859-1 codes are between
     LOWER (inclusive) and UPPER (exclusive).

     For historical reasons, the name of this procedure refers to
     "ASCII" rather than "ISO-8859-1".

 - procedure: predicate->char-set predicate
     PREDICATE must be a procedure of one argument.
     `predicate->char-set' creates and returns a character set
     consisting of the ISO-8859-1 characters for which PREDICATE is
     true.

 - procedure: char-set-difference char-set1 char-set2
     Returns a character set consisting of the characters that are in
     CHAR-SET1 but aren't in CHAR-SET2.

 - procedure: char-set-intersection char-set ...
     Returns a character set consisting of the characters that are in
     all of the CHAR-SETs.

 - procedure: char-set-union char-set ...
     Returns a character set consisting of the characters that are in at
     least one o the CHAR-SETs.

 - procedure: char-set-invert char-set
     Returns a character set consisting of the ISO-8859-1 characters
     that are not in CHAR-SET.

Unicode
=======

   MIT Scheme provides rudimentary support for Unicode characters.  In
an ideal world, Unicode would be the base character set for MIT Scheme,
but this implementation predates the invention of Unicode.  And
converting an application of this size is a considerable undertaking.
So for the time being, the base character set is ISO-8859-1 and Unicode
support is grafted on.

   This Unicode support was implemented as a part of the XML parser
(see XML Parser) implementation.  XML uses Unicode as its base
character set, and any XML implementation _must_ support Unicode.

   The Unicode implementation consists of two parts: I/O procedures
that read and write UTF-8 characters, and an "alphabet" abstraction,
which is an efficient implementation of sets of Unicode code points
(similar to the `char-set' abstraction).

   The basic unit in a Unicode implementation is the "code point".

 - procedure: unicode-code-point? object
     Returns `#t' if OBJECT is a Unicode code point.  Code points are
     implemented as exact non-negative integers.  Code points are
     further limited, by the Unicode standard, to be strictly less than
     `#x80000000'.

   The next few procedures do I/O on code points.

 - procedure: read-utf8-code-point port
     Reads and returns a UTF-8-encoded code point from PORT.  Returns
     an end-of-file object if there are no more characters available
     from PORT.  Signals an error if the input stream isn't a valid
     UTF-8 encoding.

 - procedure: write-utf8-code-point code-point port
     Writes CODE-POINT to PORT in the UTF-8 encoding.

 - procedure: utf8-string->code-point string
     Reads and returns a UTF-8-encoded code point from STRING.
     Equivalent to

          (read-utf8-code-point (string->input-port STRING))

 - procedure: code-point->utf8-string code-point
     Returns a newly-allocated string containing the UTF-8 encoding of
     CODE-POINT.  Equivalent to

          (with-string-output-port
           (lambda (port)
             (write-utf8-code-point CODE-POINT port)))

   Applications often need to manipulate sets of characters, such as the
set of alphabetic characters or the set of whitespace characters.  The
"alphabet" abstraction provides an efficient implementation of sets of
Unicode code points.

 - procedure: alphabet? object
     Returns `#t' if OBJECT is a Unicode alphabet, otherwise returns
     `#f'.

 - procedure: code-points->alphabet items
     Returns a Unicode alphabet containing the code points described by
     ITEMS.  ITEMS must satisfy `well-formed-code-points-list?'.

 - procedure: alphabet->code-points alphabet
     Returns a well-formed code-points list that describes the code
     points represented by ALPHABET.

 - procedure: well-formed-code-points-list? object
     Returns `#t' if OBJECT is a well-formed code-points list,
     otherwise returns `#f'.  A well-formed code-points list is a
     proper list, each element of which is either a code point or a
     pair of code points.  A pair of code points represents a
     contiguous range of code points.  The CAR of the pair is the lower
     limit, and the CDR is the upper limit.  Both limits are inclusive,
     and the lower limit must be strictly less than the upper limit.

 - procedure: code-point-in-alphabet? code-point alphabet
     Returns `#t' if CODE-POINT is a member of ALPHABET, otherwise
     returns `#f'.

 - procedure: char-in-alphabet? char alphabet
     Returns `#t' if CHAR is a member of ALPHABET, otherwise returns
     `#f'.  Equivalent to

          (code-point-in-alphabet? (char-code CHAR) ALPHABET)

   Character sets and alphabets can be converted to one another,
provided that the alphabet contains only 8-bit code points.  This is
true because 8-bit code points in Unicode map directly to ISO-8859-1
characters, which is what character sets contain.

 - procedure: char-set->alphabet char-set
     Returns a Unicode alphabet containing the code points that
     correspond to characters that are members of CHAR-SET.

 - procedure: alphabet->char-set alphabet
     Returns a character set containing the characters that correspond
     to 8-bit code points that are members of ALPHABET.  (Code points
     outside the 8-bit range are ignored.)

 - procedure: string->alphabet string
     Returns a Unicode alphabet containing the code points
     corresponding to the characters in STRING.  Equivalent to

          (char-set->alphabet (string->char-set STRING))

 - procedure: alphabet->string alphabet
     Returns a newly-allocated string containing the characters
     corresponding to the 8-bit code points in ALPHABET.  (Code points
     outside the 8-bit range are ignored.)

 - procedure: 8-bit-alphabet? alphabet
     Returns `#t' if ALPHABET contains only 8-bit code points,
     otherwise returns `#f'.

 - procedure: alphabet+ alphabet ...
     Returns a Unicode alphabet that contains each code point that is a
     member of any of the ALPHABET arguments.

 - procedure: alphabet- alphabet1 alphabet2
     Returns a Unicode alphabet that contains each code point that is a
     member of ALPHABET1 and is not a member of ALPHABET2.

Strings
*******

   A "string" is a mutable sequence of characters.  In the current
implementation of MIT Scheme, the elements of a string must all satisfy
the predicate `char-ascii?'; if someone ports MIT Scheme to a non-ASCII
operating system this requirement will change.

   A string is written as a sequence of characters enclosed within
double quotes `" "'.  To include a double quote inside a string, precede
the double quote with a backslash `\' (escape it), as in

     "The word \"recursion\" has many meanings."

The printed representation of this string is

     The word "recursion" has many meanings.

To include a backslash inside a string, precede it with another
backslash; for example,

     "Use #\\Control-q to quit."

The printed representation of this string is

     Use #\Control-q to quit.

   The effect of a backslash that doesn't precede a double quote or
backslash is unspecified in standard Scheme, but MIT Scheme specifies
the effect for three other characters: `\t', `\n', and `\f'.  These
escape sequences are respectively translated into the following
characters: `#\tab', `#\newline', and `#\page'.  Finally, a backslash
followed by exactly three octal digits is translated into the character
whose ISO-8859-1 code is those digits.

   If a string literal is continued from one line to another, the string
will contain the newline character (`#\newline') at the line break.
Standard Scheme does not specify what appears in a string literal at a
line break.

   The "length" of a string is the number of characters that it
contains.  This number is an exact non-negative integer that is
established when the string is created (but Variable-Length Strings).
Each character in a string has an "index", which is a
number that indicates the character's position in the string.  The index
of the first (leftmost) character in a string is 0, and the index of the
last character is one less than the length of the string.  The "valid
indexes" of a string are the exact non-negative integers less than the
length of the string.

   A number of the string procedures operate on substrings.  A
"substring" is a segment of a STRING, which is specified by two
integers START and END satisfying these relationships:

     0 <= START <= END <= (string-length STRING)

START is the index of the first character in the substring, and END is
one greater than the index of the last character in the substring.
Thus if START and END are equal, they refer to an empty substring, and
if START is zero and END is the length of STRING, they refer to all of
STRING.

   Some of the procedures that operate on strings ignore the difference
between uppercase and lowercase.  The versions that ignore case include
`-ci' (for "case insensitive") in their names.

Construction of Strings
=======================

 - procedure: make-string k [char]
     Returns a newly allocated string of length K.  If you specify
     CHAR, all elements of the string are initialized to CHAR,
     otherwise the contents of the string are unspecified.  CHAR must
     satisfy the predicate `char-ascii?'.

          (make-string 10 #\x)              =>  "xxxxxxxxxx"

 - procedure: string char ...
     Returns a newly allocated string consisting of the specified
     characters.  The arguments must all satisfy `char-ascii?'.

          (string #\a)                                =>  "a"
          (string #\a #\b #\c)                        =>  "abc"
          (string #\a #\space #\b #\space #\c)        =>  "a b c"
          (string)                                    =>  ""

 - procedure: list->string char-list
     CHAR-LIST must be a list of ISO-8859-1 characters.  `list->string'
     returns a newly allocated string formed from the elements of
     CHAR-LIST.  This is equivalent to `(apply string CHAR-LIST)'.  The
     inverse of this operation is `string->list'.

          (list->string '(#\a #\b))           =>  "ab"
          (string->list "Hello")              =>  (#\H #\e #\l #\l #\o)

 - procedure: string-copy string
     Returns a newly allocated copy of STRING.

     Note regarding variable-length strings: the maximum length of the
     result depends only on the length of STRING, not its maximum
     length.  If you wish to copy a string and preserve its maximum
     length, do the following:

          (define (string-copy-preserving-max-length string)
            (let ((length))
              (dynamic-wind
               (lambda ()
                 (set! length (string-length string))
                 (set-string-length! string
                                     (string-maximum-length string)))
               (lambda ()
                 (string-copy string))
               (lambda ()
                 (set-string-length! string length)))))

Selecting String Components
===========================

 - procedure: string? object
     Returns `#t' if OBJECT is a string; otherwise returns `#f'.

          (string? "Hi")                  =>  #t
          (string? 'Hi)                   =>  #f

 - procedure: string-length string
     Returns the length of STRING as an exact non-negative integer.

          (string-length "")              =>  0
          (string-length "The length")    =>  10

 - procedure: string-null? string
     Returns `#t' if STRING has zero length; otherwise returns `#f'.

          (string-null? "")               =>  #t
          (string-null? "Hi")             =>  #f

 - procedure: string-ref string k
     Returns character K of STRING.  K must be a valid index of STRING.

          (string-ref "Hello" 1)          =>  #\e
          (string-ref "Hello" 5)          error--> 5 not in correct range

 - procedure: string-set! string k char
     Stores CHAR in element K of STRING and returns an unspecified
     value.  K must be a valid index of STRING, and CHAR must satisfy
     the predicate `char-ascii?'.

          (define str "Dog")              =>  unspecified
          (string-set! str 0 #\L)         =>  unspecified
          str                             =>  "Log"
          (string-set! str 3 #\t)         error--> 3 not in correct range

Comparison of Strings
=====================

 - procedure: string=? string1 string2
 - procedure: substring=? string1 start end string2 start end
 - procedure: string-ci=? string1 string2
 - procedure: substring-ci=? string1 start end string2 start end
     Returns `#t' if the two strings (substrings) are the same length
     and contain the same characters in the same (relative) positions;
     otherwise returns `#f'.  `string-ci=?' and `substring-ci=?' don't
     distinguish uppercase and lowercase letters, but `string=?' and
     `substring=?' do.

          (string=? "PIE" "PIE")                  =>  #t
          (string=? "PIE" "pie")                  =>  #f
          (string-ci=? "PIE" "pie")               =>  #t
          (substring=? "Alamo" 1 3 "cola" 2 4)    =>  #t ; compares "la"

 - procedure: string<? string1 string2
 - procedure: substring<? string1 start1 end1 string2 start2 end2
 - procedure: string>? string1 string2
 - procedure: string<=? string1 string2
 - procedure: string>=? string1 string2
 - procedure: string-ci<? string1 string2
 - procedure: substring-ci<? string1 start1 end1 string2 start2 end2
 - procedure: string-ci>? string1 string2
 - procedure: string-ci<=? string1 string2
 - procedure: string-ci>=? string1 string2
     These procedures compare strings (substrings) according to the
     order of the characters they contain (also Comparison of Characters).
     The arguments are compared using a lexicographic
     (or dictionary) order.  If two strings differ in length but are
     the same up to the length of the shorter string, the shorter
     string is considered to be less than the longer string.

          (string<? "cat" "dog")          =>  #t
          (string<? "cat" "DOG")          =>  #f
          (string-ci<? "cat" "DOG")       =>  #t
          (string>? "catkin" "cat")       =>  #t ; shorter is lesser

 - procedure: string-compare string1 string2 if-eq if-lt if-gt
 - procedure: string-compare-ci string1 string2 if-eq if-lt if-gt
     IF-EQ, IF-LT, and IF-GT are procedures of no arguments (thunks).
     The two strings are compared; if they are equal, IF-EQ is applied,
     if STRING1 is less than STRING2, IF-LT is applied, else if STRING1
     is greater than STRING2, IF-GT is applied.  The value of the
     procedure is the value of the thunk that is applied.

     `string-compare' distinguishes uppercase and lowercase letters;
     `string-compare-ci' does not.

          (define (cheer) (display "Hooray!"))
          (define (boo)   (display "Boo-hiss!"))
          (string-compare "a" "b"  cheer  (lambda() 'ignore)  boo)
                  -|  Hooray!
                  =>  unspecified

 - procedure: string-hash string
 - procedure: string-hash-mod string k
     `string-hash' returns an exact non-negative integer that can be
     used for storing the specified STRING in a hash table.  Equal
     strings (in the sense of `string=?') return equal (`=') hash codes,
     and non-equal but similar strings are usually mapped to distinct
     hash codes.

     `string-hash-mod' is like `string-hash', except that it limits the
     result to a particular range based on the exact non-negative
     integer K.  The following are equivalent:

          (string-hash-mod STRING K)
          (modulo (string-hash STRING) K)

Alphabetic Case in Strings
==========================

 - procedure: string-capitalized? string
 - procedure: substring-capitalized? string start end
     These procedures return `#t' if the first word in the string
     (substring) is capitalized, and any subsequent words are either
     lower case or capitalized.  Otherwise, they return `#f'.  A word is
     defined as a non-null contiguous sequence of alphabetic characters,
     delimited by non-alphabetic characters or the limits of the string
     (substring).  A word is capitalized if its first letter is upper
     case and all its remaining letters are lower case.

          (map string-capitalized? '(""    "A"    "art"  "Art"  "ART"))
                                 => (#f    #t     #f     #t     #f)

 - procedure: string-upper-case? string
 - procedure: substring-upper-case? string start end
 - procedure: string-lower-case? string
 - procedure: substring-lower-case? string start end
     These procedures return `#t' if all the letters in the string
     (substring) are of the correct case, otherwise they return `#f'.
     The string (substring) must contain at least one letter or the
     procedures return `#f'.

          (map string-upper-case?  '(""    "A"    "art"  "Art"  "ART"))
                                 => (#f    #t     #f     #f     #t)

 - procedure: string-capitalize string
 - procedure: string-capitalize! string
 - procedure: substring-capitalize! string start end
     `string-capitalize' returns a newly allocated copy of STRING in
     which the first alphabetic character is uppercase and the remaining
     alphabetic characters are lowercase.  For example, `"abcDEF"'
     becomes `"Abcdef"'.  `string-capitalize!' is the destructive
     version of `string-capitalize': it alters STRING and returns an
     unspecified value.  `substring-capitalize!' destructively
     capitalizes the specified part of STRING.

 - procedure: string-downcase string
 - procedure: string-downcase! string
 - procedure: substring-downcase! string start end
     `string-downcase' returns a newly allocated copy of STRING in
     which all uppercase letters are changed to lowercase.
     `string-downcase!' is the destructive version of
     `string-downcase': it alters STRING and returns an unspecified
     value.  `substring-downcase!' destructively changes the case of
     the specified part of STRING.

          (define str "ABCDEFG")          =>  unspecified
          (substring-downcase! str 3 5)   =>  unspecified
          str                             =>  "ABCdeFG"

 - procedure: string-upcase string
 - procedure: string-upcase! string
 - procedure: substring-upcase! string start end
     `string-upcase' returns a newly allocated copy of STRING in which
     all lowercase letters are changed to uppercase.  `string-upcase!'
     is the destructive version of `string-upcase': it alters STRING
     and returns an unspecified value.  `substring-upcase!'
     destructively changes the case of the specified part of STRING.

Cutting and Pasting Strings
===========================

 - procedure: string-append string ...
     Returns a newly allocated string made from the concatenation of
     the given strings.  With no arguments, `string-append' returns the
     empty string (`""').

          (string-append)                         =>  ""
          (string-append "*" "ace" "*")           =>  "*ace*"
          (string-append "" "" "")                =>  ""
          (eq? str (string-append str))           =>  #f ; newly allocated

 - procedure: substring string start end
     Returns a newly allocated string formed from the characters of
     STRING beginning with index START (inclusive) and ending with END
     (exclusive).

          (substring "" 0 0)              => ""
          (substring "arduous" 2 5)       => "duo"
          (substring "arduous" 2 8)       error--> 8 not in correct range

          (define (string-copy s)
            (substring s 0 (string-length s)))

 - procedure: string-head string end
     Returns a newly allocated copy of the initial substring of STRING,
     up to but excluding END.  It could have been defined by:

          (define (string-head string end)
            (substring string 0 end))

 - procedure: string-tail string start
     Returns a newly allocated copy of the final substring of STRING,
     starting at index START and going to the end of STRING.  It could
     have been defined by:

          (define (string-tail string start)
            (substring string start (string-length string)))

          (string-tail "uncommon" 2)      =>  "common"

 - procedure: string-pad-left string k [char]
 - procedure: string-pad-right string k [char]
     These procedures return a newly allocated string created by padding
     STRING out to length K, using CHAR.  If CHAR is not given, it
     defaults to `#\space'.  If K is less than the length of STRING,
     the resulting string is a truncated form of STRING.
     `string-pad-left' adds padding characters or truncates from the
     beginning of the string (lowest indices), while `string-pad-right'
     does so at the end of the string (highest indices).

          (string-pad-left "hello" 4)             =>  "ello"
          (string-pad-left "hello" 8)             =>  "   hello"
          (string-pad-left "hello" 8 #\*)         =>  "***hello"
          (string-pad-right "hello" 4)            =>  "hell"
          (string-pad-right "hello" 8)            =>  "hello   "

 - procedure: string-trim string [char-set]
 - procedure: string-trim-left string [char-set]
 - procedure: string-trim-right string [char-set]
     Returns a newly allocated string created by removing all
     characters that are not in CHAR-SET from: (`string-trim') both
     ends of STRING; (`string-trim-left') the beginning of STRING; or
     (`string-trim-right') the end of STRING.  CHAR-SET defaults to
     `char-set:not-whitespace'.

          (string-trim "  in the end  ")          =>  "in the end"
          (string-trim "              ")          =>  ""
          (string-trim "100th" char-set:numeric)  =>  "100"
          (string-trim-left "-.-+-=-" (char-set #\+))
                                                  =>  "+-=-"
          (string-trim "but (+ x y) is" (char-set #\( #\)))
                                                  =>  "(+ x y)"

Searching Strings
=================

   The first few procedures in this section perform "string search", in
which a given string (the "text") is searched to see if it contains
another given string (the "pattern") as a proper substring.  At present
these procedures are implemented using a hybrid strategy.  For short
patterns of less than 4 characters, the naive string-search algorithm
is used.  For longer patterns, the Boyer-Moore string-search algorithm
is used.

 - procedure: string-search-forward pattern string
 - procedure: substring-search-forward pattern string start end
     PATTERN must be a string.  Searches STRING for the leftmost
     occurrence of the substring PATTERN.  If successful, the index of
     the first character of the matched substring is returned;
     otherwise, `#f' is returned.

     `substring-search-forward' limits its search to the specified
     substring of STRING; `string-search-forward' searches all of
     STRING.

          (string-search-forward "rat" "pirate")
              => 2
          (string-search-forward "rat" "pirate rating")
              => 2
          (substring-search-forward "rat" "pirate rating" 4 13)
              => 7
          (substring-search-forward "rat" "pirate rating" 9 13)
              => #f

 - procedure: string-search-backward pattern string
 - procedure: substring-search-backward pattern string start end
     PATTERN must be a string.  Searches STRING for the rightmost
     occurrence of the substring PATTERN.  If successful, the index to
     the right of the last character of the matched substring is
     returned; otherwise, `#f' is returned.

     `substring-search-backward' limits its search to the specified
     substring of STRING; `string-search-backward' searches all of
     STRING.

          (string-search-backward "rat" "pirate")
              => 5
          (string-search-backward "rat" "pirate rating")
              => 10
          (substring-search-backward "rat" "pirate rating" 1 8)
              => 5
          (substring-search-backward "rat" "pirate rating" 9 13)
              => #f

 - procedure: string-search-all pattern string
 - procedure: substring-search-all pattern string start end
     PATTERN must be a string.  Searches STRING to find all occurrences
     of the substring PATTERN.  Returns a list of the occurrences; each
     element of the list is an index pointing to the first character of
     an occurrence.

     `substring-search-all' limits its search to the specified substring
     of STRING; `string-search-all' searches all of STRING.

          (string-search-all "rat" "pirate")
              => (2)
          (string-search-all "rat" "pirate rating")
              => (2 7)
          (substring-search-all "rat" "pirate rating" 4 13)
              => (7)
          (substring-search-all "rat" "pirate rating" 9 13)
              => ()

 - procedure: substring? pattern string
     PATTERN must be a string.  Searches STRING to see if it contains
     the substring PATTERN.  Returns `#t' if PATTERN is a substring of
     STRING, otherwise returns `#f'.

          (substring? "rat" "pirate")             =>  #t
          (substring? "rat" "outrage")            =>  #f
          (substring? "" any-string)              =>  #t
          (if (substring? "moon" text)
              (process-lunar text)
              'no-moon)

 - procedure: string-find-next-char string char
 - procedure: substring-find-next-char string start end char
 - procedure: string-find-next-char-ci string char
 - procedure: substring-find-next-char-ci string start end char
     Returns the index of the first occurrence of CHAR in the string
     (substring); returns `#f' if CHAR does not appear in the string.
     For the substring procedures, the index returned is relative to
     the entire string, not just the substring.  The `-ci' procedures
     don't distinguish uppercase and lowercase letters.

          (string-find-next-char "Adam" #\A)              =>  0
          (substring-find-next-char "Adam" 1 4 #\A)       =>  #f
          (substring-find-next-char-ci "Adam" 1 4 #\A)    =>  2

 - procedure: string-find-next-char-in-set string char-set
 - procedure: substring-find-next-char-in-set string start end char-set
     Returns the index of the first character in the string (or
     substring) that is also in CHAR-SET, or returns `#f' if none of the
     characters in CHAR-SET occur in STRING.  For the substring
     procedure, only the substring is searched, but the index returned
     is relative to the entire string, not just the substring.

          (string-find-next-char-in-set my-string char-set:alphabetic)
              =>  start position of the first word in my-string
          ; Can be used as a predicate:
          (if (string-find-next-char-in-set my-string
                                            (char-set #\( #\) ))
              'contains-parentheses
              'no-parentheses)

 - procedure: string-find-previous-char string char
 - procedure: substring-find-previous-char string start end char
 - procedure: string-find-previous-char-ci string char
 - procedure: substring-find-previous-char-ci string start end char
     Returns the index of the last occurrence of CHAR in the string
     (substring); returns `#f' if CHAR doesn't appear in the string.
     For the substring procedures, the index returned is relative to
     the entire string, not just the substring.  The `-ci' procedures
     don't distinguish uppercase and lowercase letters.

 - procedure: string-find-previous-char-in-set string char-set
 - procedure: substring-find-previous-char-in-set string start end
          char-set
     Returns the index of the last character in the string (substring)
     that is also in CHAR-SET.  For the substring procedure, the index
     returned is relative to the entire string, not just the substring.

Matching Strings
================

 - procedure: string-match-forward string1 string2
 - procedure: substring-match-forward string1 start end string2 start
          end
 - procedure: string-match-forward-ci string1 string2
 - procedure: substring-match-forward-ci string1 start end string2
          start end
     Compares the two strings (substrings), starting from the
     beginning, and returns the number of characters that are the same.
     If the two strings (substrings) start differently, returns 0.
     The `-ci' procedures don't distinguish uppercase and lowercase
     letters.

          (string-match-forward "mirror" "micro") =>  2  ; matches "mi"
          (string-match-forward "a" "b")          =>  0  ; no match

 - procedure: string-match-backward string1 string2
 - procedure: substring-match-backward string1 start end string2 start
          end
 - procedure: string-match-backward-ci string1 string2
 - procedure: substring-match-backward-ci string1 start end string2
          start end
     Compares the two strings (substrings), starting from the end and
     matching toward the front, returning the number of characters that
     are the same.  If the two strings (substrings) end differently,
     returns 0.  The `-ci' procedures don't distinguish uppercase and
     lowercase letters.

          (string-match-backward-ci "BULBOUS" "fractious")
                                                  =>  3  ; matches "ous"

 - procedure: string-prefix? string1 string2
 - procedure: substring-prefix? string1 start1 end1 string2 start2 end2
 - procedure: string-prefix-ci? string1 string2
 - procedure: substring-prefix-ci? string1 start1 end1 string2 start2
          end2
     These procedures return `#t' if the first string (substring) forms
     the prefix of the second; otherwise returns `#f'.  The `-ci'
     procedures don't distinguish uppercase and lowercase letters.

          (string-prefix? "abc" "abcdef")         =>  #t
          (string-prefix? "" any-string)          =>  #t

 - procedure: string-suffix? string1 string2
 - procedure: substring-suffix? string1 start1 end1 string2 start2 end2
 - procedure: string-suffix-ci? string1 string2
 - procedure: substring-suffix-ci? string1 start1 end1 string2 start2
          end2
     These procedures return `#t' if the first string (substring) forms
     the suffix of the second; otherwise returns `#f'.  The `-ci'
     procedures don't distinguish uppercase and lowercase letters.

          (string-suffix? "ous" "bulbous")        =>  #t
          (string-suffix? "" any-string)          =>  #t

Regular Expressions
===================

   MIT Scheme provides support for using regular expressions to search
and match strings.  This manual does not define regular expressions;
instead see Syntax of Regular Expressions (emacs).

   In addition to providing standard regular-expression support, MIT
Scheme also provides the REXP abstraction.  This is an alternative way
to write regular expressions that is easier to read and understand than
the standard notation.  Regular expressions written in this notation
can be translated into the standard notation.

   The regular-expression support is a run-time-loadable option.  To use
it, execute

     (load-option 'regular-expression)

once before calling any of the procedures defined here.