[net.sources] CMD003 Part 1 of 6

mem@sii.UUCP (Mark Mallett) (06/08/85)

<->

	CMD003	TOPS20 style parsing	Part 1 of 6

	This is the 1st of 6 pieces of COMND, a TOPS-20 style parsing
library for CP/M (and other) systems, edit level 003.  Its contents are
suitable for unpacking by the standard "sh" shell.  Remove this header,
and any trailer added by the news/mail system, and run the rest through
the shell like this:

	sh part1

and you will get the following file:

	comnd.doc	Document for the library.  Note that this has
			changed somewhat since its original posting.


If you are unwilling to unpack it on a unix system, it should be fairly
simple to write a program to unpack it somewhere else.

**** End of Header, remove to here+1 ****
echo "unpacking file comnd.doc"
cat <<'EEOOFF' >comnd.doc




                                   C O M N D

                    A TOPS-20 style command parsing library
                            for personal computers




             Documentation  and  source  code Copyright (C) 1985 by Mark
        E. Mallett;  permission is granted to distribute  this  document
        and the  code  indiscriminately.  Please leave credits in place,
        and add your own as appropriate.


                                 A Disclaimer



             The code which implements this library takes up about  12Kb
        of  space  on my CP/M system using Manx's AZTEC CII Z80 compiler
        (10Kb with the date/time support stubbed out).   I  don't  claim
        that  the  coding  is  very  efficient  nor  do I make any other
        claims about the code  in  general.    I  do  believe  that  the
        definition  of  the  call  interface  is reasonable, and for me,
        this has made it quite usable.




                                 This Document



             This document contains the following sections:


         o Document overview (this here section)

         o Introduction and history

         o Functional overview

         o How to write programs using the subroutine library

         o How to make the library work on your system




                           Introduction and History



             This document describes the COMND subroutine package for  C
        programmers.    COMND   is   a   subroutine  library  to  effect
        consistent parsing of user input, and in general is well  suited
        for verb-argument   style   command  interfaces.    The  library
        provides a consistent  user  interface  as  well  as  a  program
        interface  which,  I believe, could well remain unchanged if the
        parsing library were re-written to support  different  interface
        requirements (such as menu interaction).

             The   COMND  interface  is  based  on  the  TOPS-20  model.
        TOPS-20 is an operating system  which  is/was  used  by  Digital
        Equipment Corporation  on  their  PDP-20  computer.  TOPS-20 was
        based on TENEX, written by BBN (I  think,  I  think).    TOPS-20
        COMND  is much more robust and consistent than the library which
        this document describes;  this library being intended for  small
        computer  applications,  it  provides  the  most  commonly  used
        functions.

             This library was written on a Z-80 system  running  Digital
        Research   Corporation's   CP/M  operating  system  version  3.0
        (CPM+).  I have also compiled and  tried  it  on  a  VAX  11/780
        running VMS.    It  is completely written in the C language, and
        contains only a few operating system specific elements.

             The COMND JSYS section of the TOPS-20 Monitor Calls  manual
        is probably a good thing to read.

             Please note:   while there are a few unimplemented sections
        of this library, I felt that it was nevertheless  worthwhile  to
        submit  it  to  public  domain since it is usable for almost all
        general command parsing and since the  call  interface  is  well
        defined.   I  have  used this library extensively since sometime
        in 1984.




                              Functional Overview




             The COMND subroutine library  provides  a  command-oriented
        user  interface  which is consistent at the programmer level and
        at the  user  level.    At  the  program  level,  it  gives   an
        algorithmically  controlled  parsing  flow,  where a call to the
        library exists  for  each  field  or  choice  of  fields  to  be
        parsed.

             At the user level, the interface provides:


         o Command prompting.

         o Consistent  command  line  editing.  The user may use editing
           keys to erase the last character or word,  and  to  echo  the
           current input line and prompt.

         o Input  abbreviation  and  defaulting.    The  user  may  type
           abbreviations of  keywords,  or  may  type  nothing  to  have
           defaults applied.

         o Incremental  help.    By  pressing  a  known  key  (usually a
           question mark), the user  can  find  out  what  choices  s/he
           has.

         o Guide  strings.    Parenthesized guide words are shown at the
           users option.

         o Command completion.  Where the subroutine library  can  judge
           what  the  succesful  completion  of  a portion of user input
           will be, the user can elect to have this input completed  and
           shown automatically.




                            Using the COMND Library



             While  you  read  this part of the document, you might want
        to look at the  sample  program  named  TEST.C  which  has  been
        included with  this  package.   It is an over-commented guide to
        the use of the COMND library.

             Any module which makes use of this  library  shall  include
        the definition   file  named  "comnd.h".    This  file  contains
        definitions  which   are   necessary   to   the   caller-library
        interface.   Mnemonics  (structures  and constants) mentioned in
        relation to this interface are defined in this file.

             The philosophy of parsing with the COMND library is that  a
        command  line  is  typed,  the  program  inspects  it,  then the
        program acts on  the  directions  given  in  that  line.    This
        process is  repeated  until  the  program  finishes.   The COMND
        library assists the user in typing  the  command  line  and  the
        program in  inspecting  it.    Acting  on  it  is left up to the
        calling program.

             The typing and parsing of fields in  the  command  line  go
        essentially hand-in-hand   with   this   library.    The  single
        subroutine COMND() is used to effect all parsing.  This  routine
        is  called  for  each  field  of  the  input  line to be parsed.
        Parsing is done according to a current  parse  state,  which  is
        maintained  in  a  parameter  block  passed  between  caller and
        library.   The  state  block  contains  the  following  sort  of
        information (described in detail later):


         o What to use for a prompt string.

         o  Addresses  of  scratch  buffers  for  user  input  and  atom
           storage.

         o How much the user has entered.

         o How much of the line the program has parsed.




             An important thing to note is that the  indexes  (how  much
        entered and  parsed)  are  both  variable.    The program begins
        parsing of the input line upon a break signal by the user  (such
        as the  typing  of  a carriage return, question mark, etc).  The
        user may then resume typing  and  erase  characters  back  to  a
        point BEFORE  that  already  parsed.   It is very important that
        the program does not take any action on  what  has  been  parsed
        until  the  line  has  been completely processed, otherwise that
        action could be undesired.

             Since the user may back up the command  input  to  a  point
        before  that  already  processed  by  the application program, a
        mechanism must be provided to backup the program to the  correct
        point.   Rather  than going to the point backed up to, the COMND
        library  expects  the  application  program  to  return  to  the
        beginning of  the  line,  and start again.  The user's input has
        remained in the command line buffer, and the library  will  take
        care  of  buffering  the rest of the input when that parse point
        is again reached.  However, this means  that  there  must  be  a
        method  of  communicating  to  the  calling  program  that  this
        "reparse" is  necessary.    Actually  there  are   two   methods
        provided, as follows:


         o  Each  call  to  the command parsing routine COMND() yields a
           result code.  The result may indicate that a reparse  has  to
           take place.    The  program  shall  then back up to the point
           where the parse of the line began, and start again.

         o The application program may specify the address of  a  setjmp
           buffer which  identifies  the reparse point.  (Note setjmp is
           a facility provided as part of  most  standard  C  libraries.
           It  allows  you  to  mark a point in the procedure flow [call
           frame,  registers,  and  whatever  else  is  involved  in   a
           context],  and  return to that point from another part of the
           program as if control  had  never  proceeded.    If  you  are
           unfamiliar  with  this  facility,  you  might  want to find a
           description in your C manual.) It is  up  to  the  caller  to
           setup the setjmp environment at the reparse point.


             In  either  case, the reparse point (the point at which the
        parse will be restarted if necessary) is the point at which  the
        first element  of the command line is parsed.  This is after the
        initialization call which starts every parse.




             Every  call  to  the  COMND()   subroutine   involves   two
        arguments:   a  command  state  block, in which is kept track of
        the parse state, and a command function block,  which  describes
        what sort  of  thing  to parse next.  The command state block is
        given a structure called "CSBs", and  a  typedef  called  "CSB".
        Each  element  of  the structure is named with a form "CSB_xxx",
        where "xxx" is representative of the  element's  purpose.    The
        following  are  the  elements of the command state block, in the
        order that they appear in the structure.


         o CSB_PFL is a BYTE.  This contains flags which are set by  the
           caller  to  indicate  specifics  of  the  command processing.
           These flags are:


            o _CFNEC:  Do not echo user input.

            o _CFRAI:  Convert lowercase input to uppercase.


         o CSB_RFL, a BYTE value, contains flags which are kept  by  the
           library in  the  performance  of the parse.  Generally, these
           flags  are  of  no  interest  to  the  caller   since   their
           information  can  be  gleaned  from  the  result  code of the
           COMND() call.  However, they are:


            o _CFNOP:  No  parse.    Nothing  matched,  i.e.,  an  error
              occured.

            o _CFESC:  Field terminated by escape.

            o _CFEOC:  Field terminated by CR.

            o _CFRPT:  Reparse required.

            o _CRSWT:  Switch ended with colon.

            o _CFPFE:  Previous field terminated with escape.


         o  CSB_RSB  is  the  address  of a setjmp buffer describing the
           environment at  the  reparse  point.    If  this   value   is
           non-NULL,   then  if  a  reparse  is  required,  a  longjmp()
           operation is performed using this setjmp buffer.

         o CSB_INP is the address  of  the  input-character  routine  to
           use.   If this value is non-NULL, then this routine is called
           to get each character of input.  No line editing  or  special
           interactive  characters are recognized in this mode, since it
           is assumed that this will be  used  for  file  input.    Note




           especially:   this  facility  is not yet implemented, however
           the definition is provided for future expansion.  Thou  shalt
           always leave this NULL, or write the facility thyself.

         o  CSB_OUT is the inverse correspondent to the previous element
           (CSB_INP).  It is the address of a routine to process  output
           from the  command  library.    Please  see the warning in the
           CSB_INP description about not being implemented.

         o CSB_PMT is the address  of  the  prompt  string  to  use  for
           command parsing.      The   command  library  takes  care  of
           prompting, so make sure this is filled in.

         o CSB_BUF is the address of the buffer to put user  input  into
           as s/he is typing it in.

         o  CSB_BSZ,  an int, is the number of bytes which can be stored
           in CSB_BUF;  i.e., it is the buffer size.

         o CSB_ABF is the address of an atom buffer.  Some (if not  all)
           parsing   functions   involve   extracting   some  number  of
           characters from the input buffer and interpreting  or  simply
           returning this  extracted  string.   This buffer is necessary
           for those operations.  It should probably be as large as  the
           input buffer (CSB_BUF), but it is really up to you.

         o  CSB_ASZ,  an  int,  is the number of characters which can be
           stored in CSB_ABF;  i.e., it is the size of that buffer.

           ** Note ** CSB elements from here to the end do not  have  to
           be initialized  by  the  calling  program.   They are used to
           store state information and are initialized  as  required  by
           the library.

         o CSB_PRS,  an  int,  contains  the  parse  index.  This is the
           point in the command buffer up  to  which  parsing  has  been
           achieved.

         o  CSB_FLN,  an  int,  is  the  filled  length  of  the command
           buffer.  This is the number of  characters  which  have  been
           typed by the user.

         o CSB_RCD,  an int, is a result code of the parse.  This is the
           same value which is returned as the  result  of  the  COMND()
           procedure call.

         o  CSB_RVL is a union which is used to contain either an int or
           an address value.  The  names  of  the  union  elements  are:
           _INT  for  int, _ADR for address (note that a typecast should
           be used  for  proper  address  assignment).    This   element
           contains  a  value  returned  from some parse functions which
           return values which are single values.  For  example,  if  an




           integer is parsed, its value is returned here.

         o  CSB_CFB is the address of a command function block for which
           a parse was successful.  This is significant in  cases  where
           there  are  alternative  possible interpretations of the next
           command line field.




        The parse of each element in a command line  involves,  as  well
        as  the  Command  State Block just described, a Command Function
        Block which identifies the sort of thing to  be  parsed.    This
        block  is  defined  in  a  structure  named  "CFBs", which has a
        corresponding typedef named "CFB".  Elements of the  CFB,  named
        "CFB_xxx",  are  as  follows  (in  the  order they appear in the
        structure):



         o CFB_FNC, a BYTE, is the function  code.    This  defines  the
           function to  be  performed.    The function codes are listed,
           and their actions described, a little later.

         o CFB_FLG, a BYTE, contains flags which  the  caller  specifies
           to the  library.    These  are  very significant, and in most
           cases affect the presentation to the user.    The  flag  bits
           are:


            o _CFHPP:    A  help  string has been supplied and should be
              given when the user types the help character ("?").

            o _CFDPP:  A default string has been supplied, and shall  be
              used  if  the  user  does  not type anything at this point
              (typing  nothing  means  typing  a  return  or  requesting
              command completion).     Note  that  this  flag  (and  the
              default string) is ONLY significant for the CFB passed  in
              the  call  to  the COMND() routine, and not for any others
              referenced as alternatives by  that  CFB.    Note  further
              that  a  default  specified by the first CFB is applied to
              the input stream, and not to the parsing function.    That
              means  that  the  default  is subject to interpretation by
              alternate CFBs, and in fact, does  not  even  have  to  be
              appropriate for the CFB which contains it.

            o _CFSDH:    The default help message should be supressed if
              the user  types  the  help  character  ("?").    This   is
              normally   used  in  conjunction  with  the  _CFHPP  flag.
              However, if this flag is present and  the  _CFHPP  is  not
              selected,  then  the  help operation is inhibited, and the
              help character becomes insignificant (just like any  other




              character).

            o _CFCC:      A  character  characteristic  table  has  been
              provided.  A CC table identifies which characters  may  be
              part of  the  element being recognized.  Not all functions
              support this table (for example, it does  not  make  sense
              to   re-specify   which  characters  may  compose  decimal
              numbers).  This table also specifies which characters  are
              break  characters,  causing  the  parser  to "wake up" the
              calling program when one of them is typed.   If  this  bit
              is  not  set  (as is usually the case), a default table is
              associated according to the function code.

            o _CFDTD:  For parsing date and  time,  specifies  that  the
              date should be parsed.

            o _CFDTT:    For  parsing  date and time, specifies that the
              time should be parsed.


         o CFB_CFB is the address of another CFB which  may  be  invoked
           if the  user  input  does  not satisfy this CFB.  CFBs may be
           chained in this manner at will.    Recognize,  however,  that
           the  ORDER  of the chain plays an important part in how input
           is handled, particularly in disambiguation of  input.    Note
           also  that  only  the  first  CFB  of  the  chain is used for
           specifying  a  default  string  and  CC  table  for   command
           wake-up.

           CFB  chaining  is  a very important part of parsing with this
           library.

         o CFB_DAT is defined as a long, since it  is  used  to  contain
           address or   int   values.    It  should  be  referenced  via
           typecast.  It is  not  defined  as  a  union  because  it  is
           inconvenient  or  impossible  to initialize unions at compile
           time with most (all?)  C  compilers,  and  initialization  of
           these blocks  at  compile  time  is  very  desirable.    This
           element contains data used in  parsing  of  a  field  in  the
           command line.    For  instance,  in  parsing  an integer, the
           caller specifies the default radix of the integer here.

         o CFB_HLP is the address  of  a  caller-supplied  help  string.
           This  is  only  significant  if the flag bit _CFHPP is set in
           the CFB_FLG byte.

         o CFB_DEF is the address of a caller-supplied  default  string.
           This  is  only  significant  if the flag bit _CFDPP is set in
           the CFB_FLG byte, and only for  the  first  CFB  in  the  CFB
           chain.

         o  CFB_CC  is the address of a character characteristics table.




           This is only significant if the flag bit _CFCC is set in  the
           CFB_FLG byte.    This is the address of a 16-word table, each
           word containing 16 bits which  are  interpreted  as  8  2-bit
           characteristic entries.       The   most   significant   bits
           correspond to the lower ASCII values, etc.  The 2-bit  binary
           value has the following meaning, per character:


            o 00:    Character  may  not  be  part  of the element being
              parsed.

            o 01:  Character may be part of the element only  if  it  is
              not the first character of that element.

            o 10:  Character may be part of the element.

            o 11:      Character   may  not  be  part  of  the  element;
              furthermore, when it is typed, it  will  case  parsing  to
              begin immediately (a  wake-up  character).  Note:  wake-up
              via this mechanism is not implemented.



                Don't hesitate to use CC tables;  they only take  up  16
           bytes apiece.




             The  function  code  in  the  CFB_FC element of the command
        function block  specifies  the  operation  to  be  performed  on
        behalf of that function block.  Functions are described now.



        CFB function _CMINI:  Initialize

             Every   parse   of  a  command  line  must  begin  with  an
        initialization call.  This tells the command  library  to  reset
        its indexes,  that the user must be prompted, etc.  There may be
        NO other CFBs chained to this one, because  if  they  are,  they
        are ignored.




             The reparse  point  is the point right after this call.  If
        the setjmp method is used, then the  setjmp  environment  should
        be defined  here.    After  the reparse point, any variables etc
        which may be the  victims  of  parsing  side-effects  should  be
        initialized.



        CFB function _CMKEY:  Keyword parse

             _CMKEY parses  a  keyword  from  a given list.  The CFB_DAT
        element of the function block should point to a table of  string
        pointers, ending  with  a  NULL  pointer.  The user may type any
        unique abbreviation of a keyword,  and  may  use  completion  to
        fill out  the rest of a known match.  The address of the pointer
        to the matching string is returned in  the  CSB_RVL  element  of
        the command  state  block.    The  value is returned this way so
        that the index can be  easily  calculated,  and  because  it  is
        consistent   with   the   general   keyword   parsing  mechanism
        (_CMGSK).

             The incremental help associated  with  keyword  parsing  is
        somewhat special.    The  default  help  string is "Keyword, one
        of:" followed  by  a  list  of  keywords  which  match  anything
        already typed.    If  a help string has been supplied (indicated
        by _CFHPP) and no suppression of the default help is  specified,
        then  the  initial  part  ("Keyword,  ")  is  replaced  with the
        supplied help string and the help is otherwise the same.   If  a
        help   string  has  been  supplied  and  the  default  has  been
        supressed, then the given help string is presented unaltered.



        CFB function _CMNUM:  number

             This parses a number.  The caller supplies a radix  in  the
        CFB_DAT element  of  the  function  block.  The number parsed is
        returned (as an  int)  in  the  CSB_RVL  element  of  the  state
        block.




        CFB function _CMNOI:  guide word string

             This  function  parses  a  guide word string (noise words).
        Guide words appear between  significant  parts  of  the  command
        line, if  they  are  in  parentheses.    They  do not have to be
        typed, but if they are, they must match what is  expected.    If
        the  previous  field  ended  with  command  completion, then the
        guide words are shown automatically by the parser.

             An interesting use of guide  word  strings  is  to  provide
        alternate sets  with  the  command  chaining feature.  The parse
        (and program) flow can be altered depending on which string  was
        matched.



        CFB function _CMCFM:  confirmation

             A confirmation  is  a  carriage  return.  The caller should
        parse a confirmation as the last thing  before  processing  what
        was parsed.    Since  carriage  return  is  by default a wake-up
        character, requiring a confirmation will (if  you  don't  change
        this  wake-up  attribute)  require  that  the parse be completed
        with no extra characters typed.   A  parse  with  this  function
        code returns only a status.



        CFB function _CMGSK:  General storage keyword

             This  call provides for parsing of one of a set of keywords
        which are  not  arranged  in  a  table.    Often,  keywords  are
        actually stored  in  a  file  or  in  a linked list.  The caller
        fills in the CFB_DAT element of the command function block  with
        the  address  of  a  structure  named  CGKs (typedef CGK), which
        contains the following elements:


         o CGK_BAS:  A base address to give to the fetch routine.   Does
           not  matter  what  this  is,  as  long  as  the fetch routine
           understands it.

         o CFK_CFR:  The address  of  a  keyword  fetch  routine.    The
           routine  is called with the CGK_BAS value, and the address of
           the pointer to the previous  keyword.    It  is  expected  to
           return  the  address  of  the pointer to the next keyword, or
           with the first one if  the  passed  value  for  the  previous
           pointer is NULL.




                When  this  function  completes successfully, it returns
           the address of the pointer  to  the  string  in  the  CSB_RVL
           element in   the   command   state  block;    otherwise  (for
           unsuccessful completion), it must return NULL.    Please  see
           the   description   of   the   _CMKEY  function  code  for  a
           description of help and other processing.

                Note:  the General Keyword facility can be  used  to  do
           special  pre-processing  of candidate strings, such as hiding
           keywords which are not appropriate  for  the  program  state,
           user, access, etc.




        CFB function _CMSWI:  Parse a switch.

             This  is  intended  to  perform  switch  matching,  but  it
        currently is not implemented  and  will  return  a  result  code
        _CRIFC (invalid  function  code) if you try it.  Basically it is
        a placeholder for an unimplemented function.



        CFB function _CMTXT:  Rest of line

             This function parses the text  to  the  end  of  the  line.
        Note  that  this  does  not  parse  the trailing break character
        (i.e. the carriage return).  The text is returned  in  the  atom
        buffer  which  is  defined  (by  the  caller) by the CSB_ABF and
        CSB_ASZ elements of the command state block.



        CFB function _CMTOK:  token

             This function will parse an exact  match  of  a  particular
        token.   A  token  is  a  string of characters, whose address is
        supplied by the caller in the CFB_DAT  element  of  the  command
        function block.    This  function  is  mainly useful for parsing
        such things as commas and other separators, especially where  it
        is one  of  several  alternative parse functions.  It returns no
        value other than its status.




        CFB function _CMUQS:  unquoted string

             This function parses an unquoted string, consisting of  any
        characters other  than  spaces,  tabs, slashes, or commas.  This
        set may of course be changed by  supplying  a  CC  table.    The
        unquoted  string  is returned in the atom buffer associated with
        the command state block.



        CFB function _CMDAT:  parse date/time

             This function parses  a  date  and/or  time.    The  caller
        specifies,  via  flag  bits  in  the CFB_FLG byte of the command
        function block (as identified above) which  of  date,  time,  or
        both, are  to  be parsed.  The date and time are returned as the
        first two ints in the atom buffer which is associated  with  the
        command state   block.    Note  that  both  date  and  time  are
        returned, regardless of which were requested.

             Note  further  that  the  _CMDAT  function  is  not   fully
        implemented as of this writing.




                           Calling the COMND library


             All  that  you need to know to use the above information is
        how to call the  command  library.    Basically,  there  is  one
        support routine:  COMND().  It is used like this:

                 status = COMND (csbp, cfbp);

             Here,  "csbp"  is  the  address of the command state block,
        and "cfbp" is the address of the command function  block.    The
        COMND()  routine  returns  an  int status value, which is one of
        the following:


         o _CROK:   The  call  succeeded;    a  requested  function  was
           performed.   The  address  of  the matching function block is
           returned in the CSB_CFB element of the command  state  block,
           and other information is returned as described above.

         o _CRNOP:  The call did not succeed;  nothing matched.

         o _CRRPT:   The call did not succeed because the user took back
           some of what had already been parsed.    In  other  words,  a
           reparse  is  required,  and  your program must back up to the
           reparse point.  Note that if  you  specify  a  setjmp  buffer




           address  in  the  CSB_RSB element of the command state block,
           you will never see this value because the COMND library  will
           execute a longjmp() operation using that setjmp buffer.

         o _CRIFC:    The  call  failed  because you provided an invalid
           function code in the command function block (or in one  which
           is chained to it).  One of us has made a programming error.

         o _CRBOF:   Buffer  overflow.   The atom buffer is too small to
           contain the parsed field.

         o _CRBAS:  Invalid radix for number parse.

         o _CRAGN:  You should not see this code.  It is reserved for  a
           support-mode call to the subroutine library.




             When  you use the setjmp method of command reparsing, it is
        usually  enough  to  check  the  result  against   _CROK   only,
        everything else being treated the same (error in input).




                         Installing the COMND library



             This  part of the document describes the modules which come
        with the COMND library kit, and what you might have to  look  at
        if  the  code does not instantly work on your system (which will
        probably be the case if your system is not the same kind as  the
        one which you got it from).

             The files which come in the COMND kit are as follows:


         o  COMND.R  -  Source for this document, in a form suitable for
           the public domain formatting program called "roff4".

         o COMND.DOC - This document.

         o COMND.EDT - Edit history for the subroutine library.

         o MEM.H - A file of my (Mark  Mallett)  definitions  which  are
           used by the code in the command subroutine library.

         o COMND.H - Command library interface definitions.

         o COMNDI.H - Command library implementation definitions.

         o COMND.C  -  Primary  module  of  the COMND library.  Contains
           user input buffering and various library support routines.

         o  CMDPF1.C  -  First  module  of  parse  function   processing
           routines.

         o  CMDPF2.C  -  Second  module  of  parse  function  processing
           routines.

         o CMDPFD.C - Contains the date/time  parse  function  routines.
           This  is  included  in  a  separate  module so that it can be
           replaced with  a  stub,  since  few  programs  (that  I  have
           written,  anyway)  use  this  function, and it does take up a
           bit of code.

         o CMDPSD.C - A stub for the date/time parsing functions.   This
           can  be  linked  with  programs which do not actually use the
           date/time parse function.

         o CMDOSS.CPM - Operating system specific code which  works  for
           CP/M.   This  is  provided  as a model for the routines which
           you will have to write for your system.

         o DATE.CPM - Date/time support  routines  for  version  3.0  of
           CP/M.   This  is a module containing routines to get the date




           and time from the  operating  system,  and  to  encode/decode
           these values  to and from internal form.  This is provided as
           a model;  you will probably have to  rewrite  them  for  your
           system.   Note,  you  don't  need these routines if you don't
           use the date and time parsing function (if you use  the  stub
           instead).




                               Your Improvements



             If  you  improve  this  library  or  make  it work on a new
        operating system, I'd appreciate hearing about it so that I  can
        maintain a   proper   version.      Also   please  maintain  the
        edit/version history in the file COMND.EDT.


                                                Mark E. Mallett
                                                c/o M-TEK
                                                P.O. box 6357
                                                Nashua NH 03114

                                                voice: 603 424 8129
                                                data:  603 424 8124
                                                   (1200 baud, allow system
                                                    time to boot)
EEOOFF