This document describes the classes and functions provided by the zk
library.  These are handy because they are available immediately with
no explicit #includes.  If any of the following descriptions are hard
to understand at first, it might help to experiment with the classes
and/or functions in question.  Using zk, such experimentation is much
easier and faster than with a c++ compiler.

Text and integer container classes:

    String      --    Text.
    Mfile       --    Two-dimensional text.
    Iota        --    Groups of integers.
    Iotasa      --    Two-dimensional groups of integers.

The relationship between String and Mfile is the same as the relationship
between Iota and Iotasa.  An Mfile is a string of Strings, and an Iotasa
is a string of Iotas.

In addition to the above classes, there is a "Z" version of each.  They
are named String_Z, Mfile_Z, Iota_Z, and Iotasa_Z.  The "Z" versions are
for moving the data efficiently, by disconnecting it from one object and
reconnecting it to another object.  That makes compound expressions more
efficient, because the data is not copied between subexpressions.

The operations you can do on the "Z" version of each class are limited.
You can only use it as an argument to a function call, assignment, or
initialization.  You can use it as the operand of "+=" and other operators
because they are equivalent to function calls.  To retrieve the data
from the "Z" object for further operations, you should assign it, using
the assignment operator, "=", to an object of the corresponding non-"Z"
class, and do the operations on that object.

In addition to the above classes, other similar classes are available
if you enable them in sa.zh.  They are Mfilesa, Iotasasa, etc.  In each
case, the suffix "sa" means it is a string of objects of that class.  So
an Mfilesa is a string of Mfiles, to give 3-dimensional text, and an
Iotasasa is a string of Iotasas, to give 3-dimensional groups of integers.

To convert an object to the corresponding "Z" class, use the "!" operator,
which is a prefix operator.  No data is moved when you do that, but just
relinked to its new owner.  See the examples below.

Here are the other operators you can use on the non-"Z" versions of all
of the above classes:

   +=  Add new elements, individually or in groups.
   ==  Compare, returns true if data is equal
   !=  Compare, not equal
   =   Assign data to the object, deleting old data.
   []  Select an element from the object, return a reference

   See example usage of each operator below.

Here are the other functions you can use on the non-"Z" versions of all
of the above classes:

   void compress(Iota&)               For each nonzero element of the
                                      Iota, the corresponding element
                                      of the object survives.  The rest
                                      are deleted.

   void clear()                       Delete all the elements of the
                                      object and reset it to empty.

   last()                             Returns a reference to the last
                                      (rightmost) element of the object.

   offlensubstr(int offset, int length)  Makes a substring of the object,
                                      from that offset and length.  The
                                      result is of the corresponding "Z"
                                      class (see above).

   ed and ted                         Edit and tail edit.  Ed takes 1, 2,
                                      or 3 arguments.  The first argument
                                      is the offset to the data to be
                                      edited.  (Offset means element number,
                                      starting from zero.)  The 2nd argument,
                                      if any, is the number of elements to
                                      delete.  The 3rd argument, if any, is
                                      the data to insert in place of the
                                      deleted data.  Often you will want to
                                      delete 0 elements or insert 0 elements,
                                      to just delete or insert instead of
                                      replacing.

                                      Ted is similar to ed but operates on
                                      the end of the string of data, and
                                      just takes two arguments, with the
                                      2nd argument optional.  The first
                                      argument tells how many elements to
                                      delete from the end, and the 2nd
                                      tells what to replace them with.

                                      The replacement argument to ed and
                                      ted, which tells what data to insert
                                      in place of any data deleted, can be
                                      of various types.  For each of the
                                      classes discussed above, it can be
                                      an element, or it can be a group of
                                      elements, which means it's another
                                      object of the same class as the object
                                      being edited, or of the corresponding
                                      "Z" class.  Also, for class String,
                                      it can be an ordinary "char*" string.

   int len()                          Returns the number of elements.

   bool empty()                       Returns true if there are no elements.

   newlast()                          Adds an empty element to the end and
                                      returns a reference to it.


Member functions of String specifically, not available in the other classes:

   Note: The read and write functions return false when the operation fails.

   bool read()                        Read from standard input into the
                                      String, until end of file is reached.
                                      Newline characters go in the String.

   bool read("filename.ext")          Same as read, but from the given file.

   bool write()                       Write the String to standard output.

   bool write("filename.ext")         Write the String to the given file.

   ...



Besides the container classes, the zk library also provides the following
miscellaneous functions, etc., some of which use the container classes:

   msg and gsm                         These macros output a formatted
                                       message to standard error output,
                                       which is normally the console, and
                                       also to the session log, if any.
                                       See environ.txt for details of how
                                       to get a session log.  See examples
                                       of msg/gsm in the examples below.
                                       The format codes are %s for strings,
                                       %d for decimal numbers, and %h for
                                       hexadecimal numbers.

   write(Mfile_Z)                      This writes an entire Mfile to stanard
                                       output, one line per String.

   write("filename",Mfile_Z)           Same as above, but to a file, replacing
                                       the whole file.

   Mfile_Z exts(Mfile_Z)               This gets the filename extensions of
                                       a list of filenames.

   Mfile_Z uniq(Mfile_Z)               This omits identical elements.

   Mfile_Z globm(cx)                   This gets filenames from a pattern,
                                       e.g., "*.*" or "*.ini".

   Mfile_Z globmroots(cx)              Like globm but with the .extensions
                                       deleted.

   Mfile_Z cols(int,int,Mfile_Z)       This converts an Mfile of
                                       fields to a page of tabulated text.
                                       The fields fill the page column by
                                       column.  The page consists of lines
                                       of text, one line per String of the
                                       resulting Mfile.  The first argument
                                       is the number of columns, and the
                                       2nd is the width of each column.  No
                                       tab characters are used, tabulation
                                       is done by adding spaces.

   unsigned long mtime("filename")     This returns the modification date
                                       and time of a file, such that you
                                       can tell which file was modified
                                       most recently by comparing their
                                       mtimes.  Very handy for writing
                                       your own version of make.

   whatis x                            This macro is useful mainly at the
                                       zk command line.  It tells you what
                                       zk thinks the name x means.  Handy
                                       if you defined something and forget
                                       whether it was a function or class
                                       or what.

   void version()                      This outputs the version of zk.

   tx("prototype",args)                See msg/gsm above.  This provides
                                       the same printf style processing,
                                       but returns the result as char*,


Non-class typedefs used by these functions:

   bool                                typedef int bool; 1=true, 2=false.
   cx                                  typedef const char *cx;







                                 Examples


Note: When these descriptions refer to classes such as Mfile, they can
also mean Mfile_Z, etc., depending on which version the function takes.
From the programmer's point of view, there is conceptually no difference
between Mfile and Mfile_Z.  Mfile_Z is merely a vehicle for passing an
Mfile to a function more efficiently.


Example 1:  write(cols(20,4,uniq(sort(exts(globm("*.*"))))));

Example 1 looks at all the filenames in the current directory, gets the
filename extension of each, sorts them, filters out duplicates, and
writes the result in 20 4-character columns.  There will usually be less
than 20 extensions, so the output will usually be one line, with just
some of the 20 columns occupied.  The purpose of this is to show you all
the filename extensions that exist in the current directory without
requiring you to look at all the filenames.  If the output seems
"tabulated", i.e., if the first 3-character extension output is blank,
that means there are one or more filenames that have no extension at
all, which is considered a blank extension.

Explanation of example 1:
1. The glom function creates an Mfile containing the filenames.
2. The exts function deletes the path and root filename from each filename
   in the Mfile, leaving just the extension (e.g. ".exe").
3. The sort function sorts the results into alphabetical order.
4. The uniq function deletes duplications, so the word "exe", for example,
   won't appear more than once in the output.
5. The cols function, with arguments 20 and 4, formats the names into
   20 columns, each 4 characters wide, such that each String in the resulting
   Mfile consists of one row of 20 columns.
6. The write function writes it to standard output so you can see it.


Example 2:  write(cols(8,10,sort(globmroots("*.bat"))));

Example 2 looks for all batch files, *.bat, and writes their names,
without the .bat extension, to standard output, in 8 columns, each
column 10 characters wide.  The output is sorted in each column,
continued in the next column.  The globmroots function finds all files
that match the pattern and returns a list of their root names (without
extensions).

Example 2 uses the same functions as example 1, except that it uses
globmroots instead of globm.  The difference is that globmroots deletes
the filename extensions, leaving the root filenames without extensions.


Example 3:  msg "Hello world." gsm; // A newline character is appended too.


Example 4:  msg "%s%d is A1","A",1 gsm; // This just shows how to use %s/%d.


Example 5:  Mfile roots;
            roots=globmroots("*.*"); // Mfile_Z is converted to Mfile.
            roots=sort(!roots);      // And converted back to Mfile_Z and back.

Example 5 is just to show you how to use "!" to convert to a "Z" class, and
the assignment operator to convert back to the non-"Z" class.  Keep in mind
that the whole point of all these conversions is to avoid copying the data,
to avoid taking extra time.  The conversions themselves take practically no
time at all.


Example 6:  String s1;
            for(int i=0; i<10; i++) s1+="A";
            msg "s1 is \"%s\"",s1 gsm;

Example 6 shows use of the += operator with the container classes.  Note
that the backslashes in the string are for the purpose of making the
quotation marks part of the string rather than indicating end of string.
If this example is still not clear, it might help to copy it to the end
of zk.ini so you can see it run.


Example 7:  String s1="ABC";
            if(s1=="xyz") msg "that's impossible" gsm;
            if(s1=="ABC") msg "that's much better" gsm;
            if(s1!="ABC") msg "forget it, too many contradictions" gsm;

Example 7 shows that you can use char* literals with String::operator==
and String::operator!=.  You can also use other Strings or String_Z's.


Example 8:  String alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            for(int i=0,j=alphabet.len(); i<j; i++) msg "-%s-",alphabet[i] gsm;

Example 8 shows usage of the len() function and the [] operator.


If any of the examples are not clear, copy them to the end of zk.ini so you
can see them run.  If you are already in zk, just type "lz" at the zk
command line prompt to reload zk.ini, which will run the example you copied.

