@menu
* Introduction to string processing::
* Functions and Variables for input and output::
* Functions and Variables for characters::
* Functions and Variables for strings::
@end menu

@node Introduction to string processing, Functions and Variables for input and output, stringproc, stringproc
@section Introduction to string processing

@code{stringproc.lisp} enlarges Maximas capabilities of working with strings 
and adds some useful functions for file in/output.

For questions and bugs please mail to volkervannek at gmail dot com .

In Maxima a string is easily constructed by typing "text".
@code{stringp} tests for strings.

@c ===beg===
@c m: "text";
@c stringp(m);
@c ===end===
@example
(%i1) m: "text";
(%o1)                         text
(%i2) stringp(m);
(%o2)                         true
@end example

Characters are represented as strings of length 1.
These are not Lisp characters.
Tests can be done with @code{charp} (respectively @code{lcharp}
and conversion from Lisp to Maxima characters with @code{cunlisp}).


@c ===beg===
@c c: "e";
@c [charp(c),lcharp(c)];
@c supcase(c);
@c charp(%);
@c ===end===
@example
(%i1) c: "e";
(%o1)                           e
(%i2) [charp(c),lcharp(c)];
(%o2)                     [true, false]
(%i3) supcase(c);
(%o3)                           E
(%i4) charp(%);
(%o4)                         true
@end example

All functions in @code{stringproc.lisp} that return characters, return Maxima-characters.
Due to the fact, that the introduced characters are strings of length 1,
you can use a lot of string functions also for characters.
As seen, @code{supcase} is one example.

It is important to know,
that the first character in a Maxima-string is at position 1.
This is designed due to the fact that the first element in a Maxima-list is at position 1 too.
See definitions of @code{charat} and @code{charlist} for examples.

In applications string-functions are often used when working with files.
You will find some useful stream- and print-functions in @code{stringproc.lisp}.
The following example shows some of the here introduced functions at work.

Example: 

@code{openw} returns an output stream to a file, @code{printf} then allows formatted writing 
to this file. See @code{printf} for details.

@example
(%i1) s: openw("E:/file.txt");
(%o1)                    #<output stream E:/file.txt>
(%i2) for n:0 thru 10 do printf( s, "~d ", fib(n) );
(%o2)                                done
(%i3) printf( s, "~%~d ~f ~a ~a ~f ~e ~a~%", 
              42,1.234,sqrt(2),%pi,1.0e-2,1.0e-2,1.0b-2 );
(%o3)                                false
(%i4) close(s);
(%o4)                                true
@end example

After closing the stream you can open it again, this time with input direction. 
@code{readline} returns the entire line as one string. The @code{stringproc} package 
now offers a lot of functions for manipulating strings. Tokenizing can be done by 
@code{split} or @code{tokens}.

@example
(%i5) s: openr("E:/file.txt");
(%o5)                     #<input stream E:/file.txt>
(%i6) readline(s);
(%o6)                     0 1 1 2 3 5 8 13 21 34 55 
(%i7) line: readline(s);
(%o7)               42 1.234 sqrt(2) %pi 0.01 1.0E-2 1.0b-2
(%i8) list: tokens(line);
(%o8)           [42, 1.234, sqrt(2), %pi, 0.01, 1.0E-2, 1.0b-2]
(%i9) map( parse_string, list );
(%o9)            [42, 1.234, sqrt(2), %pi, 0.01, 0.01, 1.0b-2]
(%i10) float(%);
(%o10) [42.0, 1.234, 1.414213562373095, 3.141592653589793, 0.01,
                                                     0.01, 0.01]
(%i11) readline(s);
(%o11)                               false
(%i12) close(s)$
@end example

@code{readline} returns @code{false} when the end of file occurs.

@opencatbox
@category{Strings} @category{Share packages} @category{Package stringproc}
@closecatbox


@node Functions and Variables for input and output, Functions and Variables for characters, Introduction to string processing, stringproc
@section Functions and Variables for input and output

Example: 

@c ===beg===
@c s: openw("E:/file.txt");
@c control: 
@c  "~2tAn atom: ~20t~a~%~2tand a list: ~20t~@{~r ~@}~%~2tand an integer: ~20t~d~%"$
@c printf( s,control, 'true,[1,2,3],42 )$
@c close(s);
@c s: openr("E:/file.txt");
@c while stringp( tmp:readline(s) ) do print(tmp)$
@c close(s)$
@c ===end===
@example
(%i1) s: openw("E:/file.txt");
(%o1)                     #<output stream E:/file.txt>
(%i2) control: 
"~2tAn atom: ~20t~a~%~2tand a list: ~20t~@{~r ~@}~%~2t\
and an integer: ~20t~d~%"$
(%i3) printf( s,control, 'true,[1,2,3],42 )$
(%o3)                                false
(%i4) close(s);
(%o4)                                true
(%i5) s: openr("E:/file.txt");
(%o5)                     #<input stream E:/file.txt>
(%i6) while stringp( tmp:readline(s) ) do print(tmp)$
  An atom:          true 
  and a list:       one two three  
  and an integer:   42 
(%i7) close(s)$
@end example

@deffn {Function} close (@var{stream}) 
Closes @var{stream} and returns @code{true} if @var{stream} had been open. 

@opencatbox
@category{File input} @category{File output} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} flength (@var{stream})
Returns the number of elements in @var{stream}
where @var{stream} has to be a stream from or to a file. 

@opencatbox
@category{File input} @category{File output} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} fposition (@var{stream})
@deffnx {Function} fposition (@var{stream}, @var{pos})

Returns the current position in @var{stream}, if @var{pos} is not used. 
If @var{pos} is used, @code{fposition} sets the position in @var{stream}.
@var{stream} has to be a stream from or to a file and 
@var{pos} has to be a positive number where the first element in @var{stream} 
is in position 1.

@opencatbox
@category{File input} @category{File output} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} freshline () 
@deffnx {Function} freshline (@var{stream}) 
Writes a new line (to @var{stream}),
if the position is not at the beginning of a line.
See also @code{newline}.

@opencatbox
@category{File output} @category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@anchor{get_output_stream_string}
@deffn {Function} get_output_stream_string (@var{stream})

Returns a string containing all the characters currently present in 
@var{stream} which must be an open string-output stream. 
The returned characters are removed from @var{stream}.

Example: See @ref{make_string_output_stream} .

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@anchor{make_string_input_stream}
@deffn {Function} make_string_input_stream (@var{string})
@deffnx {Function} make_string_input_stream (@var{string}, @var{start})
@deffnx {Function} make_string_input_stream (@var{string}, @var{start}, @var{end})

Returns an input stream which contains parts of @var{string} and an end of file. 
Without optional arguments the stream contains the entire string 
and is positioned in front of the first character. 
@var{start} and @var{end} define the substring contained in the stream. 
The first character is available at position 1.
 
@example
(%i1) istream : make_string_input_stream("text", 1, 4);
(%o1)              #<string-input stream from "text">
(%i2) (while (c : readchar(istream)) # false do sprint(c), newline())$
t e x 
(%i3) close(istream)$
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@anchor{make_string_output_stream}
@deffn {Function} make_string_output_stream ()

Returns an output stream that accepts characters. Characters currently present 
in this stream can be retrieved by @ref{get_output_stream_string}.
 
@example
(%i1) ostream : make_string_output_stream();
(%o1)               #<string-output stream 09622ea0>
(%i2) printf(ostream, "foo")$

(%i3) printf(ostream, "bar")$

(%i4) string : get_output_stream_string(ostream);
(%o4)                            foobar
(%i5) printf(ostream, "baz")$

(%i6) string : get_output_stream_string(ostream);
(%o6)                              baz
(%i7) close(ostream)$
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@deffn {Function} newline () 
@deffnx {Function} newline (@var{stream}) 
Writes a new line (to @var{stream}).
See @code{sprint} for an example of using @code{newline()}.
Note that there are some cases, where @code{newline()} does not work as expected. 

@opencatbox
@category{File output} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} opena (@var{file}) 
Returns an output stream to @var{file}.
If an existing file is opened, @code{opena} appends elements at the end of file.

@opencatbox
@category{File output} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} openr (@var{file}) 
Returns an input stream to @var{file}.
If @var{file} does not exist, it will be created.

@opencatbox
@category{File input} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} openw (@var{file}) 
Returns an output stream to @var{file}.
If @var{file} does not exist, it will be created.
If an existing file is opened, @code{openw} destructively modifies @var{file}.

@opencatbox
@category{File output} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} printf (@var{dest}, @var{string})
@deffnx {Function} printf (@var{dest}, @var{string}, @var{expr_1}, ..., @var{expr_n})

Produces formatted output by outputting the characters of control-string 
@var{string} and observing that a tilde introduces a directive.
The character after the tilde, possibly preceded by prefix parameters 
and modifiers, specifies what kind of formatting is desired.
Most directives use one or more elements of the arguments 
@var{expr_1}, ..., @var{expr_n} to create their output.

If @var{dest} is a stream or @code{true}, then @code{printf} returns @code{false}.
Otherwise, @code{printf} returns a string containing the output.

@code{printf} provides the Common Lisp function @code{format} in Maxima. 
The following example illustrates the general relation between these two 
functions.

@example
(%i1) printf(true, "R~dD~d~%", 2, 2);
R2D2
(%o1)                                false
(%i2) :lisp (format t "R~dD~d~%" 2 2)
R2D2
NIL
@end example

The following description is limited to a rough sketch of the possibilities of 
@code{printf}.
The Lisp function @code{format} is described in detail in many reference books. 
Of good help is e.g. the free available online-manual 
"Common Lisp the Language" by Guy L. Steele. See chapter 22.3.3 there. 

@example
   ~%       new line
   ~&       fresh line
   ~t       tab
   ~$       monetary
   ~d       decimal integer
   ~b       binary integer
   ~o       octal integer
   ~x       hexadecimal integer
   ~br      base-b integer
   ~r       spell an integer
   ~p       plural
   ~f       floating point
   ~e       scientific notation
   ~g       ~f or ~e, depending upon magnitude
   ~h       bigfloat
   ~a       uses Maxima function string
   ~s       like ~a, but output enclosed in "double quotes"
   ~~       ~
   ~<       justification, ~> terminates
   ~(       case conversion, ~) terminates 
   ~[       selection, ~] terminates 
   ~@{       iteration, ~@} terminates
@end example

The directive ~h for bigfloat is no Lisp-standard and is therefore illustrated below. 

Note that the directive ~* is not supported.

If @var{dest} is a stream or @code{true}, then @code{printf} returns @code{false}.
Otherwise, @code{printf} returns a string containing the output.

@c ===beg===
@c printf( false, "~a ~a ~4f ~a ~@@r", 
@c         "String",sym,bound,sqrt(12),144), bound = 1.234;
@c printf( false,"~@{~a ~@}",["one",2,"THREE"] );
@c printf( true,"~@{~@{~9,1f ~@}~%~@}",mat ),
@c         mat = args( matrix([1.1,2,3.33],[4,5,6],[7,8.88,9]) )$
@c control: "~:(~r~) bird~p ~[is~;are~] singing."$
@c printf( false,control, n,n,if n=1 then 1 else 2 ), n=2;
@c ===end===
@example
(%i1) printf( false, "~a ~a ~4f ~a ~@@r", 
              "String",sym,bound,sqrt(12),144), bound = 1.234;
(%o1)                 String sym 1.23 2*sqrt(3) CXLIV
(%i2) printf( false,"~@{~a ~@}",["one",2,"THREE"] );
(%o2)                          one 2 THREE 
(%i3) printf(true,"~@{~@{~9,1f ~@}~%~@}",mat ),
          mat = args(matrix([1.1,2,3.33],[4,5,6],[7,8.88,9]))$
      1.1       2.0       3.3 
      4.0       5.0       6.0 
      7.0       8.9       9.0 
(%i4) control: "~:(~r~) bird~p ~[is~;are~] singing."$
(%i5) printf( false,control, n,n,if n=1 then 1 else 2 ), n=2;
(%o5)                    Two birds are singing.
@end example

The directive ~h has been introduced to handle bigfloats. 

@example
~w,d,e,x,o,p@@H
 w : width
 d : decimal digits behind floating point
 e : minimal exponent digits
 x : preferred exponent
 o : overflow character
 p : padding character
 @@ : display sign for positive numbers
@end example

@example
(%i1) fpprec : 1000$
(%i2) printf(true, "|~h|~%", 2.b0^-64)$
|0.0000000000000000000542101086242752217003726400434970855712890625|
(%i3) fpprec : 26$
(%i4) printf(true, "|~h|~%", sqrt(2))$
|1.4142135623730950488016887|
(%i5) fpprec : 24$
(%i6) printf(true, "|~h|~%", sqrt(2))$
|1.41421356237309504880169|
(%i7) printf(true, "|~28h|~%", sqrt(2))$
|   1.41421356237309504880169|
(%i8) printf(true, "|~28,,,,,'*h|~%", sqrt(2))$
|***1.41421356237309504880169|
(%i9) printf(true, "|~,18h|~%", sqrt(2))$
|1.414213562373095049|
(%i10) printf(true, "|~,,,-3h|~%", sqrt(2))$
|1414.21356237309504880169b-3|
(%i11) printf(true, "|~,,2,-3h|~%", sqrt(2))$
|1414.21356237309504880169b-03|
(%i12) printf(true, "|~20h|~%", sqrt(2))$
|1.41421356237309504880169|
(%i13) printf(true, "|~20,,,,'+h|~%", sqrt(2))$
|++++++++++++++++++++|
@end example

@opencatbox
@category{File output} @category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@anchor{readchar}
@deffn {Function} readchar (@var{stream})

Removes and returns the first character in @var{stream}. 
If the end of file is encountered @code{readchar} returns @code{false}.

Example: See @ref{make_string_input_stream}.

@opencatbox
@category{File input} @category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@deffn {Function} readline (@var{stream}) 
Returns a string containing the characters from the current position 
in @var{stream} up to the end of the line or @code{false} 
if the end of the file is encountered.

@opencatbox
@category{File input} @category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@anchor{sprint}
@deffn {Function} sprint (@var{expr_1}, @dots{}, @var{expr_n})

Evaluates and displays its arguments one after the other `on a line' starting at
the leftmost position.  The numbers are printed with the '-' right next to the
number, and it disregards line length.  @code{newline()}, which will be
autoloaded from @code{stringproc.lisp} might be useful, if you whish to place
intermediate line breaking.

Example:

@c ===beg===
@c for n:0 thru 19 do sprint( fib(n) )$
@c for n:0 thru 22 do ( 
@c    sprint(fib(n)), if mod(n,10)=9 then newline() )$
@c ===end===
@example
(%i1) for n:0 thru 19 do sprint( fib(n) )$
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
(%i2) for n:0 thru 22 do ( 
         sprint(fib(n)), if mod(n,10)=9 then newline() )$
0 1 1 2 3 5 8 13 21 34 
55 89 144 233 377 610 987 1597 2584 4181 
6765 10946 17711 
@end example

@opencatbox
@category{Package stringproc}
@closecatbox
@end deffn

@node Functions and Variables for characters, Functions and Variables for strings, Functions and Variables for input and output, stringproc
@section Functions and Variables for characters

@deffn {Function} alphacharp (@var{char})    
Returns @code{true} if @var{char} is an alphabetic character. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} alphanumericp (@var{char}) 
Returns @code{true} if @var{char} is an alphabetic character or a digit. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} ascii (@var{int}) 
Returns the character corresponding to the ASCII number @var{int}.
( -1 < int < 256 )

@c ===beg===
@c for n from 0 thru 255 do ( 
@c    tmp: ascii(n), if alphacharp(tmp) then sprint(tmp), 
@c       if n=96 then newline() )$
@c ===end===
@example
(%i1) for n from 0 thru 255 do ( 
   tmp: ascii(n), if alphacharp(tmp) then sprint(tmp),
      if n=96 then newline() )$
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
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} cequal (@var{char_1}, @var{char_2})          
Returns @code{true} if @var{char_1} and @var{char_2} are the same. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} cequalignore (@var{char_1}, @var{char_2})    
Like @code{cequal} but ignores case. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} cgreaterp (@var{char_1}, @var{char_2})       
Returns @code{true} if the ASCII number of @var{char_1} is greater than the number of @var{char_2}. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} cgreaterpignore (@var{char_1}, @var{char_2})
Like @code{cgreaterp} but ignores case. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} charp (@var{obj}) 
Returns @code{true} if @var{obj} is a Maxima-character.
See introduction for example.

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} cint (@var{char}) 
Returns the ASCII number of @var{char}.

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} clessp (@var{char_1}, @var{char_2})
Returns @code{true} if the ASCII number of @var{char_1} is less than the number of @var{char_2}. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} clesspignore (@var{char_1}, @var{char_2})
Like @code{clessp} but ignores case. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} constituent (@var{char})   
Returns @code{true} if @var{char} is a graphic character and not the space character.
A graphic character is a character one can see, plus the space character.
(@code{constituent} is defined by Paul Graham, ANSI Common Lisp, 1996, page 67.)

@c ===beg===
@c for n from 0 thru 255 do ( 
@c    tmp: ascii(n), if constituent(tmp) then sprint(tmp) )$
@c ===end===
@example
(%i1) for n from 0 thru 255 do ( 
tmp: ascii(n), if constituent(tmp) then sprint(tmp) )$
! " #  %  ' ( ) * + , - . / 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 @{ | @} ~
@end example

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} cunlisp (@var{lisp_char}) 
Converts a Lisp-character into a Maxima-character.
(You won't need it.)

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} digitcharp (@var{char})    
Returns @code{true} if @var{char} is a digit. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} lcharp (@var{obj}) 
Returns @code{true} if @var{obj} is a Lisp-character.
(You won't need it.)

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} lowercasep (@var{char})    
Returns @code{true} if @var{char} is a lowercase character. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@defvr {Variable} newline 
The newline character. 

@opencatbox
@category{Global variables} @category{Package stringproc}
@closecatbox

@end defvr

@defvr {Variable} space   
The space character.

@opencatbox
@category{Global variables} @category{Package stringproc}
@closecatbox

@end defvr

@defvr {Variable} tab     
The tab character.

@opencatbox
@category{Global variables} @category{Package stringproc}
@closecatbox

@end defvr

@deffn {Function} uppercasep (@var{char})    
Returns @code{true} if @var{char} is an uppercase character. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@node Functions and Variables for strings,  , Functions and Variables for characters, stringproc
@section Functions and Variables for strings

@c -----------------------------------------------------------------------------
@anchor{base64}
@deffn {Function} base64 (@var{string})

Returns the base64-representation of @var{string} as a string.

Example:

@example
(%i1) base64 : base64("foo bar baz");
(%o1)                       Zm9vIGJhciBiYXo=
(%i2) string : base64_decode(base64);
(%o2)                          foo bar baz
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@anchor{base64_decode}
@deffn {Function} base64_decode (@var{base64-string})

Decodes the string @var{base64-string} coded in base64 back to the original string.

Example: See @ref{base64}.

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@deffn {Function} charat (@var{string}, @var{n}) 
Returns the @var{n}-th character of @var{string}.
The first character in @var{string} is returned with @var{n} = 1.

@c ===beg===
@c charat("Lisp",1);
@c ===end===
@example
(%i1) charat("Lisp",1);
(%o1)                           L
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@deffn {Function} charlist (@var{string}) 
Returns the list of all characters in @var{string}. 

@c ===beg===
@c charlist("Lisp");
@c %[1];
@c ===end===
@example
(%i1) charlist("Lisp");
(%o1)                     [L, i, s, p]
(%i2) %[1];
(%o2)                           L
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} eval_string (@var{str})
Parse the string @var{str} as a Maxima expression and evaluate it.
The string @var{str} may or may not have a terminator (dollar sign @code{$} or semicolon @code{;}).
Only the first expression is parsed and evaluated, if there is more than one.

Complain if @var{str} is not a string.

Examples:

@c ===beg===
@c eval_string ("foo: 42; bar: foo^2 + baz");
@c eval_string ("(foo: 42, bar: foo^2 + baz)");
@c ===end===
@example
(%i1) eval_string ("foo: 42; bar: foo^2 + baz");
(%o1)                       42
(%i2) eval_string ("(foo: 42, bar: foo^2 + baz)");
(%o2)                   baz + 1764
@end example

See also @code{parse_string}.

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@anchor{md5sum}
@deffn {Function} md5sum (@var{string})

Returns the md5 checksum of a @var{string} as a string. To parse the returned 
value into an integer please set the input base to 16 and prefix the string by zero.

Example:

@example
(%i1) string : md5sum("foo bar baz");
(%o1)                  ab07acbb1e496801937adfa772424bf7
(%i2) ibase : obase : 16.$

(%i3) integer : parse_string(sconcat(0, string));
(%o3)                 0ab07acbb1e496801937adfa772424bf7
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@deffn {Function} parse_string (@var{str})
Parse the string @var{str} as a Maxima expression (do not evaluate it).
The string @var{str} may or may not have a terminator (dollar sign @code{$} or semicolon @code{;}).
Only the first expression is parsed, if there is more than one.

Complain if @var{str} is not a string.

Examples:

@c ===beg===
@c parse_string ("foo: 42; bar: foo^2 + baz");
@c parse_string ("(foo: 42, bar: foo^2 + baz)");
@c ===end===
@example
(%i1) parse_string ("foo: 42; bar: foo^2 + baz");
(%o1)                    foo : 42
(%i2) parse_string ("(foo: 42, bar: foo^2 + baz)");
                                   2
(%o2)          (foo : 42, bar : foo  + baz)
@end example

See also @code{eval_string}.

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} scopy (@var{string}) 
Returns a copy of @var{string} as a new string. 

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sdowncase (@var{string}) 
@deffnx {Function} sdowncase (@var{string}, @var{start}) 
@deffnx {Function} sdowncase (@var{string}, @var{start}, @var{end}) 
Like @code{supcase}, but uppercase characters are converted to lowercase. 

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sequal (@var{string_1}, @var{string_2}) 
Returns @code{true} if @var{string_1} and @var{string_2} are the same length and contain the same characters. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sequalignore (@var{string_1}, @var{string_2})
Like @code{sequal} but ignores case. 

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sexplode (@var{string})
@code{sexplode} is an alias for function @code{charlist}.

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} simplode (@var{list})  
@deffnx {Function} simplode (@var{list}, @var{delim})  
@code{simplode} takes a list of expressions and concatenates them into a string.
If no delimiter @var{delim} is specified, @code{simplode} uses no delimiter.
@var{delim} can be any string.

@c ===beg===
@c simplode(["xx[",3,"]:",expand((x+y)^3)]);
@c simplode( sexplode("stars")," * " );
@c simplode( ["One","more","coffee."]," " );
@c ===end===
@example
(%i1) simplode(["xx[",3,"]:",expand((x+y)^3)]);
(%o1)             xx[3]:y^3+3*x*y^2+3*x^2*y+x^3
(%i2) simplode( sexplode("stars")," * " );
(%o2)                   s * t * a * r * s
(%i3) simplode( ["One","more","coffee."]," " );
(%o3)                   One more coffee.
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sinsert (@var{seq}, @var{string}, @var{pos})  
Returns a string that is a concatenation of @code{substring (@var{string}, 1, @var{pos} - 1)},
the string @var{seq} and @code{substring (@var{string}, @var{pos})}.
Note that the first character in @var{string} is in position 1.

@c ===beg===
@c s: "A submarine."$
@c concat( substring(s,1,3),"yellow ",substring(s,3) );
@c sinsert("hollow ",s,3);
@c ===end===
@example
(%i1) s: "A submarine."$
(%i2) concat( substring(s,1,3),"yellow ",substring(s,3) );
(%o2)                  A yellow submarine.
(%i3) sinsert("hollow ",s,3);
(%o3)                  A hollow submarine.
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sinvertcase (@var{string})  
@deffnx {Function} sinvertcase (@var{string}, @var{start})  
@deffnx {Function} sinvertcase (@var{string}, @var{start}, @var{end})  
Returns @var{string} except that each character from position @var{start} to @var{end} is inverted.
If @var{end} is not given,
all characters from @var{start} to the end of @var{string} are replaced.

@c ===beg===
@c sinvertcase("sInvertCase");
@c ===end===
@example
(%i1) sinvertcase("sInvertCase");
(%o1)                      SiNVERTcASE
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} slength (@var{string}) 
Returns the number of characters in @var{string}. 

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} smake (@var{num}, @var{char}) 
Returns a new string with a number of @var{num} characters @var{char}. 

@c ===beg===
@c smake(3,"w");
@c ===end===
@example
(%i1) smake(3,"w");
(%o1)                          www
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} smismatch (@var{string_1}, @var{string_2}) 
@deffnx {Function} smismatch (@var{string_1}, @var{string_2}, @var{test}) 
Returns the position of the first character of @var{string_1} at which @var{string_1} and @var{string_2} differ or @code{false}.
Default test function for matching is @code{sequal}.
If @code{smismatch} should ignore case, use @code{sequalignore} as test.

@c ===beg===
@c smismatch("seven","seventh");
@c ===end===
@example
(%i1) smismatch("seven","seventh");
(%o1)                           6
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} split (@var{string})  
@deffnx {Function} split (@var{string}, @var{delim})  
@deffnx {Function} split (@var{string}, @var{delim}, @var{multiple})  
Returns the list of all tokens in @var{string}.
Each token is an unparsed string.
@code{split} uses @var{delim} as delimiter.
If @var{delim} is not given, the space character is the default delimiter.
@var{multiple} is a boolean variable with @code{true} by default.
Multiple delimiters are read as one.
This is useful if tabs are saved as multiple space characters.
If @var{multiple} is set to @code{false}, each delimiter is noted.

@c ===beg===
@c split("1.2   2.3   3.4   4.5");
@c split("first;;third;fourth",";",false);
@c ===end===
@example
(%i1) split("1.2   2.3   3.4   4.5");
(%o1)                 [1.2, 2.3, 3.4, 4.5]
(%i2) split("first;;third;fourth",";",false);
(%o2)               [first, , third, fourth]
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sposition (@var{char}, @var{string}) 
Returns the position of the first character in @var{string} which matches @var{char}.
The first character in @var{string} is in position 1.
For matching characters ignoring case see @code{ssearch}.

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sremove (@var{seq}, @var{string})  
@deffnx {Function} sremove (@var{seq}, @var{string}, @var{test})  
@deffnx {Function} sremove (@var{seq}, @var{string}, @var{test}, @var{start})  
@deffnx {Function} sremove (@var{seq}, @var{string}, @var{test}, @var{start}, @var{end})  
Returns a string like @var{string} but without all substrings matching @var{seq}.
Default test function for matching is @code{sequal}.
If @code{sremove} should ignore case while searching for @var{seq}, use @code{sequalignore} as test.
Use @var{start} and @var{end} to limit searching.
Note that the first character in @var{string} is in position 1.

@c ===beg===
@c sremove("n't","I don't like coffee.");
@c sremove ("DO ",%,'sequalignore);
@c ===end===
@example
(%i1) sremove("n't","I don't like coffee.");
(%o1)                   I do like coffee.
(%i2) sremove ("DO ",%,'sequalignore);
(%o2)                    I like coffee.
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sremovefirst (@var{seq}, @var{string})  
@deffnx {Function} sremovefirst (@var{seq}, @var{string}, @var{test})  
@deffnx {Function} sremovefirst (@var{seq}, @var{string}, @var{test}, @var{start})  
@deffnx {Function} sremovefirst (@var{seq}, @var{string}, @var{test}, @var{start}, @var{end})  
Like @code{sremove} except that only the first substring that matches @code{seq} is removed. 

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} sreverse (@var{string}) 
Returns a string with all the characters of @var{string} in reverse order. 

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} ssearch (@var{seq}, @var{string})  
@deffnx {Function} ssearch (@var{seq}, @var{string}, @var{test})  
@deffnx {Function} ssearch (@var{seq}, @var{string}, @var{test}, @var{start})  
@deffnx {Function} ssearch (@var{seq}, @var{string}, @var{test}, @var{start}, @var{end})
Returns the position of the first substring of @var{string} that matches the string @var{seq}.
Default test function for matching is @code{sequal}.
If @code{ssearch} should ignore case, use @code{sequalignore} as test.
Use @var{start} and @var{end} to limit searching.
Note that the first character in @var{string} is in position 1.

@example
(%i1) ssearch("~s","~@{~S ~@}~%",'sequalignore);
(%o1)                                  4
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} ssort (@var{string}) 
@deffnx {Function} ssort (@var{string}, @var{test}) 
Returns a string that contains all characters from @var{string} in an order such there are no two successive characters @var{c} and @var{d} such that @code{test (@var{c}, @var{d})} is @code{false} and @code{test (@var{d}, @var{c})} is @code{true}.
Default test function for sorting is @var{clessp}.
The set of test functions is @code{@{clessp, clesspignore, cgreaterp, cgreaterpignore, cequal, cequalignore@}}.

@c ===beg===
@c ssort("I don't like Mondays.");
@c ssort("I don't like Mondays.",'cgreaterpignore);
@c ===end===
@example
(%i1) ssort("I don't like Mondays.");
(%o1)                    '.IMaddeiklnnoosty
(%i2) ssort("I don't like Mondays.",'cgreaterpignore);
(%o2)                 ytsoonnMlkIiedda.'   
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} ssubst (@var{new}, @var{old}, @var{string}) 
@deffnx {Function} ssubst (@var{new}, @var{old}, @var{string}, @var{test}) 
@deffnx {Function} ssubst (@var{new}, @var{old}, @var{string}, @var{test}, @var{start}) 
@deffnx {Function} ssubst (@var{new}, @var{old}, @var{string}, @var{test}, @var{start}, @var{end}) 
Returns a string like @var{string} except that all substrings matching @var{old} are replaced by @var{new}.
@var{old} and @var{new} need not to be of the same length.
Default test function for matching is @code{sequal}.
If @code{ssubst} should ignore case while searching for old, use @code{sequalignore} as test.
Use @var{start} and @var{end} to limit searching.
Note that the first character in @var{string} is in position 1.

@c ===beg===
@c ssubst("like","hate","I hate Thai food. I hate green tea.");
@c ssubst("Indian","thai",%,'sequalignore,8,12);
@c ===end===
@example
(%i1) ssubst("like","hate","I hate Thai food. I hate green tea.");
(%o1)          I like Thai food. I like green tea.
(%i2) ssubst("Indian","thai",%,'sequalignore,8,12);
(%o2)         I like Indian food. I like green tea.
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} ssubstfirst (@var{new}, @var{old}, @var{string}) 
@deffnx {Function} ssubstfirst (@var{new}, @var{old}, @var{string}, @var{test}) 
@deffnx {Function} ssubstfirst (@var{new}, @var{old}, @var{string}, @var{test}, @var{start}) 
@deffnx {Function} ssubstfirst (@var{new}, @var{old}, @var{string}, @var{test}, @var{start}, @var{end}) 
Like @code{subst} except that only the first substring that matches @var{old} is replaced. 

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} strim (@var{seq},@var{string}) 
Returns a string like @var{string},
but with all characters that appear in @var{seq} removed from both ends. 

@c ===beg===
@c "/* comment */"$
@c strim(" /*",%);
@c slength(%);
@c ===end===
@example
(%i1) "/* comment */"$
(%i2) strim(" /*",%);
(%o2)                        comment
(%i3) slength(%);
(%o3)                           7
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} striml (@var{seq}, @var{string}) 
Like @code{strim} except that only the left end of @var{string} is trimmed. 

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} strimr (@var{seq}, @var{string}) 
Like @code{strim} except that only the right end of string is trimmed. 

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@deffn {Function} stringp (@var{obj}) 
Returns @code{true} if @var{obj} is a string.
See introduction for example.

@opencatbox
@category{Predicate functions} @category{Package stringproc}
@closecatbox

@end deffn

@c -----------------------------------------------------------------------------
@deffn {Function} substring (@var{string}, @var{start})
@deffnx {Function} substring (@var{string}, @var{start}, @var{end}) 
Returns the substring of @var{string} beginning at position @var{start} and ending at position @var{end}.
The character at position @var{end} is not included.
If @var{end} is not given, the substring contains the rest of the string.
Note that the first character in @var{string} is in position 1.

@c ===beg===
@c substring("substring",4);
@c substring(%,4,6);
@c ===end===
@example
(%i1) substring("substring",4);
(%o1)                        string
(%i2) substring(%,4,6);
(%o2)                          in
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} supcase (@var{string}) 
@deffnx {Function} supcase (@var{string}, @var{start}) 
@deffnx {Function} supcase (@var{string}, @var{start}, @var{end}) 
Returns @var{string} except that lowercase characters from position @var{start} to @var{end} are replaced by the corresponding uppercase ones.
If @var{end} is not given,
all lowercase characters from @var{start} to the end of @var{string} are replaced.

@c ===beg===
@c supcase("english",1,2);
@c ===end===
@example
(%i1) supcase("english",1,2);
(%o1)                        English
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn

@deffn {Function} tokens (@var{string}) 
@deffnx {Function} tokens (@var{string}, @var{test}) 
Returns a list of tokens, which have been extracted from @var{string}.
The tokens are substrings whose characters satisfy a certain test function.
If test is not given, @var{constituent} is used as the default test.
@code{@{constituent, alphacharp, digitcharp, lowercasep, uppercasep, charp, characterp, alphanumericp@}} is the set of test functions. 
(The Lisp-version of @code{tokens} is written by Paul Graham. ANSI Common Lisp, 1996, page 67.)

@c ===beg===
@c tokens("24 October 2005");
@c tokens("05-10-24",'digitcharp);
@c map(parse_string,%);
@c ===end===
@example
(%i1) tokens("24 October 2005");
(%o1)                  [24, October, 2005]
(%i2) tokens("05-10-24",'digitcharp);
(%o2)                     [05, 10, 24]
(%i3) map(parse_string,%);
(%o3)                      [5, 10, 24]
@end example

@opencatbox
@category{Package stringproc}
@closecatbox

@end deffn
