This manual is for FreeM, (version 0.52.4), which is a free and
open-source implementation of the M programming language and database
system.

Copyright (C) 2014-2021 Coherent Logic Development LLC

     Permission is granted to copy, distribute and/or modify this
     document under the terms of the GNU Free Documentation License,
     Version 1.3 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.

The FreeM Manual
****************

This is the official manual for the FreeM programming language and
database.

Introduction
************

FreeM started its life as _FreeMUMPS_, written for MS-DOS and ported to
SCO UNIX by a mysterious individual going by the name of "Shalom
ha-Ashkenaz".  It was released to MUG Deutschland in 1998.  In 1999,
Ronald L. Fox ported FreeM to the Red Hat Linux 5 of the GNU/Linux
operating system.  Thereafter, maintenance was taken over by the Generic
Universal M Project, which changed its name first to Public Standard
MUMPS and then by popular request to FreeM.

   When GT.M was open-sourced in late 1999, FreeM and GUMP were
essentially abandoned.  L.D. Landis, the owner of the original GUMP
SourceForge project, and one of FreeM's significant contributors, passed
maintenance of FreeM and ownership of its SourceForge project to John
Willis in 2014.  At this point, FreeM would not compile or run on modern
Linux systems, so steps were taken to remedy the most pressing issues in
the codebase.  Limitations on the terminal size (previously hard-coded
to 80x25) were lifted, and new '$VIEW' functions were added to retrieve
the terminal size information.  '$X' and '$Y' intrinsic special
variables were updated to support arbitrary terminal sizes, and FreeM
was once again able to build and run.

   In February of 2020, work began in earnest to build a development and
support infrastructure for FreeM and begin the careful process of
refining it into a more stable and robust product.

Production Readiness
====================

FreeM is not yet production-ready.  There are several show-stopping bugs
that preclude a general release for public use:

   * 'VIEW' commands and '$VIEW' functions are used extensively to
     configure and inspect the run-time behavior of FreeM, rather than
     the "canonical" SSVN-based approach.

   * Server sockets are not yet implemented.

   * There are some situations that can result in segmentation faults
     and/or lock-ups.

   * In spite of our best efforts, this manual is not yet complete.

Contributors
============

Current contributors denoted with a _+_ following their name and role.

   * Shalom ha-Ashkenaz (Original Implementer)

   * John Best (IBM i and OS/400)

   * Jon Diamond (Library, Utilities, Conformance)

   * Ronald L. Fox (Initial port to Red Hat 5/libc-6)

   * Winfried Gerum (Code, Advice, MTA coordination)

   * Greg Kreis (Hardhats coordination, Dependencies)

   * Larry Landis (Coordination, Code, Documentation)

   * Rick Marshall (Testing, MDC Conformance) _+_

   * Lloyd Milligan (Code, Testing, Documentation)

   * Steve Morris (Code, Microsoft)

   * John Murray (Code, Conformance)

   * Wilhelm Pastoors (Testing, Documentation)

   * Kate Schell (Coordination, Conformance, MTA, MDC, Advice)

   * Lyle Schofield (Advice, Prioritization, Tracking, Project
     Management)

   * Jim Stefanik (GNU/Linux on s390x, IBM AIX, IBM z/OS)

   * Axel Trocha (Code, Utilities)

   * Dick Walters (Project Lead, Chief Coordinator, MTA)

   * David Whitten (QA Test Suite, MDC, Advice) _+_

   * David Wicksell (Debugging, Code, Testing) _+_

   * John Willis (Current Maintainer and Project Lead) _+_

   * Steve Zeck (Code)

1 FreeM Invocation
******************

1.1 Synopsis
============

     $ ./freem [_OPTIONS_...] [[-r <entryref>] | [--routine=<entryref>]]

   When FreeM loads, it searches the 'SYSTEM' namespace for the
'^%SYS.INIT' routine, and begins executing it.

   When '-r' or '--routine' are passed on the command line, FreeM will
load and run the specified routine instead of '^%SYS.INIT'.  Beginning
with FreeM 0.1.7, routines invoked in this manner are no longer required
to perform their own namespace setup with 'VIEW' commands.

1.2 Command-Line Options
========================

'-d', '--daemon'
     Starts the FreeM daemon, exactly one of which must be running at
     all times in order for FreeM interpreter and fmadm processes to
     function.

'-k', '--nofork'
     When used with '-d' or '--daemon', causes the FreeM daemon to run
     instead in the foreground.  Useful for debugging.

'-p', '--pidfile'
     When used with '-d' or '--daemon', sets the file in which the PID
     of the running daemon is stored.

'-S', '--shmsize'
     When used with '-d' or '--daemon', specifies the number of bytes of
     shared memory FreeM will allocate for the 'LOCK' table, job table,
     and IPC table.  This will determine the maximum number of
     concurrent FreeM processes and 'LOCK's available in this
     environment.

'-c', '--config'
     Specify a configuration file other than '$PREFIX/etc/freem.conf'.

'-h', '--help'
     Display a help message showing valid FreeM options.

'-i', '--import'
     Causes your UNIX environment variables to be imported into FreeM's
     local symbol table.

'-f', '--filter'
     Allows your M routines to be used as UNIX filters.

'-n _<namespace-name>_', '--namespace=_<namespace-name>_'
     Selects the FreeM namespace to be entered on startup.  Must be
     defined in '/etc/freem.conf'.

'-r _<entryref>_', '--routine=_<entryref>_'
     Causes '<entryref>' to be executed at load, instead of
     '^%SYS.INIT'.

'--standard=_<standard>_'
     Sets the default FreeM dialect to use for new routine buffers.

     Valid values for '_<standard>_' are as follows:

     'M77'
          Restricts FreeM to use only features specified by the 1977 M
          standard.
     'M84'
          Restricts FreeM to use only features specified by the 1984 M
          standard.
     'M90'
          Restricts FreeM to use only features specified by the 1990 M
          standard.
     'M95'
          Restricts FreeM to use only features specified by the 1995 M
          standard.
     'MDS'
          Restricts FreeM to use only features proposed by the
          Millennium Draft Standard.
     'M5'
          Restricts FreeM to use only features proposed by the upcoming
          M5 standard.
     'FREEM, EXTENDED'
          Removes all standards-based restrictions and allows full
          access to all FreeM features.  This is the default value of
          '$DIALECT'.

     Please note that FreeM is not entirely standards-compliant,
     regardless of the value of '_<standard>_'.

'-v', '--version'
     Displays FreeM version information.

'-x _<mcode>_', '--execute=_<mcode>_'
     Executes M code '<mcode>' at startup instead of the startup
     routine.

1.3 Using FreeM for Shell Scripting
===================================

FreeM M routines can be used as shell scripts by providing a _shebang_
line beginning with '#!/path/to/freem' as the first line of the routine.
The following example presumes that FreeM is installed at
'/usr/local/bin/freem' and uses the 'USER' namespace:

     #!/usr/local/bin/freem
     MYSCRIPT ;
      SET ^$JOB($JOB,"NAMESPACE")="USER"
      WRITE "This is output from an M routine used as a shell script.",!
      Q

   Currently, the script needs to have a '.m' file extension.  You will
also need to select an appropriate namespace in your script using the
'SET ^$JOB($JOB,"NAMESPACE")="_<namespace>_"' command before attempting
to call other routines or access globals.

   You will also need to set the script's permissions to _executable_ in
order for this to work:

     $ chmod +x _myscript.m_

2 The FreeM Daemon
******************

3 The FreeM Direct-Mode Environment
***********************************

The FreeM direct-mode environment is the mode entered when FreeM is
invoked without the use of '-r _<entryref>_' or
'--routine=_<entryref>_':

     Coherent Logic Development FreeM version 0.52.4 (x86_64-pc-linux-gnu)
     Copyright (C) 2014, 2020, 2021 Coherent Logic Development LLC

     USER>

   The prompt ('USER>') indicates the currently-active namespace.  If
any uncommitted direct-mode transactions have been started, the prompt
will change to reflect the current value of '$TLEVEL':

     TL1:USER>

   In the above example, 'TL1' indicates that '$TLEVEL' is currently
_1_.

3.1 Direct-Mode Commands
========================

When you are in direct mode, in addition to M commands, a number of
internal commands are available to help developers be more productive:

'?'
     Accesses FreeM online help.  Requires GNU 'info(1)' to be installed
     on your local system.

'events'
     Writes a list of _event classes_ and their 'ABLOCK' counts:

          USER> events

          Event Class          Processing Mode ABLOCK Count
          -----------          --------------- ------------
          COMM                 Disabled        0
          HALT                 Disabled        0
          IPC                  Disabled        0
          INTERRUPT            Disabled        0
          POWER                Disabled        0
          TIMER                Disabled        0
          USER                 Disabled        0
          WAPI                 Disabled        0
          TRIGGER              Disabled        0

'trantab'
     Displays information about any uncommitted transactions currently
     in-flight for this process.

'jobtab'
     Displays a summary of the FreeM job table.

'locktab'
     Displays a list of 'LOCK's held in the current environment.

'rbuf'
     Lists the status of all FreeM routine buffers.

'dbstats'
     Shows statistics for the BerkeleyDB global handler.

'wh'
     Forces an immediate flush of this process's 'readline' history
     buffer to disk.

'shmstat'
     Displays the configuration of FreeM shared memory.  Intended only
     for advanced debugging of the FreeM environment.

'shmpages'
     Lists the status of each FreeM shared memory page.  Intended only
     for advanced debugging of the FreeM environment.

'history'
     Prints a list of all the direct-mode commands you have entered
     across all sessions.

'rcl _<history-index>_'
     Allows you to recall command number _<history-index>_ and run it
     again.  Obtain the value for _<history-index>_ from the output of
     the 'history' command.

'!!'
     Launches a subshell within the FreeM direct mode, allowing the user
     to run operating system commands.

          USER> !!

          Type Ctrl-D to exit from the shell
          $ uname -a
          Linux hesperos 4.19.0-17-amd64 #1 SMP Debian 4.19.194-3 (2021-07-18) x86_64 GNU/Linux
          $ exit

          USER>

'!_<external-command>_'
     Invokes a shell to run _<external-command>_ from within FreeM. This
     temporarily disables 'SIGALRM' handling in FreeM, which may
     interrupt the use of event-driven M programming commands including
     'ESTART' and 'ESTOP'.

     If the '<' character is supplied immediately preceding
     _<external-command>_, FreeM will append the contents of M local
     variable '%' to _<external-command>_ as standard input.

     If the '>' character is supplied immediately preceding
     _<external-command>_, FreeM will take the standard output stream of
     _<external-command>_ and store it in M local variable '%'.

     '%' contains the number of lines in the input or output.
     '%(1)..%(_n_)' contains the data for lines 1-_n_.

   If you issue a 'HALT' command at the direct-mode prompt, you will
exit out of FreeM. However, if you issue a 'HALT' command when '$TLEVEL'
is greater than zero, you will be given the opportunity to commit or
rollback any pending transactions:

     USER> TSTART

     TL1:USER> SET ^MYGLOBAL=1

     TL1:USER> HALT

     UNCOMMITTED TRANSACTIONS EXIST:

      $TLEVEL 1*
       Operations for Transaction ID: k8xj1de
       1:	action = 0  key = ^MYGLOBAL  data = 1

     Would you like to c)ommit or r)ollback the above transactions and their operations? ($TLEVEL = 1) r

     Transactions have been rolled back.

   In the above example, the user selected 'r' to rollback the single
pending transaction.

3.2 REPL Functionality
======================

FreeM direct mode allows you to enter M expressions directly from the
direct-mode prompt, as long as they begin with a number:

     USER> S DENOM=10

     USER> 100/DENOM

     10
     USER>

   Such expressions will be immediately evaluated, and the result
printed on '$IO'.

4 Directives
************

In FreeM, a directive is an instruction embedded in an M comment, and
passed to the interpreter to affect a change that is specific to the
current routine only.

   The format of a directive is ';%_<directive-name>_', where
'_<directive-name>_' is one of the directives listed below.

4.1 %DIALECT
============

_Syntax_

     ;%DIALECT _<dialect>_

   Valid values for '_<dialect>_' are as follows:

'M77'
     Restricts FreeM to use only features specified by the 1977 M
     standard.
'M84'
     Restricts FreeM to use only features specified by the 1984 M
     standard.
'M90'
     Restricts FreeM to use only features specified by the 1990 M
     standard.
'M95'
     Restricts FreeM to use only features specified by the 1995 M
     standard.
'MDS'
     Restricts FreeM to use only features proposed by the Millennium
     Draft Standard.
'M5'
     Restricts FreeM to use only features proposed by the upcoming M5
     standard.
'FREEM, EXTENDED'
     Removes all standards-based restrictions and allows full access to
     all FreeM features.  This is the default value of '%DIALECT'.

   Please note that FreeM is not entirely standards-compliant,
regardless of the value of '%DIALECT'.

5 Intrinsic Special Variables
*****************************

5.1 $DEVICE
===========

Returns the status of the device currently in use.

   If '$DEVICE' returns _1_, an error condition exists on the current
device.  In this case, there will be two additional fields separated by
commas, indicating the internal FreeM error code representing the error
present on the device and a text explanation of the error.

5.2 $DIALECT
============

Returns or sets the language dialect of the current routine.

   Valid values for '$DIALECT' are as follows:

'M77'
     Restricts FreeM to use only features specified by the 1977 M
     standard.
'M84'
     Restricts FreeM to use only features specified by the 1984 M
     standard.
'M90'
     Restricts FreeM to use only features specified by the 1990 M
     standard.
'M95'
     Restricts FreeM to use only features specified by the 1995 M
     standard.
'MDS'
     Restricts FreeM to use only features proposed by the Millennium
     Draft Standard.
'M5'
     Restricts FreeM to use only features proposed by the upcoming M5
     standard.
'FREEM, EXTENDED'
     Removes all standards-based restrictions and allows full access to
     all FreeM features.  This is the default value of '$DIALECT'.

   Please note that FreeM is not entirely standards-compliant,
regardless of the value of '$DIALECT'.

5.3 $ECODE
==========

Returns a comma-delimited list of error conditions currently present,
and is writable.  An empty '$ECODE' indicates no errors.

5.4 $ESTACK
===========

Returns the depth of the program execution stack since the last time
'$ESTACK' was 'NEW'ed.  'NEW'-able, but not 'SET'-able.  Differs from
the '$STACK' ISV in that it is 'NEW'-able, and resets to a value of 0
when 'NEW'ed.

5.5 $ETRAP
==========

Sets or retrieves the M code that is run when an error is encountered or
'$ECODE' is set to a non-blank value.  '$ETRAP' code executes when
'$ECODE' becomes non-blank.

5.6 $HOROLOG
============

Returns a string containing the current date and time as
'<days>,<seconds>', where '<days>' represents the number of days since
the M epoch (midnight on 31 December 1840), and '<seconds>' represents
the number of seconds since the most recent midnight.

     _FreeM Extension_

     In FreeM, '$HOROLOG' is 'SET'table.  Setting '$HOROLOG' will set
     the system clock if your user account has the appropriate
     permissions.  If your user account does not have permissions to
     modify the system clock, FreeM will raise a 'ZPROTECT' error.

5.7 $IO
=======

Represents the current input/output device.  Read-only.

5.8 $JOB
========

Represents the process ID of the FreeM instance currently in use.

5.9 $KEY
========

Represents the sequence of control characters that terminated the last
'READ' command on '$IO'.

5.10 $PDISPLAY
==============

Represents the current principal display for M Windowing API operations.
Commonly used as an index into the '^$DISPLAY' structured system
variable.

5.11 $PRINCIPAL
===============

Represents the primary input/output device.  Usually a terminal or
virtual terminal.

5.12 $REFERENCE
===============

Returns the last _glvn_ referenced.  Can be 'SET', and also stacked with
'NEW'.

5.13 $QUIT
==========

If the current execution context was invoked as an extrinsic function,
'$QUIT' returns _1_.  Otherwise, returns _0_.

   When '$QUIT' returns _1_, a subsequent 'QUIT' command must have an
argument.

5.14 $STACK
===========

Represents the current stack level.

5.15 $STORAGE
=============

Represents the number of bytes of free space available in FreeM's heap.

5.16 $SYSTEM
============

Returns the MDC system ID of FreeM, as well as the environment ID of the
current environment.

5.17 $TEST
==========

'$TEST' is a writable, 'NEW'-able ISV that is _1_ if the most recently
evaluated expression was _true_.  Otherwise, returns _0_.

   '$TEST' is implicitly 'NEW'ed when entering a new stack frame for
extrinsic functions and argumentless 'DO'.  '$TEST' is _not_ implicitly
'NEW'ed when a new stack frame is entered with an argumented 'DO'.

   For single-line 'IF' or 'ELSE' expressions, you may use 'THEN' to
stack '$TEST' until the end of the line.  All new code should employ
'THEN' in this manner, as stacking '$TEST' prevents a wide range of
coding errors that can be very challenging to detect and eliminate.

5.18 $TLEVEL
============

Returns a numeric value indicating the current level of transaction
nesting in the process.  When '$TLEVEL' is greater than _0_, uncommitted
transactions exist.

5.19 $TRESTART
==============

Returns an empty string, as FreeM transaction processing does not yet
support restartable transactions.

5.20 $WITH
==========

Returns the variable prefix set by the 'WITH' command.

5.21 $X
=======

Represents the current column position of the FreeM cursor.

     In FreeM, setting '$X' will move the FreeM cursor.

5.22 $Y
=======

Represents the current row position of the FreeM cursor.

     In FreeM, setting '$Y' will move the FreeM cursor.

5.23 $ZA
========

On the 'HOME' device, always '0'.  On other devices, returns the current
position of the file opened on I/O channel '$IO'.

5.24 $ZB
========

Represents the last keystroke.

5.25 $ZCONTROLC
===============

Returns the status of the Ctrl-C flag and resets it to _false_.

5.26 $ZDATE
===========

Returns the current date, in the preferred representation for the
current system locale.

5.27 $ZERROR
============

Returns the last error message.

5.28 $ZHOROLOG
==============

Output '$HOROLOG'-style time, with the addition of milliseconds.

5.29 $ZINRPT
============

Gets or sets the interrupt enable/disable flag.

5.30 $ZJOB
==========

Returns the '$JOB' value of the parent process if the current process
was started by a 'JOB' command.  Otherwise, returns an empty string.

5.31 $ZLOCAL
============

Returns the last local variable referenced.

5.32 $ZNAME
===========

Returns the name of the current routine.

5.33 $ZPRECISION
================

Gets or sets the number of digits of numeric precision used for
fixed-point decimal arithmetic.  If '^$JOB($JOB,"MATH")' is 'IEEE754',
'$ZPRECISION' defaults to 16 digits, with a maximum of 16 digits.  If
'^$JOB($JOB,"MATH")' is 'FIXED', '$ZPRECISION' defaults to 100 digits,
with a maximum of 20,000 digits.

5.34 $ZREFERENCE
================

Returns the last _gvn_ referenced.

5.35 $ZSYSTEM
=============

Represents the return value of the last external command run with '!'.

5.36 $ZTIME
===========

Returns the system time in the preferred representation for the current
system locale.

5.37 $ZTRAP
===========

Sets or retrieves the entryref to be executed when an M program
execution error occurs under FreeM-style or DSM 2.0-style error
processing.

   In FreeM-style error processing, '$ZTRAP' is specific to each program
execution stack level.

   In DSM 2.0-style error processing, '$ZTRAP' is the same for all
program execution stack levels.

   When FreeM encounters an error, if '$ZTRAP' is nonempty and '$ETRAP'
is empty, FreeM will perform an implicit 'GOTO' to the entryref
indicated in '$ZTRAP'.

   If '$ETRAP' is nonempty when FreeM encounters an error, the value of
'$ZTRAP' is ignored, whether FreeM-style or DSM 2.0-style error
processing is enabled.

5.38 $ZVERSION
==============

Returns the version of FreeM in use, as well as the GNU host triplet for
the current FreeM build.

   See _https://wiki.osdev.org/Target_Triplet_.

6 Intrinsic Functions
*********************

6.1 $ASCII
==========

Returns the ASCII code (in decimal) for one character in a string.

     SET RESULT=$ASCII(_<string>_[,_<index>_])

   If _<index>_ is not supplied, '$ASCII' will return the ASCII code of
the first character.  Otherwise, returns the ASCII code of the character
at position _<index>_.

6.2 $CHAR
=========

Returns a string of characters corresponding to a list of ASCII codes.

     SET RESULT=$CHAR(_<ascii-code>_[,_<ascii-code>_,...])

6.3 $DATA
=========

Returns a numeric value 0, 1, 10, or 11, depending on whether a
referenced node is defined, has data, or has children:

     SET RESULT=$DATA(_<node>_)

   The return values are as follows:

     0: _<node>_ is undefined
     1: _<node>_ has data but no children
     10: _<node>_ has children but no data
     11: _<node>_ has children and data

6.4 $EXTRACT
============

Extracts a substring of a string.

   The first argument is the source string.

   The optional second argument specifies the starting position of the
substring to extract, and defaults to '1'.

   The optional third argument specifies the ending position of the
substring to extract, and defaults to the value of the second argument,
or '1'.

   This example will extract the string _FreeM_ into the local variable
'M'.

     SET NAME="FreeM is the best!"
     SET M=$EXTRACT(NAME,1,5)

   It is also possible to use '$EXTRACT' on the left-hand side of a
'SET' assignment in order to modify a substring:

     USER> SET FOO="ABCDEFG"

     USER> SET $EXTRACT(FOO,1,3)="XYZ"

     USER> WRITE FOO

     XYZDEFG

6.5 $FIND
=========

Finds the character immediately following the first occurence of a
substring within a string.

   The first argument is the source string.

   The second argument is the substring to be located.

   The optional third argument indicates the position within the source
string at which to begin searching.

6.6 $FNUMBER
============

Formats a number according to a particular set of formatting codes.

   The first argument is the number to format.

   The second argument is the series of formatting codes.

6.7 $GET
========

Returns the value of a local, global, or SSVN if the specified item is
defined, or a default value otherwise.

   The first argument is the local, global, or SSVN to be examined.

   The optional second argument is the default value to be returned if
the referenced item is undefined, and defaults to the empty string.

6.8 $JUSTIFY
============

Right-justifies a string based on a specified fixed length.

   The first argument is the source string.

   The second argument is the character length of the output.

   The optional third argument controls the number of fractional digits
to be included in the output, and defaults to the number of digits
specified in the first argument.

6.9 $LENGTH
===========

Returns the length of a string, or the number of items in a list
delimited by a specified character (as used by '$PIECE').

   The first argument is the source string.

   The optional second argument is the list delimiter to be used.  When
this argument is omitted, the length of the string in characters is
returned.

6.10 $NAME
==========

Returns the canonical name reference along with some or all of its
subscripts.

   The first argument is the source name.

   The optional second argument indicates the maximum subscript count to
be returned, and defaults to the subscript count of the source name.

6.11 $NEXT
==========

6.12 $ORDER
===========

6.13 $PIECE
===========

_Syntax_

   '$PIECE(_s_,_d_[,_n_[,_end_]])'

   Accesses the 'n'th through 'end' 'd'-delimited pieces of string 's'.

   The first argument is the string to be evaluated.

   The second argument is the delimiter to be used.

   The optional third argument is the first 'd'-delimited piece to
access, and defaults to '1'.

   The optional fourth argument is the final 'd'-delimited piece to
access, and defaults to the value of the third argument ('n').

   Can be used on the left-hand side of an expression in order to 'SET'
a value into a 'd'-delimited piece of 's', as in:

     ; ^jpw="this^is^a^piece"
     SET $PIECE(^jpw,"^",2)="isn't" ; => "this^isn't^a^piece"

6.14 $QLENGTH
=============

_Syntax_

     $QLENGTH(_expr V glvn_)

   Returns the number of subscripts in _glvn_.

   _Example_
     SET SUBCT=$QLENGTH("^GBL(1,2,3)") ; => 3

6.15 $QSUBSCRIPT
================

_Syntax_

     $QSUBSCRIPT(_expr V glvn_,_expr V n_)

   Returns the _n_th subscript of _glvn_.

   _Example_

     SET SUB=$QSUBSCRIPT("^GBL(1,2,3)",2) ; => 2

6.16 $QUERY
===========

Returns the next subscripted reference in a global.

   _Syntax_

     $QUERY(_glvn_)

   _Example_

   We will assume the following data structure exists:
     ^jpw(1)=1
     ^jpw(1,2)="foo"
     ^jpw(2)=3
     ^jpw(3)=""

   The following code will retrieve the next subscripted name after
'^jpw(1)':

     SET NEXTNAM=$QUERY(^jpw(1)) ; => ^jpw(1,2)

6.17 $RANDOM
============

_Syntax_

     $RANDOM(_max_)

   Returns a pseudo-random integer in the range of '0.._max_ - 1'

6.18 $REVERSE
=============

_Syntax_

     $REVERSE(_s_)

   Returns the reverse of string _s_.

   _Example_

     SET FOO=$REVERSE("ABC") ; => CBA

6.19 $SELECT
============

Returns a value corresponding to the first true condition in a list of
conditional expressions.  Each argument is an expression, followed by a
colon, followed by an expression whose value will be returned if the
first expression is true.  If no expressions are true, error condition
'M4' is raised.

   _Example_

     SET FOO=$SELECT(1=2:"math is broken",1=1:"the world makes sense") ; => "the world makes sense"

6.20 $STACK
===========

Returns information about the program execution stack.  The '$STACK'
intrinsic function has both a one-argument form and a two-argument form.

   _Syntax (One-Argument)_

      $STACK(_<num>_)

   If _num_ is '0', returns the command with which this FreeM instance
was invoked.

   If _num_ is '-1', returns the current program execution stack level.

   If _num_ represents a valid program execution stack depth above '0',
returns one of the following values indicating the reason for which the
referenced program execution stack level was created:

'$$'
     If '$STACK(_<num>_)="$$"', program execution stack level 'num' was
     created as the result of an extrinsic function call

_<m-command>_
     If '$STACK(_<num>_)' returns a valid M command, the referenced
     program execution stack level was created as a result of the
     _m-command_ command.

   _Syntax (Two-Argument_)

      $STACK(_<num>_,"[ECODE|MCODE|PLACE]")

   Returns the error codes, M program code, or entryref applicable to
the action that created program execution stack level _num_.

6.21 $TEXT
==========

Returns a line of code from a routine.

6.22 $TRANSLATE
===============

6.23 $VIEW
==========

6.24 $ZBOOLEAN
==============

Performs _boolean-operation_ on numeric arguments _A_ and _B_.

   _Syntax_

     SET RESULT=$ZBOOLEAN(_A_,_B_,_boolean-operation_)

   '$ZBOOLEAN' Operations (_boolean-operation_ values)

'0'
     Always _false_
'1'
     'A AND B'
'2'
     'A AND NOT B'
'3'
     'A'
'4'
     'NOT A AND B'
'5'
     'B'
'6'
     'A XOR B'
'7'
     'A OR B'
'8'
     'A NOR B'
'9'
     'A EQUALS B'
'10'
     'NOT B'
'11'
     'A OR NOT B'
'12'
     'NOT A'
'13'
     'NOT A OR B'
'14'
     'A NAND B'
'15'
     Always _true_

6.25 $ZCALL
===========

6.26 $ZCRC
==========

Returns a checksum of 'arg1'.

   _Syntax_

   '$ZCRC(_arg1_)'

   'SET VAR=$ZCRC("MUMPS") ; => 86'

6.27 $ZDATA
===========

6.28 $ZDATE
===========

Converts a '$HOROLOG' string into a human-readable date.

   _Syntax_

     SET VAR=$ZDATE($H[,_<format-string>_])

   The optional _<format-string>_ follows the same rules as the UNIX
'strftime' function.  If _<format-string>_ is omitted, the value of
'^$SYSTEM("ZDATE_FORMAT")' is used (typically '%x').

6.29 $ZEDIT
===========

6.30 $ZHOROLOG
==============

Converts date and/or time values producible by '$ZDATE' or '$ZTIME' to
'$HOROLOG' format.

   _Syntax_

     $ZHOROLOG(_<date-value>_,_<format-string>_)

   _<date-value>_ is a date or time string compatible with the formats
from '$ZDATE' or '$ZTIME'.

   _<format-string>_ is a format string of the same format as used by
the 'strptime(3)' UNIX function.

6.31 $ZKEY
==========

6.32 $ZLENGTH
=============

6.33 $ZLSD
==========

Returns the Levenshtein distance between two arguments.  The Levenshtein
distance represents the minimum number of edits needed to change the
first argument into the second argument.

   _Syntax_

   'SET VAR=$ZLSD(_arg1_,_arg2_)'

   _Example_

   'SET VAR=$ZLSD("KITTENS","MITTENS") ; => 1'

6.34 $ZM
========

6.35 $ZNAME
===========

6.36 $ZNEXT
===========

6.37 $ZORDER
============

6.38 $ZPIECE
============

6.39 $ZPREVIOUS
===============

6.40 $ZREPLACE
==============

Replaces all instances of 'arg2' with 'arg3' in string 'arg1'.

   _Syntax_ '$ZREPLACE(_arg1_,_arg2_,_arg3_)'

   _Example_

   'SET VAR=$ZREPLACE("CAT","C","B") ; => BAT'

6.41 $ZSYNTAX
=============

'$ZSYNTAX' performs a very basic syntax check on _expr V mcode_.  Checks
only for illegal commands, mismatched brackets, mismatched quotes,
missing or surplus arguments, or surplus commas.

   _Syntax_
     $ZSYNTAX(_expr V mcode_)

   If no syntax error is found, returns the empty string.

   If a syntax error is found, returns a number indicating the position
in _expr V mcode_ at which the error was found, followed by a comma, and
the FreeM error code that was found.

6.42 $ZTIME
===========

Converts a '$HOROLOG' string into a human-readable time.

   _Syntax_

     SET VAR=$ZTIME($H[,_<format-string>_])

   The optional _<format-string>_ follows the same rules as the UNIX
'strftime(3)' function.  If _<format-string>_ is omitted, the value of
'^$SYSTEM("ZTIME_FORMAT")' is used (typically '%X').

7 Commands
**********

7.1 @
=====

Executes FreeM code _expr V mcode_.

   _Syntax_

     @_expr V mcode_

   _Example (Using Variable)_

     USER> SET FOO="WRITE ""HELLO WORLD"",!"
     USER> @FOO

     HELLO WORLD

     USER>

   _Example (Using String Literal)_

     USER> @"WRITE ""HELLO WORLD"",!"

     HELLO WORLD

     USER>

   _Example (Using Indirection)_

     USER> SET FOO="BAR"

     USER> SET BAR="WRITE ""HELLO WORLD"",!"

     USER> @@FOO

     HELLO WORLD

     USER>

7.2 !
=====

_FreeM Extension_

   Invokes a shell to run _<external-command>_ from within FreeM. This
temporarily disables 'SIGALRM' handling in FreeM, which may interrupt
the use of event-driven M programming commands including 'ESTART' and
'ESTOP'.

   If the '<' character is supplied immediately preceding
_<external-command>_, FreeM will append the contents of M local variable
'%' to _<external-command>_ as standard input.

   If the '>' character is supplied immediately preceding
_<external-command>_, FreeM will take the standard output stream of
_<external-command>_ and store it in M local variable '%'.

   '%' contains the number of lines in the input or output.
'%(1)..%(_n_)' contains the data for lines 1-_n_.

7.3 !!
======

_FreeM Extension_

   Launches a subshell within the FreeM direct mode, allowing the user
to run operating system commands.

     USER> !!

     Type Ctrl-D to exit from the shell
     $ uname -a
     Linux hesperos 4.19.0-17-amd64 #1 SMP Debian 4.19.194-3 (2021-07-18) x86_64 GNU/Linux
     $ exit

     USER>

7.4 ABLOCK
==========

Increments the event block counter for one or more event classes.  While
the block counter for an event class is greater than zero, registered
event handlers for that event class will not execute, and will instead
be queued for later execution once the block counter reaches zero (all
blocks removed).

   An implicit 'ABLOCK' on all event classes occurs when an event
handler subroutine is executing.  As soon as a 'QUIT' is reached within
an event handler, an implicit 'ABLOCK' will occur.

   _Syntax_

       ABLOCK_:postcondition_

   In its argumentless form, 'ABLOCK' increments the block counter for
_all_ event classes, provided the optional _postcondition_ is either
_true_ or omitted.

       ABLOCK_:postcondition_ _evclass1_...,_evclassN_

   In its inclusive form, 'ABLOCK' increments the block counters for all
event classes named in the list, provided the optional _postcondition_
is either _true_ or omitted.

       ABLOCK_:postcondition_ (_evclass1_...,_evclassN_

   In its exclusive form, 'ABLOCK' increments the block counters for all
event classes _except for_ those named in the list, provided the
optional _postcondition_ is either _true_ or omitted.

7.5 ASSERT
==========

_FreeM Extension_

   Triggers error 'ASSERT' if the supplied truth-valued expression
_tvexpr_ is _false_ (_1_ is _true_, and _0_ is _false_), and that the
optional _postcondition_ evaluates to _true_ or is omitted.

   The 'ASSERT' error is catchable whether using standard-style,
FreeM-style, or DSM 2.0-style error processing.

   _Syntax_

      ASSERT_:postcondition_ _<tvexpr>_

   _Example_

     USER> SET DEBUG=1

     USER> ASSERT:DEBUG 1=1

     USER> ASSERT:DEBUG 1=0

     >> Error ZASSERT:  programmer assertion failed in SYSTEM::^%SYS.INIT  [$STACK = 0]
     >> ASSERT:DEBUG 1=0
                        ^

7.6 ASTART
==========

Enables asynchronous event handling for one or more event classes.

   _Syntax_

       ASTART_:postcondition_

   In its argumentless form, 'ASTART' enables asynchronous event
handling for all event classes, provided the optional _postcondition_ is
either _true_ or omitted.

       ASTART_:postcondition_ _evclass1_...,_evclassN_

   In its inclusive form, 'ASTART' enables asynchronous event handling
for all event classes named in the list, provided the optional
_postcondition_ is either _true_ or omitted.

       ASTART_:postcondition_ (_evclass1_...,_evclassN_)

   In its exclusive form, 'ASTART' enables asynchronous event handling
for all event classes _except for_ those named in the list, provided the
optional _postcondition_ is either _true_ or omitted.

7.7 ASTOP
=========

Disables asynchronous event handling for one or more event classes.

   _Syntax_

       ASTOP_:postcondition_

   In its argumentless form, 'ASTOP' disables asynchronous event
handling for all event classes, provided the optional _postcondition_ is
either _true_ or omitted.

       ASTOP_:postcondition_ _evclass1_...,_evclassN_

   In its inclusive form, 'ASTOP' disables asynchronous event handling
for all event classes named in the list, provided the optional
_postcondition_ is either _true_ or omitted.

       ASTOP_:postcondition_ (_evclass1_...,_evclassN_)

   In its exclusive form, 'ASTOP' disables asynchronous event handling
for all event classes _except for_ those named in the list, provided the
optional _postcondition_ is either _true_ or omitted.

7.8 AUNBLOCK
============

Decrements the event block counter for one or more event classes.

   _Syntax_

       AUNBLOCK_:postcondition_

   In its argumentless form, 'AUNBLOCK' decrements the block counter for
_all_ event classes, provided the optional _postcondition_ is either
_true_ or omitted.

       AUNBLOCK_:postcondition_ _evclass1_...,_evclassN_

   In its inclusive form, 'AUNBLOCK' decrements the block counters for
all event classes named in the list, provided the optional
_postcondition_ is either _true_ or omitted.

       AUNBLOCK_:postcondition_ (_evclass1_...,_evclassN_

   In its exclusive form, 'AUNBLOCK' decrements the block counters for
all event classes _except for_ those named in the list, provided the
optional _postcondition_ is either _true_ or omitted.

7.9 BREAK
=========

Interrupts running routine to allow interactive debugging.

   _Syntax_

     BREAK_:postcondition_

   In its argumentless form, 'BREAK' suspends execution of running code,
provided the optional _postcondition_ is _true_ or omitted.

     BREAK_:postcondition_ _breakflag_

   _FreeM Extension_

   In its single-argument form, 'BREAK' sets _Ctrl-C_ handling and error
handling characteristics, provided the optional _postcondition_ is
_true_ or omitted.  The following table enumerates the possible values
of _breakflag_

'0'
     Disables _Ctrl-C_ handling
'-2'
     Enables normal FreeM error handling
'2'
     Enables _Digital Standard MUMPS_ v2 error handling
'_any integer value other than 0, 2, or -2_'
     Enables _Ctrl-C_ handling

7.10 CLOSE
==========

Closes an input/output device.

   _Syntax_

     CLOSE_:postcondition_

   In its argumentless form, 'CLOSE' closes all I/O devices except for
device 0 (the 'HOME' device), provided the optional _postcondition_ is
_true_ or omitted.

     CLOSE_:postcondition_ _channel_

   In its single-argument form, 'CLOSE' closes the I/O device associated
with channel _channel_, provided that _channel_ represents a
currently-open device, and the optional _postcondition_ is _true_ or
omitted.

7.11 CONST
==========

_FreeM Extension_

   Defines a local _constant_, or variable that cannot be altered after
its initial definition, provided the optional _postcondition_ is _true_
or omitted.

   Constants must only be locals, and globals are not supported.

   _Syntax_

     CONST_:postcondition_ _mref1_=_initial-value1_,...,_mrefN_=_initial-valueN_

7.12 DO
=======

In its inclusive form, transfers program control to one or more
specified subroutines, provided the optional _postcondition_ evaluates
to _true_ or is omitted.  Line levels of entryrefs specified in the
argument list must be one, or error 'M14' is raised.

   _Syntax_

     DO[_:postcondition_] _entryref_[_:postcondition_[,...]]

   In its argumentless form, transfers control to the following block of
code where the line level is one greater than the level at which 'DO'
was encountered, provided the optional _postcondition_ evaluates to
_true_ or is omitted.

   _Syntax_

     DO[_:postcondition_]

7.13 ELSE
=========

Executes the remainder of the line of code on which 'ELSE' is
encountered only if '$TEST' evaluates to _false_, provided the optional
_postcondition_ evaluates to _true_ or is omitted.

   _Syntax_

     ELSE[_:postcondition_]

     _Non-Standard Behavior_

     FreeM allows a _postcondition_ on 'ELSE'.  While explicitly
     forbidden in the _standard_-and for good reason-it was decided that
     FreeM should allow postconditions everywhere, both for the sake of
     foolish consistency (the likes of which Emerson warned against),
     and for the benefit of entrants to a hypothetical future obfuscated
     M contest, and those with a Machiavellian predisposition to wicked
     perversions and undue cleverness.

     Using postconditions on 'ELSE' should be strictly avoided in
     production code, as they have no practical use, and may contribute
     to technical debt, hardening of the arteries, hobgoblins, a small
     mind, a surfeit of logic, climate change, Daily WTF rants, or
     meltdown of global financial markets.

7.14 FOR
========

In its argumentless form, repeatedly executes the remainder of the line
on which 'FOR' was encountered until a 'QUIT', 'GOTO', or end-of-line is
encountered, provided the optional _postcondition_ evaluates to _true_
or is omitted.

   _Syntax_

     FOR[_:postcondition_]

     _Non-Standard Behavior_

     When '$DIALECT' is set to 'FREEM', FreeM allows a _postcondition_
     on 'FOR'.  Much like postconditions on 'ELSE' and 'IF', this is
     explicitly forbidden in the _standard_.  The expression contained
     in the _postcondition_ is evaluated on each iteration of the 'FOR'
     loop, and if it does not evaluate _true_, the loop will be
     immediately exited.  The effect is roughly similar to 'WHILE'
     constructs present in other languages, but absent from standard M.

     As with all non-standard features of FreeM, please exercise caution
     when using this feature, especially in code that is expected to run
     in other, less preternaturally-inclined M implementations.

   In its sentinel form, repeatedly executes the remainder of the line
and sets a sentinel variable on each iteration, provided the optional
_postcondition_ evaluates to _true_ or is omitted.

   On the first iteration of the loop, _glvn_ will be set to
_initalizer-expression_.  On each subsequent iteration, _glvn_ will be
incremented by _increment-expression_, and the loop will terminate when
_glvn_ meets or exceeds the value of _max-expression_.

   _Syntax_

     FOR[_:postcondition_] _glvn_=_initializer-expression_:_increment-expression_:_max-expression_

   _Example_

     USER> FOR I=1:1:10 WRITE I,!

     1
     2
     3
     4
     5
     6
     7
     8
     9
     10

     USER> FOR I=2:2:10 WRITE I,!

     2
     4
     6
     8
     10

   In its explicit parameter form, a variable is set to each of a series
of explicit values, once per iteration, provided the optional
_postcondition_ evaluates to _true_ or is omitted.  The loop terminates
when no more values are available.

   _Syntax_

     FOR[_:postcondition_] _glvn_=_expr1_[,.._exprN_]

   _Example_

     USER> FOR I=60,"FOO",-3,"George",1450,$HOROLOG WRITE I,!

     60
     FOO
     -3
     George
     1450
     66106,52388

7.15 GOTO
=========

Transfers program execution to another line of code, provided the
optional _postcondition_ evaluates to _true_ or is omitted.  Attempting
to 'GOTO' a different line level or a different block when the line
level of 'GOTO' is greater than one will raise error 'M45'.

   _Syntax_

     GOTO[_:postcondition_] _entryref_

7.16 HALT
=========

Halts program execution and frees resources allocated during execution,
provided the optional _postcondition_ evaluates to _true_ or is omitted.

   _Syntax_

     HALT[_:postcondition_]

7.17 HANG
=========

Temporarily suspends the program for _expr_ seconds, provided the
optional _postcondition_ evaluates to _true_ or is omitted.  Values of
_expr_ that are zero or less than zero are ignored.

   _Syntax_

     HANG[_:postcondition_] _expr_

     _Non-Standard Behavior_

     FreeM supports sub-second values for _expr_.

7.18 IF
=======

In its argumented form, allows the remainder of the line of code
following 'IF' to execute only if all _tvexpr_s evaluate to _true_,
provided the optional _postcondition_ evaluates to _true_ or is omitted.

   _Syntax_
     IF[_:postcondition_] _tvexpr_[,..._tvexpr_]

   In its argumentless form, allows the remainder of the line of code
following 'IF' to execute only if '$TEST' evaluates to _1_, provided the
optional _postcondition_ evaluates to _true_ or is omitted.

   _Syntax_
     IF[_:postcondition_]

7.19 JOB
========

Executes _entryref_ in a separate process, provided the optional
_postcondition_ evaluates to _true_ or is omitted.

   _Syntax_
     JOB[_:postcondition_] _entryref_[:_job-parameters_[:_timeout_]]

   If _timeout_ is supplied, FreeM will set '$TEST' to _1_ if the child
process completes within _timeout_ seconds.

7.20 KILL
=========

In its inclusive form, 'KILL' deletes the specified _glvn_s and their
descendant subscripts, provided the optional _postcondition_ evaluates
to _true_ or is omitted.

   _Syntax_
     KILL[_:postcondition_] _glvn_[,..._glvn_]

   In its exclusive form, 'KILL' deletes all local variables _except_
for those specified by _lvn_, provided the optional _postcondition_
evaluates to _true_ or is omitted.

   _Syntax_
     KILL[_:postcondition_] (_lvn_[,..._lvn_])

   In its argumentless form, 'KILL' deletes all local variables,
provided the optional _postcondition_ evaluates to _true_ or is omitted.

   _Syntax_
     KILL[_:postcondition_]

7.21 KSUBSCRIPTS
================

Kills only the descendant subscripts (but not the data value) of a
referenced global, local, or SSVN (where allowed).

   _Syntax_

     KSUBSCRIPTS_:postcondition_ _var1_,...

   In the above _inclusive_ form, 'KVALUE' will kill the descendant
subscripts at each local, global, or SSVN node specified in the list
(provided that the optional _postcondition_ is _true_ or omitted), but
will leave the data value intact.

     _Note_ The below _argumentless_ and _exclusive_ forms of
     'KSUBSCRIPTS' are not implemented in FreeM, as of version 0.3.3,
     but are planned for a future release.

     KSUBSCRIPTS_:postcondition_

   In the above _argumentless_ form, 'KSUBSCRIPTS' will kill the
descendant subscripts at the root of each local variable (provided that
the optional _postcondition_ is _true_ or omitted), but will leave data
values intact.

     KSUBSCRIPTS_:postcondition_ (_var1_,...)

   In the above _exclusive_ form, 'KSUBSCRIPTS' will kill the descendant
subscripts of all local variables, _with the exception of_ those named
in the list, provided that the optional _postcondition_ is _true_ or
omitted, while leaving their data values intact.

7.22 KVALUE
===========

Kills only the data value (but not descendant subscripts) of a
referenced global, local, or SSVN (where allowed).

   _Syntax_

     KVALUE_:postcondition_ _var1_,...

   In the above _inclusive_ form, 'KVALUE' will kill the data values at
each local, global, or SSVN node specified in the list (provided that
the optional _postcondition_ is _true_ or omitted), but will leave
descendant subscripts intact.

     _Note_ The below _argumentless_ and _exclusive_ forms of 'KVALUE'
     are not implemented in FreeM, as of version 0.52.4, but are planned
     for a future release.

     KVALUE_:postcondition_

   In the above _argumentless_ form, 'KVALUE' will kill the data values
at the root of each local variable (provided that the optional
_postcondition_ is _true_ or omitted), but will leave descendant
subscripts intact.

     KVALUE_:postcondition_ (_var1_,...)

   In the above _exclusive_ form, 'KVALUE' will kill the data values of
all local variables, _with the exception of_ those named in the list,
provided that the optional _postcondition_ is _true_ or omitted, while
leaving their descendant subscripts intact.

7.23 LOCK
=========

Acquires or releases ownership of names.

   In its argumentless form, 'LOCK' releases ownership of all names
previously locked by the current process, provided the optional
_postcondition_ evaluates to _true_ or is omitted.

   _Syntax_
     LOCK[_:postcondition_]

   In its incremental form, increments or decrements the lock counter
for each specified _name_, provided the optional _postcondition_
evaluates to _true_ or is omitted.  Ownership of each _name_ is
considered to be the current process as long as the lock counter for
_name_ is greater than zero.  If _timeout_ is specified, FreeM will wait
no more than _timeout_ seconds in attempting to acquire ownership of
_name_.

   If 'LOCK' succeeds within _timeout_, '$TEST' is set to _1_.
Otherwise, '$TEST' is set to _0_.

   _Syntax_
     LOCK[_:postcondition_] [+|-]_name_[:_timeout_][,...[+|-]_name_[:_timeout_]]

   _Example_

   This example will increment the lock counter for '^JPW' and decrement
the lock counter for '^MJR'.

     LOCK +^JPW,-^MJR

   In its non-incremental form, 'LOCK' releases all 'LOCK's held by the
current process, and then attempts to acquire a lock on each _name_,
provided the optional _postcondition_ evaluates to _true_ or is omitted.
If _timeout_ is supplied, FreeM will attempt to lock _name_ for no more
than _timeout_ seconds.

   If 'LOCK' succeeds within _timeout_, '$TEST' is set to _1_.
Otherwise, '$TEST' is set to _0_.

   _Syntax_
     LOCK[_:postcondition_] _name_[:_timeout_][,..._name_[:_timeout_]]

7.24 MAP
========

Maps global name 'gvn' to be mapped to the non-default namespace _expr V
namespace_, provided the optional _postcondition_ evaluates to _true_ or
is omitted.

   _Syntax_

     MAP[_:postcondition_] GLOBAL _gvn_=_expr V namespace_

7.25 MERGE
==========

Merges the contents of one global, local, or SSVN subtree to another
global, local, or SSVN.

   _Syntax_

     MERGE A=^$JOB

   The above example will merge the '^$JOB' SSVN into the 'A' local.
Note that the FreeM implementation of 'MERGE' does not yet support
multiple merge arguments.  Returns error 'M19' if either the source or
the target variable are descendants of each other.

7.26 NEW
========

In all forms of 'NEW', _name_ must be a local variable name or
'NEW'-able structured or intrinsic system variable.

   In its inclusive form, 'NEW' saves each specified _name_ on the
process stack and removes it, provided the optional _postcondition_
evaluates to _true_ or is omitted.  When the current stack frame is
exited, the previous values are restored.

   _Syntax_

     NEW[_:postcondition_] _name_[,..._name_]

   In its exclusive form, 'NEW' saves all local variables _except_ those
named (each _name_) and removes them, provided the optional
_postcondition_ evaluates to _true_ or is omitted.  When the current
stack frame is exited, the previous values are restored.

   _Syntax_
     NEW[_:postcondition_] (_name_[,..._name_])

   In its argumentless form, 'NEW' saves all local variables and removes
them, provided the optional _postcondition_ evaluates to _true_ or is
omitted.  When the current stack frame is exited, the previous values
are restored.

   _Syntax_
     NEW_:postcondition_ _name_=_expr_

   In its initializing form, 'NEW' stacks variable _name_ and sets its
value to _expr_, provided the optional _postcondition_ evaluates to
_true_ or is omitted.  When the current stack frame is exited, the
previous value is restored.

7.27 OPEN
=========

Opens sequential or socket I/O devices and files and associates them
with a numeric FreeM input/output channel.

   _Syntax (Sequential Files)_

     OPEN_:postcondition_ _channel_:"_filename_/_access-mode_"

   Opens _filename_ for reading and/or writing, and associates the file
with FreeM I/O channel _channel_, provided that the optional
_postcondition_ is _true_ or omitted.  The below table lists the valid
options for _access-mode_:

'r'
     Read-only access
'w'
     Create a new file for write access
'a'
     Write access; append to existing file
'r+'
     Read/write access

     _I/O Path_

     You cannot specify a fully-qualified filesystem path in the FreeM
     'OPEN' command.  By default, FreeM will assume that _filename_
     exists in the directory indicated in '^$JOB($JOB,"CWD")'.  If you
     wish to access files in other directories, you must first set the
     _I/O Path_ in '^$JOB($JOB,"IOPATH")'.

     The following example will set the I/O path to '/etc':

          SET ^$JOB($JOB,"IOPATH")="/etc"

   If _channel_ was already 'OPEN'ed in the current process, calling
'OPEN' on the same channel again implicitly closes the file or device
currently associated with _channel_.

   _Syntax (Network Sockets)_

   Network sockets use a dedicated range of FreeM I/O channels ranging
from 100-255.  'OPEN'ing a socket I/O channel does _not_ implicitly
connect the socket.  Connecting the socket to the specified remote host
is accomplished by the '/CONNECT' control mnemonic supplied to the 'USE'
command.

       OPEN_:postcondition_ _socket-channel_:"_hostname-or-address_:_port_:_address-family_:_connection-type_"

   _Socket Parameters_

_socket-channel_
     The socket I/O channel to use.  This must be in the range of
     100-255.

_hostname-or-address_
     The hostname or IP address to connect to.  If a hostname is
     supplied, 'OPEN' will implictly do a name lookup, the mechanism of
     which is typically determined by the configuration of
     '/etc/nsswitch.conf' on most UNIX and UNIX-like platforms.

_port_
     The TCP or UDP port to which the socket will connect on the remote
     host.

_address-family_
     The address family to use.  Either _IPV4_ or _IPV6_.

_connection-type_
     Which connection type to use.  Either _TCP_ or _UDP_.

   If you do not specify the address family and connection type, they
will default to _IPV4_ and _TCP_, respectively.

7.28 QUIT
=========

'QUIT' will end execution of the current process level, optionally
returning _expr_, provided the optional _postcondition_ evaluates to
_true_ or is omitted.

   'QUIT' with _expr_ when an argument is not expected will raise error
'M16'; 'QUIT' without _expr_ when an argument is expected will raise
error 'M17'.

   Argumentless 'QUIT' may also be used to exit a 'FOR' loop occurring
on the same line.

   _Syntax_
     QUIT[_:postcondition_] [_expr_]

7.29 READ
=========

The 'READ' command takes input from I/O channel '$IO' and stores it into
specified variables, provided the optional _postcondition_ evaluates to
_true_ or is omitted.

   _Syntax_
     READ[_:postcondition_] _read-argument_[,..._read-argument_]

   Each _read-argument_ may be one of the following:

String Literal
     String literal _read-argument_s will be output to '$IO' unmodified.

Format Specifier
     One or more of the following:

     '!' (newline)
          Advances the cursor down by one line and returns it to the
          first column.

     '#' (form-feed)
          Advances the screen down by '$ZROWS' and moves the cursor to
          the upper-left corner of the screen.

     '?_n_' (position)
          Advances the cursor and '$X' forward to position _n_.

Single-Character Read ('*_variable-name_[_:timeout_]')
     Reads one character into variable _variable-name_.  If the optional
     _timeout_ is specified, will wait _timeout_ seconds to retrieve one
     character.  If a character is read within _timeout_ seconds,
     '$TEST' will be set to _1_.  If no character is read within
     _timeout_ seconds, '$TEST' will be set to _0_.

Variable-Length Character Read ('_variable-name_[_:timeout_]')
     Reads characters into _variable-name_ until the character or
     character pair in '^$DEVICE(_io-channel_,"OPTIONS","TERMINATOR")'
     is encountered.  If the optional _timeout_ is specified, will wait
     _timeout_ seconds to retrieve characters.  If characters are read
     within _timeout_ seconds, '$TEST' will be set to _1_.  If no
     character is read within _timeout_ seconds, '$TEST' will be set to
     _0_.

Fixed-Length Character Read ('_variable-name_#_count_[_:timeout_]')
     Reads _count_ characters into _variable-name_.  If the optional
     _timeout_ is specified, will wait _timeout_ seconds to retrieve
     characters.  If characters are read within _timeout_ seconds,
     '$TEST' will be set to _1_.  If no character is read within
     _timeout_ seconds, '$TEST' will be set to _0_.

Control Mnemonic ('/_control-mnemonic_[_(arg1[,...argN])_]')
     Outputs X3.64 control mnemonic _control-mnemonic_ to '$IO'.  Please
     see the appendix on X3.64 Control Mnemonics for more information.

7.30 SET
========

The 'SET' command places values into one or more variables, provided the
optional _postcondition_ evaluates to _true_ or is omitted.

   _Syntax_
     SET[_:postcondition_] _set-argument_[=_expression_ | _postfix-operator_][_,...set-argument_[=_expression_ | _postfix-operator_]]

   Each _set-argument_ can be:

_variable-name_
     A local variable, global variable, writable intrinsic special
     variable, or writable structured system variable.

_lhs-function_
     '$EXTRACT' or '$PIECE'.

   If any grouping of _set-argument_s is surrounded by parentheses, all
_set-argument_s in the parenthesized group will be set to the result of
_expression_.

   If _postfix-operator_ is used instead of '=_expression_', the results
of applying _postfix-operator_ to the _set-argument_ will be stored in
_set-argument_.  _postfix-operator_ may not be used following a
parenthesized group of _set-argument_s.

   _Example (postfix-operator)_

     SET A++,B-- ; increments A, decrements B

7.31 TCOMMIT
============

Commits all pending transactions to the database, provided the optional
_postcondition_ evaluates to _true_ or is omitted.

   _Syntax_
     TCOMMIT[_:postcondition_]

7.32 THEN
=========

Saves the value of '$TEST' until the end of the current line, restoring
it at the end of the current line or when a 'QUIT' is encountered.
'THEN' should be used in all new code in conjunction with 'IF'.

   _Example_
     IF 1 THEN  WRITE "HELLO!",!

7.33 THROW
==========

_FreeM Extension_

   Raises an error condition as long as the optional _postcondition_ is
_true_ or omitted.

   _Syntax_

     THROW_:postcondition_ _expr V error-code_

   _Example_

     THROW "M102"

7.34 TRESTART
=============

FreeM does not yet support restartable transactions.

7.35 TROLLBACK
==============

Rolls back all pending transactions for the current process, provided
the optional _postcondition_ evaluates to _true_ or is omitted.

   _Syntax_

     TROLLBACK[_:postcondition_]

7.36 TSTART
===========

Introduces a new transaction level, incrementing '$TLEVEL', provided the
optional _postcondition_ evaluates to _true_ or is omitted.  Any
database operations encountered when '$TLEVEL' is greater than zero will
not be committed to the database until 'TCOMMIT' is encountered.

   If a transaction is restartable, variables in the _variables-list_
will be restored to their original values on a restart of the
transaction.

   _Syntax_

     TSTART[_:postcondition_] _<variables-list>_:_<transaction-parameters>_

   _<variables-list>_ can be:

'()'
     Do not save off any local variables.  Makes the transaction
     non-restartable.

'*'
     Save off all local variables.  Makes the transaction restartable.

'_variableName_'
     Saves off only one local variable, _variableName_.  Makes the
     transaction restartable.

'(_variableName1_,...,_variableNameN_)'
     Saves off all local variables listed.  Makes the transaction
     restartable.

   _<transaction-parameters>_ can be:

'S[ERIAL]'
     Forces ACID properties on the transaction.  When 'SERIAL' is not
     selected, transactions occur in batch mode, and no attempt is made
     to guarantee ACID properties.

'T[RANSACTIONID]=_transaction-id_'
     Sets the ID of the transaction to _transaction-id_

   If you are using more than one transaction parameter, surround all of
them in parentheses and separate them with commas, e.g.:

     TSTART (FOO,BAR):(SERIAL,TRANSACTIONID="FOO")

7.37 UNMAP
==========

Removes any mapping connecting _gvn_ to a non-default namespace,
provided the optional _postcondition_ evaluates to _true_ or is omitted.

   _Syntax_

     UNMAP GLOBAL _gvn_

7.38 USE
========

Sets '$IO' to a particular FreeM I/O channel, allowing 'READ's from and
'WRITE's to the associated terminal, sequential file, or network socket.
Also sets various device parameters.

   _Syntax (Terminal)_

       USE_:postcondition_ _io-channel_[:(_right-margin_:_input-field-length_:_device-status-word_:_position_:_line-terminator_:_break-key_)]

   For terminals, _io-channel_ must be 0.

   Semantic and functional description of each device parameter TBA.

   _Syntax (Sequential Files)_

       USE_:postcondition_ _io-channel_[:_seek-position_:_terminator_:_nodelay_)]

   For sequential files, _io-channel_ must be in the range 1-99.

   Semantic and functional description of each device parameter TBA.

   _Syntax (Network Sockets)_

       USE_:postcondition_ _io-channel_

   The above syntax will set '$IO' to _io-channel_, directing successive
'READ's and 'WRITE's to _io-channel_, provided the optional
_postcondition_ is _true_ or omitted.

       USE_:postcondition_ _io-channel_:/CONNECT

   The above syntax will set '$IO' to _io-channel_, as in the prior
example, but will also attempt to connect to the host and port specified
for _io-channel_ when it was 'OPEN'ed.  The '/CONNECT' control mnemonic
is only valid for socket channels whose connection type is 'TCP'.  Using
'/CONNECT' on a 'UDP' socket channel will throw 'SCKAERR' (error code
55).

   For network sockets, _io-channel_ must be in the range 100-255.

7.39 VIEW
=========

Provides write access to various FreeM internal parameters, provided the
optional _postcondition_ evaluates to _true_ or is omitted.

   _Syntax_
     VIEW[_:postcondition_] _view-number_[:_view-argument_[:_view-argument_...]]

   The _view-number_ argument can be one of the following:

'21' - Close All Globals
     Closes all global database files open in the current process.
     Takes no arguments.

     _Syntax_
          VIEW 21

'29' - Symbol Table Copy
     Copies the primary symbol table's contents to the alternate symbol
     table.  Takes no arguments.

     _Syntax_
          VIEW 29

'52' - Set G0 Input Translation Table for '$IO'

     _Syntax_
          VIEW 52:_expr V trantab_

'53' - Set G0 Output Translation Table for '$IO'

     _Syntax_
          VIEW 53:_expr V trantab_

'54' - Set G1 Input Translation Table for '$IO'

     _Syntax_
          VIEW 54:_expr V trantab_

'55' - Set G1 Output Translation Table for '$IO'

     _Syntax_
          VIEW 55:_expr V trantab_

'62' - Set '$RANDOM' Seed Number
     Sets the seed number used by '$RANDOM' to _numexpr_.

     _Syntax_
          VIEW 62:_numexpr_

'63' - Set '$RANDOM' Parameter A
     Sets the number used for '$RANDOM' Parameter A to _numexpr_.

     _Syntax_
          VIEW 63:_numexpr_

'64' - Set '$RANDOM' Parameter B
     Sets the number used for '$RANDOM' Parameter B to _numexpr_.

     _Syntax_
          VIEW 64:_numexpr_

'65' - Set '$RANDOM' Parameter C
     Sets the number used for '$RANDOM' Parameter C to _numexpr_.

     _Syntax_
          VIEW 65:_numexpr_

'66' - Set or Clear 'SIGTERM' Handling Flag
     Enables or disables handling of 'SIGTERM' UNIX signals.  If
     _tvexpr_ evaluates to 1 (_true_), 'SIGTERM' handling will be
     enabled.  Otherwise, 'SIGTERM' handling will be disabled.

     _Syntax_
          VIEW 66:_tvexpr_

'67' - Set or Clear 'SIGHUP' Handling Flag
     Enables or disables handling of 'SIGHUP' UNIX signals.  If _tvexpr_
     evaluates to 1 (_true_), 'SIGHUP' handling will be enabled.
     Otherwise, 'SIGHUP' handling will be disabled.

     _Syntax_
          VIEW 67:_tvexpr_

'70' - Set '$ZSORT'/'$ZSYNTAX' Flag
     Selects whether '$ZS' resolves to '$ZSORT' or '$ZSYNTAX'.

     If _tvexpr_ evaluates to _true_, selects '$ZSYNTAX'.  Otherwise,
     selects '$ZSORT'.

     _Syntax_
          VIEW 70:_tvexpr_

'71' - Set '$ZNEXT'/'$ZNAME' Flag
     Selects whether '$ZN' resolves to '$ZNEXT' or '$ZNAME'.

     If _tvexpr_ evaluates to _true_, selects '$ZNAME'.  Otherwise,
     selects '$ZNEXT'.

     _Syntax_
          VIEW 71:_tvexpr_

'72' - Set '$ZPREVIOUS'/'$ZPIECE' Flag
     Selects whether '$ZP' resolves to '$ZPREVIOUS' or '$ZPIECE'.

     If _tvexpr_ evaluates to _true_, selects '$ZPIECE'.  Otherwise,
     selects '$ZPREVIOUS'.

     _Syntax_
          VIEW 72:_tvexpr_

'73' - Set '$ZDATA'/'$ZDATE' Flag
     Selects whether '$ZD' resolves to '$ZDATA' or '$ZDATE'.

     If _tvexpr_ evaluates to _true_, selects '$ZDATE'.  Otherwise,
     selects '$ZDATA'.

     _Syntax_
          VIEW 73:_tvexpr_

'79' - Set Old 'ZJOB' vs. New 'ZJOB' Flag
     If _tvexpr_ evaluates to _true_, sets the 'ZJOB' mode to new,
     otherwise, sets it to old.

     _Syntax_
          VIEW 79:_tvexpr_

'80' - Set or Clear 8-Bit Flag
     If _tvexpr_ evaluates to _true_, sets FreeM to 8-bit mode.
     Otherwise, sets FreeM to 7-bit mode.

     _Syntax_
          VIEW 80:_tvexpr_

'81' - Set or Clear PF1 Flag
     If _tvexpr_ evaluates to _true_, sets the 'PF1' flag.  We do not
     yet know what this does.

     _Syntax_
          VIEW 81:_tvexpr_

'83' - Set or Clear Text in '$ZERROR' Flag
     If _tvexpr_ evaluates to _true_, descriptive error messages will be
     included in '$ZERROR'.  Otherwise, only the short error code (i.e.
     _ZILLFUN_) will be included in '$ZERROR'.

     _Syntax_
          VIEW 83:_tvexpr_

'87' - Date Type Definition
     We believe this defines date formats for '$ZDATE', but we have not
     yet figured out how it works.

     _Syntax_
          ; Syntax unknown

'88' - Time Type Definition
     We believe this defines time formats for '$ZTIME', but we have not
     yet figured out how it works.

     _Syntax_
          ; Syntax unknown

'89' - Set Default Expression for Undefined Local Variable
     Sets the default expression to be printed when an undefined local
     variable is encountered.  We're not entirely sure what this does.

     _Syntax_
          ; Syntax unknown

'90' - Set Default Expression for Undefined Global Variable
     Sets the default expression to be printed when an undefined global
     variable is encountered.  We're not entirely sure what this does.

     _Syntax_
          ; Syntax unknown

'91' - Set Default Expression for Missing 'QUIT' Expression
     Sets the default expression to be printed when a 'QUIT' is
     encountered where a 'QUIT' argument would be expected, but was not
     provided.  We're not entirely sure what this does.

     _Syntax_
          ; Syntax unknown

'92' - Set Type Mismatch Error Flag on 'EUR2DEM'
     If _tvexpr_ evaluates to _true_, a type mismatch error will be
     thrown in 'EUR2DEM' currency conversions in certain situations that
     we do not yet understand.

     _Syntax_
          VIEW 92:_tvexpr_

'93' - Define 'ZKEY' Production Rule
     We do not know what this does.

'96' - Set Global Prefix
     Forces global database filenames to be prefixed with the result of
     _expr_.

     _Syntax_
          VIEW 96:_expr V string_

'97' - Set Global Postfix
     Forces global database filenames to be postfixed with the result of
     _expr_.

     _Syntax_
          VIEW 97:_expr V string_

'98' - Set Routine Extension
     Sets the default extension for M routine filenames to the result of
     _expr_.

     _Syntax_
          VIEW 98:_expr V string_

'101' - Set 'ierr'
     Sets the FreeM internal 'ierr' value to _intexpr_.  Used by some
     FreeM polyfills (commands or functions implemented in M code).

     _Syntax_
          VIEW 101:_intexpr_

'102' - Set 'ierr' (Deferred)
     Sets the FreeM internal 'ierr' value to _intexpr_, but only after
     the current process stack level is exited.  Used by FreeM polyfills
     to throw an error that will appear to come from the user's own code
     rather than the polyfill implementation M code.

     _Syntax_
          VIEW 102:_intexpr_

'103' - Signal 'MERGE' to '^$WINDOW' Complete
     Signals FreeM's MWAPI implementation that a 'MERGE' to '^$WINDOW'
     or descendant subscripts thereof has completed.

     _Syntax_
          VIEW 103[_:subscript_]

'110' - Set Local '$ORDER'/'$QUERY' Data Value
     Sets the local variable '$ORDER'/'$QUERY' data value to the result
     of _expr_.  We're not entirely sure what this is.

     _Syntax_
          VIEW 110:_expr_

'111' - Set Global '$ORDER'/'$QUERY' Data Value
     Sets the global variable '$ORDER'/'$QUERY' data value to the result
     of _expr_.  We're not entirely sure what this is.

     _Syntax_
          VIEW 111:_expr_

'113' - Set 'termio' Information
     We don't know what this does.

'133' - Remember 'ZLOAD' Directory on 'ZSAVE'
     We don't know what this does, but it takes a _tvexpr_.

     _Syntax_
          VIEW 133:_tvexpr_

7.40 WATCH
==========

_FreeM Extension_

   Sets a watchpoint on a global, local, or SSVN node.

   _Syntax_

   In its _argumentless_ form, 'WATCH' toggles watchpoints on and off,
provided the optional _postcondition_ is _true_ or omitted.

     WATCH[_:postcondition_]

   In its _inclusive_ form, 'WATCH' adds, removes, or examines
watchpoints, provided the optional _postcondition_ is _true_ or omitted.

   A '+' adds a new watchpoint to the following variable.

   A '-' removes an existing watchpoint for the following variable.

   A '?' examines the status of a watchpoint for the following variable.

     WATCH[_:postcondition_] [+|-|?]_var1_...,[+|-|?]_varN_

   The following example demonstrates turning watchpoint processing on
and adding a watchpoint for global variable '^jpw(1)'.  It then changes
the value of '^jpw(1)'.

     USER> WATCH

     Watchpoints enabled.

     USER> WATCH +^JPW(1)

     Added '^JPW("1")' to the watchlist.

     USER> SET ^JPW(1)="new value"

     >> WATCHPOINT:  ^JPW("1") => 'new value' (changed 1 times)

   The following example will remove that watchpoint:

     USER> WATCH -^JPW(1)

     Removed '^JPW("1")' from the watchlist.

     USER> WATCH ?^JPW(1)

     '^JPW("1")' is not being watched.

7.41 WITH
=========

_FreeM Extension_

   Sets a prefix to be applied to all subsequent local variable or
constant references.

   _Syntax_

     WITH_:postcondition_ _var-prefix_

   In the above single-argument form, sets the '$WITH' prefix to
_var-prefix_, provided that the optional _postcondition_ is either
_true_ or omitted.

   The _var-prefix_ argument may be a string literal or any valid FreeM
expression.

     WITH_:postcondition_

   In the above argumentless form, clears the '$WITH' prefix, provided
the optional _postcondition_ is either _true_ or omitted.  Equivalent to
'WITH ""'.

7.42 WRITE
==========

7.43 XECUTE
===========

7.44 ZALLOCATE
==============

_FreeM Extension_

7.45 ZBREAK
===========

_FreeM Extension_

7.46 ZDEALLOCATE
================

_FreeM Extension_

7.47 ZGO
========

_FreeM Extension_

7.48 ZHALT
==========

_FreeM Extension_

7.49 ZINSERT
============

_FreeM Extension_

7.50 ZJOB
=========

_FreeM Extension_

7.51 ZLOAD
==========

_FreeM Extension_

   Loads routine _<routine-name>_ into FreeM's routine buffer, provided
the optional _postcondition_ is _true_ or omitted.

   _Syntax_

     ZLOAD_:postcondition_ _<routine-name>_

7.52 ZNEW
=========

_FreeM Extension_

7.53 ZPRINT
===========

_FreeM Extension_

   Prints the contents of the current routine buffer, provided the
optional _postcondition_ is _true_ or omitted.

   _Syntax_

     ZPRINT_:postcondition_

7.54 ZQUIT
==========

_FreeM Extension_

   In its single-argument form, quits from _levels_ levels of the stack,
provided the optional _postcondition_ is _true_ or omitted.

   In its argumentless form, quits from '$STACK' levels of the stack,
provided the optional _postcondition_ is _true_ or omitted.

   _Syntax_

     ZQUIT_:postcondition_ [_levels_]

7.55 ZREMOVE
============

_FreeM Extension_

7.56 ZSAVE
==========

_FreeM Extension_

7.57 ZTRAP
==========

_FreeM Extension_

7.58 ZWRITE
===========

_FreeM Extension_

   Writes the names and values of M variables to '$IO'.

   _Syntax_

     ZWRITE_:postcondition_

   In the argumentless form, writes the names and values of all local
variables to '$IO' if the optional _postcondition_ is _true_ or omitted.

     ZWRITE_:postcondition_ _ArrayName_,...

   In the inclusive form, writes the names and values of all local,
global, or structured system variables specified in the list of
_ArrayName_s to '$IO' if the optional _postcondition_ is _true_ or
omitted.

     ZWRITE_:postcondition_ (_ArrayName_,...)

   In the exclusive form, writes all local variables _except_ those
specified in the list of _ArrayName_s to '$IO' if the optional
_postcondition_ is _true_ or omitted.

8 Structured System Variables
*****************************

SSVN subscripts are each described in the following format:

'_<ssvn-subscript-name>_' +/-R +/-U +/-D

   The R, U, and D flags represent Read, Update, and Delete.  A minus
sign indicates that the given operation is _not_ allowed, and a plus
sign indicates that the given operation _is_ allowed.

8.1 ^$CHARACTER
===============

Exposes character set information.  As FreeM currently only supports the
'M' character set, the first subscript of '^$CHARACTER' must always be
'"M"'.

   The following values for the second subscript are supported:

'IDENT' +R -U -D
     Returns the empty string.

'COLLATE' +R -U -D
     Returns the empty string.

'INPUT' +R -U -D
     Returns the empty string if the third subscript is 'M', otherwise,
     raises error 'M38'.

'OUTPUT' +R -U -D
     Returns the empty string if the third subscript is 'M', otherwise,
     raises error 'M38'.

8.2 ^$DEVICE
============

FreeM implements several important pieces of functionality in the
'^$DEVICE' SSVN.

   The first subscript of '^$DEVICE' represents the I/O channel of an
'OPEN'ed device.

   The following values for the second subscript are supported:

'$DEVICE'
     Returns the value of '$DEVICE' for the specified I/O channel.

'$X' +R -U -D
     Returns the horizontal cursor position of a terminal device.  Only
     valid if the I/O channel is '0'.

'$Y' +R -U -D
     Returns the vertical cursor position of a terminal device.  Only
     valid if the I/O channel is '0'.

'CHARACTER' +R -U -D
     Returns the character set of the specified I/O channel; always 'M'
     in the current implementation.

'INPUT_BUFFER' +R +U -D
     Returns or sets the contents of the input buffer for the specified
     I/O channel.  Data populated in this node will remain in the buffer
     until subsequent 'READ' command(s) remove it.  This can be used to
     perform input buffer stuffing, i.e., to fill out an interactive
     form programmatically.

'NAME' +R -U -D
     Returns the operating system's name for the file, device, or socket
     attached to the specified I/O channel.

'FD' +R -U -D
     Returns the UNIX file descriptor of the specified I/O channel.

'MODE' +R -U -D
     Returns one of 'READ', 'WRITE', 'READWRITE', or 'APPEND', depending
     on the mode in which the specified I/O channel was opened.

'EOF' +R -U -D
     Returns '1' if the I/O channel has encountered an end-of-file
     condition; '0' otherwise.  Only valid if the I/O channel is
     connected to a sequential file.

'LENGTH' +R -U -D
     Returns the length of the file connected to the I/O channel.  Only
     valid if the I/O channel is connected to a sequential file.

'NAMESPACE' +R -U -D
     Returns the current _mnemonic-space_ in use for the referenced I/O
     channel.  Always 'X364' for terminals and blank for sequential
     files.

'TYPE' +R -U -D
     Returns either '1,FILE', '2,SOCKET', or '4,TERMINAL', depending on
     the device type associated with the specified I/O channel.

'OPTIONS' -R -U -D
     The following subscripts reside beneath
     '^$DEVICE(<io-channel>,"OPTIONS")', and this subscript may not be
     accessed without one of the following third-level subscripts being
     specified:

     'DSW' +R +U -D
          Sets or returns the current _Device Status Word_ controlling
          terminal characteristics.  Only valid for I/O channel 0.

     'TERMINATOR' +R +U -D
          Sets or returns the 'READ' terminator for the specified I/O
          channel.  Must be either '$C(13,10)' or '$C(10)'.  Currently
          only supported for socket devices (those having an I/O channel
          of 100-255).

     'TERMID' +R -U -D
          Returns the type of terminal connected to channel 0.  Only
          valid for I/O channel 0.

     'ECHO' +R +U -D
          Enables or disables local echo of characters typed in a 'READ'
          command.  Only valid for I/O channel 0.  Corresponds to bit 0
          of the Device Status Word.

     'DELMODE' +R +U -D
          Enables or disables visual backspace during a 'READ' command.
          Only valid for I/O channel 0.  Corresponds to bit 2 of the
          Device Status Word.

     'ESCAPE' +R +U -D
          Enables or disables escape sequence processing during a 'READ'
          command.  Only valid for I/O channel 0.  Corresponds to bit 6
          of the Device Status Word.

     'CONVUPPER' +R +U -D
          Enables or disables automatic conversion to uppercase of
          alphabetical characters during a 'READ' command.  Only valid
          for I/O channel 0.  Corresponds to bit 14 of the Device Status
          Word.

     'DELEMPTY' +R +U -D
          Enables or disables the automatic deletion of empty strings
          supplied to a 'READ' command.  Only valid for I/O channel 0.
          Corresponds to bit 19 of the Device Status Word.

     'NOCTRLS' +R +U -D
          TBD. Only valid for I/O channel 0.  Corresponds to bit 20 of
          the Device Status Word.

     'CTRLOPROC' +R +U -D
          Enables or disables _Ctrl-O_ processing during 'READ'
          commands.  Only valid for I/O channel 0.  Corresponds to bit
          21 of the Device Status Word.

     'NOTYPEAHEAD' +R +U -D
          Enables or disables typeahead buffering during 'READ'
          commands.  Only valid for I/O channel 0.  Corresponds to bit
          25 of the Device Status Word.

   _Example_

   The following example M code opens '/etc/freem.conf' and reads its
contents line-by-line until the end of the file is reached.

      SET ^$JOB($JOB,"IOPATH")="/etc"   ; set I/O path to /etc
      OPEN 1:"freem.conf/r" ; open freem.conf for reading
      ;
      ; read until we run out of lines
      ;
      FOR  USE 1 READ LINE USE 0 QUIT:^$DEVICE(1,"EOF")  D
      . WRITE LINE,!
      ;
      CLOSE 1
      QUIT

8.3 ^$DISPLAY
=============

Provides information about the specified graphical display.  The first
subscript corresponds to a display number, which is an integer value,
often corresponding to the current value of the '$PDISPLAY' ISV.

   The following second-level subscripts and specified descendant
subscripts are supported:

'CLIPBOARD' +R +U +D
     Retrieves, sets, or erases the contents of the system clipboard.

'PLATFORM' +R -U -D
     Retrieves the name and version of the underlying window system
     platform.

'SIZE' +R -U -D
     Retrieves the display resolution of the specified graphical
     display.  For instance, a 1080p display would have a 'SIZE' value
     of '1920,1080'.

'SPECTRUM' +R -U -D
     Retrieves the color depth (number of colors supported) of the
     specified graphical display.

'COLORTYPE' +R -U -D
     Always returns 'COLOR', as monochrome and grayscale displays are
     not yet supported in FreeM.

'UNITS' +R -U -D
     Returns the measurement unit of the specified display, i.e.,
     'PIXEL'.

'TYPEFACE' +R -U -D
     The third-level subscripts beneath this subscript represent a list
     of font families available on this display.  The fourth level
     subscript is a list of sizes supported for the specified typeface,
     or '0' for vector typefaces, such as TrueType, OpenType, and Adobe
     Type 1 fonts.

8.4 ^$EVENT
===========

The '^$EVENT' SSVN is not yet implemented.

8.5 ^$GLOBAL
============

The '^$GLOBAL' structured system variable provides information about M
globals.  The first-level subscript is a global name, sans the leading
caret symbol.

   The following second-level subscripts are supported:

'BYTES' +R -U -D
     Returns the number of bytes this global occupies in fixed storage.

'BLOCKS' +R -U -D
     Returns the number of database blocks contained in this global.

'BLOCKSIZE' +R -U -D
     Returns the size of database blocks for this global.  Currently,
     FreeM only supports 1024-byte database blocks.

'FILE' +R -U -D
     Returns the full filesystem path to the database file where this
     global resides in fixed storage.

'NAMESPACE' +R +U +D
     Returns or sets the name of the FreeM namespace to which this
     global belongs.  'SET'ting this node creates a mapping for the
     specified global name to a non-default namespace.  'KILL'ing this
     node restores the mapping configuration for the specified global to
     the default.

8.6 ^$JOB
=========

FreeM fully implements '^$JOB' per ANSI X11.1-1995, as well as several
extensions proposed in the M Millennium Draft Standard.

   The first subscript of '^$JOB' represents the '$JOB' of the process.

   If you 'KILL' a first-level subscript of '^$JOB', the 'SIGTERM'
signal will be sent to the corresponding UNIX process, causing pending
transactions to be rolled back and the process to be terminated.  If the
targeted process is in direct mode, the user will be prompted with
options of either rolling back or committing any pending transactions.

   The following subscripts are supported:

'ZCOMMANDS' +R +U -D
     Contains a space-delimited list of 'Z'-commands to be treated as
     intrinsic.  Any 'Z'-command not appearing in this list will be
     treated as a user-defined command.

     For instance, if command 'ZFOO' does _not_ appear in this list,
     FreeM will attempt to run '^%ZFOO' as a subroutine when the 'ZFOO'
     command is encountered in program code.

     If you remove a command from this list, you may provide your own
     private M implementation of the command in the manner described
     above.

     If an argument is passed to a 'Z'-command you implement in M, it is
     made available to your M code in a variable whose name is specified
     in '^$JOB($JOB,"ZCOMMAND_ARGUMENT_NAME")', which defaults to '%'.

'ZCOMMAND_ARGUMENT_NAME' +R +U -D
     Returns or sets the variable name in which arguments to
     user-defined 'Z'-commands are passed.  Defaults to '%'.

'ZFUNCTIONS' +R +U -D
     Contains a space-delimited list of 'Z' functions to be treated as
     intrinsic.  Any 'Z' function not appearing in this list will be
     treated as a user-defined extrinsic function.

     For instance, if function '$ZFOO' does _not_ appear in this list,
     FreeM will attempt to return the value of '$$^%ZFOO' called as an
     extrinsic function.

     If you remove a function from this list, you may provide your own
     private M implementation of the function in the manner described
     above.

'ZSVS' +R +U -D
     Contains a space-delimited list of 'Z' special variables to be
     treated as intrinsic.  Any 'Z' special variable not appearing in
     this list will be treated as a user-defined extrinsic function
     taking no arguments.

     For instance, if the special variable '$ZFOO' does _not_ appear in
     this list, FreeM will attempt to return the value of '$$^%ZFOO'
     called as an extrinsic function.

     If you remove a built-in special variable from this list, you may
     provide your own private M implementation of the special variable
     in the manner described above.

'BREAK_HANDLER' +R +U -D
     Contains M code to be executed when the 'BREAK' command is run.

'ROUTINE_BUFFER_SIZE' +R +U -D
     Returns or sets the number of bytes allocated to each routine
     buffer.  If 'ROUTINE_BUFFER_AUTO_ADJUST' is set to '0', this
     determines the maximum size of routines that FreeM will execute.

'ROUTINE_BUFFER_COUNT' +R +U -D
     Returns or sets the number of routine buffers that FreeM will store
     in memory concurrently.  Raising this value will increase memory
     usage, but will also increase performance if your applications call
     many different routines repeatedly.

'ROUTINE_BUFFER_AUTO_ADJUST' +R +U -D
     Determines whether or not the size of routine buffers will be
     automatically adjusted at runtime.  If set to '0', routine buffers
     will be fixed to the byte size specified in 'ROUTINE_BUFFER_SIZE'
     and may be manually resized using 'ROUTINE_BUFFER_SIZE'.  If set to
     '1', routine buffers will grow automatically as necessary.

'SYMBOL_TABLE_SIZE' +R +U -D
     Returns or sets the number of bytes allocated to each of the two
     FreeM symbol tables.  If 'SYMBOL_TABLE_AUTO_ADJUST' is '1', this
     value is treated as a default, initial size.  If
     'SYMBOL_TABLE_AUTO_ADJUST' is '0', this value controls the fixed
     size of the two symbol tables.

'SYMBOL_TABLE_AUTO_ADJUST' +R +U -D
     Determines whether or not the size of the two FreeM symbol tables
     will be automatically adjusted at runtime.  If set to '0', the
     symbol table will be fixed to the byte size specified in
     'SYMBOL_TABLE_SIZE' and may be manually resized by modifying
     'SYMBOL_TABLE_SIZE'.  If set to '1', the two symbol tables will
     grow automatically as necessary.

'USER_DEFINED_ISV_TABLE_SIZE' +R +U -D
     Returns or sets the number of bytes allocated to the FreeM
     user-defined intrinsic special variable table.  If
     'USER_DEFINED_ISV_TABLE_AUTO_ADJUST' is '1', this value is treated
     as a default, initial size.  If
     'USER_DEFINED_ISV_TABLE_AUTO_ADJUST' is '0', this value controls
     the fixed byte size of the user-defined intrinsic special variable
     table.

'USER_DEFINED_ISV_TABLE_AUTO_ADJUST' +R +U -D
     Determines whether or not the size of the FreeM user-defined
     intrinsic special variable table will be automatically adjusted at
     runtime.  If set to '0', the user-defined ISV table will be fixed
     to the byte size specified in 'USER_DEFINED_ISV_TABLE_SIZE' and may
     be manually resized by modifying 'USER_DEFINED_ISV_TABLE_SIZE'.  If
     set to '1', the user-defined ISV table will grow automatically as
     necessary.

'GVN_UNIQUE_CHARS' +R +U -D
     Returns or sets the number of characters of a global name that make
     it unique, from 1 to 255.

'GVN_CASE_SENSITIVE' +R +U -D
     Returns or sets the case sensitivity of global names.  If set to
     '0', global names are case-insensitive.  If set to '1', global
     names are case-sensitive.

'GVN_NAME_SUB_LENGTH' +R +U -D
     Returns or sets the maximum number of characters of a global name
     plus all of its subscripts, from 1-255.

'GVN_SUB_LENGTH' +R +U -D
     Returns or sets the maximum number of characters of a single global
     subscript, from 1-255.

'SINGLE_USER' +R +U -D
     If set to '1', FreeM will skip all file locking operations on
     globals, as well as the 'LOCK' and 'ZALLOCATE' tables.  If set to
     '0', FreeM will enforce file locking on both.

     Setting 'SINGLE_USER' to '1' will improve FreeM performance, but
     you must _ONLY_ use this on systems where you are absolutely sure
     that only one FreeM process will run at any given time, as running
     multiple instances of FreeM concurrently when any of them are set
     to 'SINGLE_USER' mode _will_ cause database and 'LOCK'/'ZALLOCATE'
     table corruption!

'CHARACTER' +R -U -D
     Returns the character set of the job.

'CWD' +R +U -D
     Returns or sets the current working directory of the job.

'OPEN' +R -U -D
     The '^$JOB($JOB,"OPEN",<channel>' subscripts list the open I/O
     channels in the specified job.

'ENGINES' +R -U -D
     Returns or sets the storage engines for various FreeM subsystems.

     The following table lists the types of storage engines that can be
     defined.

     'GLOBAL' +R +U -D
          Returns or sets the global handler for a particular FreeM
          namespace:

          The following code would set the global handler for the
          'SYSTEM' namespace to 'BERKELEYDB':

          'SET ^$JOB($JOB,"ENGINES","GLOBAL","SYSTEM")="BERKELEYDB"'

     'LOCAL' +R -U -D
          Returns the local handler for a particular FreeM namespace.
          Always 'BUILTIN' in the current FreeM release.

'BERKELEYDB,FLUSH_THRESHOLD' +R +U -D
     Returns or sets the number of write operations that will be cached
     in the BerkeleyDB global handler prior to flushing BerkeleyDB's
     cache to disk.

'EVENT' +R +U +D
     The subtree contained under '^$JOB($J,"EVENT")' defines
     asynchronous event handlers for the current job.  Please see
     _Asynchronous Event Handling_ for more information.

'GLOBAL' +R -U -D
     Returns the global environment of the job.

'IOPATH' +R +U -D
     Returns or sets the _I/O path_ to be used by the 'OPEN' command.

'PRIORITY' +R +U -D
     Returns or sets the _nice_ value of the FreeM job.

'REVSTR' +R +U -D
     When set to 1, allows '$EXTRACT' to accept negative values.

'ROUTINE' +R -U -D
     Returns the name of the routine currently being executed by the
     job.

'SYMTAB' +R +U -D
     Returns or sets the current local variable symbol table in use.

     FreeM supports two unique and independent symbol tables, allowing
     FreeM programs to maintain two independent sets of identically- or
     differently-named local variables per process.

     The default symbol table is '0', and the alternate symbol table is
     '1', corresponding to the valid values for '^$JOB($JOB,"SYMTAB")'.

     Setting this subscript to values other than '0' or '1' will result
     in a 'ZINVEXPR' error.

'$PDISPLAY' +R -U -D
     Returns the value of '$PDISPLAY' for the job.

'$PRINCIPAL' +R -U -D
     Returns the value of '$PRINCIPAL' for the job.

'$TLEVEL' +R -U -D
     Returns the current transaction level (value of '$TLEVEL' for the
     job.

'$IO' +R -U -D
     Returns the current value of '$IO' for the job.

'USER' +R -U -D
     Returns the UID of the user owning the job.

'GROUP' +R -U -D
     Returns the GID of the group owning the job.

'NAMESPACE' +R +U -D
     Returns or sets the name of the job's currently-active namespace.

'MATH' +R +U -D
     Returns or sets the mode in which decimal comparisons and
     arithmetic calculations are conducted.  Valid values are 'FIXED',
     for fixed-point decimals having up to 20,000 digits of precision,
     as determined by the '$ZPRECISION' intrinsic special variable, and
     'IEEE754', to use IEEE 754 floating-point decimals.  When in
     'IEEE754' mode, floating-point numbers support up to 16 digits of
     numeric precision.

     'IEEE754' mode will make mathematical calculations significantly
     faster, especially when accelerated by a floating-point processor,
     at the expense of precision and accuracy.

     'FIXED' mode is recommended for financial calculations, or where
     precision and accuracy are valued over performance.  'FIXED' is the
     default mode of FreeM operation.

     Attempting to 'SET' this node to values other than 'FIXED' or
     'IEEE754' will set '$ECODE' to 'M29'.

8.7 ^$LOCK
==========

The first-level subscript of '^$LOCK' is a lock name.  The value at each
node is the PID which owns the lock, a comma, and the lock counter for
the locked resource.

   Attempting to 'SET' or 'KILL' any node in '^$LOCK' will raise error
'M29'.

8.8 ^$ROUTINE
=============

The '^$ROUTINE' SSVN exposes a list of routines available in the current
FreeM namespace, as well as additional attributes further describing
each routine.

   The first-level subscript is the name of a FreeM routine minus the
leading caret symbol.

   The following second-level subscripts are supported:

'CHARACTER' +R -U -D
     Returns the character set of the routine.

'NAMESPACE' +R -U -D
     Returns the name of the FreeM namespace in which the routine
     resides.

'PATH' +R -U -D
     Returns the full filesystem path to the routine in fixed storage.

8.9 ^$SYSTEM
============

The '^$SYSTEM' SSVN exposes system-level implementation details.

   The following first-level subscripts are supported:

'DEFPSIZE' +R -U -D
     Returns the default size in bytes of the symbol table and routine
     buffer memory partition.

'DEFUDFSVSIZ' +R -U -D
     Returns the default size in bytes of the user-defined intrinsic
     special variable table.

'DEFNSIZE' +R -U -D
     Returns the default size of the 'NEW' stack, in number of entries.

'MAXNO_OF_RBUF' +R -U -D
     Returns the maximum number of routine buffers.

'DEFNO_OF_RBUF' +R -U -D
     Returns the default number of routine buffers.

'DEFPSIZE0' +R -U -D
     Returns the default size in bytes of each routine buffer.

'NO_GLOBLS' +R -U -D
     Returns the maximum number of globals that can be concurrently
     opened.

'NO_OF_GBUF' +R -U -D
     Returns the number of global buffers.

'NESTLEVLS' +R -U -D
     Returns the depth of the 'DO', 'FOR', 'XECUTE' stack.

'PARDEPTH' +R -U -D
     Returns the maximum depth of the parser's parameter stack.

'PATDEPTH' +R -U -D
     Returns the maximum number of _patatom_s in each pattern.

'TRLIM' +R -U -D
     Returns the trace limit of the 'BUILTIN' global handler.

'ARGS_IN_ESC' +R -U -D
     Returns the maximum number of arguments in a terminal escape
     sequence.

'ZTLEN' +R -U -D
     Returns the maximum length of '$ZTRAP'.

'FUNLEN' +R -U -D
     Returns the maximum length of the '$ZF' (function key) variable.

'NAME_LENGTH' +R -U -D
     Returns the maximum length of variable names in the current FreeM
     build.  Compatible with the same SSVN node in _Reference Standard
     M_

'STRING_MAX' +R -U -D
     Returns the maximum length of character strings in the current
     FreeM build.  Compatible with the same SSVN node in _Reference
     Standard M_

'$NEXTOK' +R -U -D
     Returns a value indicating whether or not the '$NEXT' intrinsic
     function is allowed.  In FreeM, '$NEXT' is always enabled, and this
     SSVN is provided solely for compatibility with _Reference Standard
     M_. Thus, this SSVN node always returns '1'.

'EOK' +R -U -D
     Returns a value indicating whether or not 'E' notation for
     exponents is allowed.  In FreeM, this feature is always enabled,
     and this SSVN is provided solely for compatibility with _Reference
     Standard M_. Thus, this SSVN node always returns '1'.

'OFFOK' +R -U -D
     Returns a value indicating whether or not offsets are allowed in
     'DO' and 'GOTO'.  In FreeM, this feature is always enabled, and
     this SSVN is provided solely for compatibility with _Reference
     Standard M_. Thus, this SSVN node always returns '1'.

'BIG_ENDIAN' +R -U -D
     Returns a 1 if FreeM is running on a big-endian platform, or a 0
     otherwise.  Compatible with the same SSVN node in _Reference
     Standard M_.

'NAMESPACE' +R -U -D
     The descendant subscripts of this node list each namespace in the
     current FreeM environment.

'MAPPINGS,GLOBAL' +R -U -D
     Descendant subscripts of this node represent global name mappings
     set in '^$GLOBAL(_gvn_,"NAMESPACE")'

8.10 ^$WINDOW
=============

The '^$WINDOW' SSVN has no nodes yet defined.  However, completing a
'MERGE' to this SSVN will cause MWAPI-ish things to happen, and further
work is proceeding on MWAPI implementation.

8.11 ^$ZPROCESS
===============

Provides access to 'procfs', which is a filesystem-like abstraction for
UNIX process metadata contained in '/proc', as well as features for
examining and controlling the state of processes external to the FreeM
interpreter.

   The first subscript always represents the _process ID_ of the
external process being acted upon.

   The following values for the second subscript are supported:

'EXISTS' +R -U -D
     Returns 1 if the referenced process exists; 0 otherwise.

'ATTRIBUTE' +R -U -D
     Exposes the '/proc' files as descendant subscripts, i.e., 'WRITE
     ^$ZPROCESS(2900,"ATTRIBUTE","cmdline"),!' would print the initial
     command line used to invoke process ID 2900.  Note that the third
     subscript (the immediate descendant of the 'ATTRIBUTE' subscript)
     is case sensitive.

'SIGNAL' -R +U -D
     Allows signals to be sent to the referenced process.  The following
     subscript is an integer value corresponding to the desired signal
     number.  You may obtain a list of signal numbers on most UNIX
     systems with the command 'kill -l'.

     The constants '%SYS.SIGNAL.HUP', '%SYS.SIGNAL.INT',
     '%SYS.SIGNAL.KILL', and '%SYS.SIGNAL.TERM' are provided for
     convenient use of this SSVN subscript.

8.12 ^$ZRPI
===========

The '^$ZRPI' structured system variable provides easy access to
general-purpose input/output (GPIO) pins on Raspberry Pi single-board
computers.

   To initialize the GPIO subsystem, 'SET ^$ZRPI("INITIALIZE")=1'.

   Individual pins are accessed through '^$ZRPI("GPIO",<pin>,...)',
where '<pin>' represents the desired pin number.  Descendant subscripts
of '^$ZRPI("GPIO",<pin>)' are as follows:

'MODE' +R +U -D
     Represents the operating mode of the selected pin.  One of 'INPUT',
     'OUTPUT', 'PWM_OUTPUT', or 'GPIO_CLOCK'.

'DIGITAL' +R +U -D
     Reads or writes the selected pin digitally.  The value is limited
     to '1' or '0'.

'ANALOG' +R +U -D
     Reads or writes the selected pin in an analog fashion.  The value
     represents analog voltage.

9 Operators
***********

9.1 Unary +
===========

Forces a number to positive, whether positive or negative.  Also forces
numeric coercion of strings.

9.2 Unary -
===========

9.3 + (Add)
===========

9.4 += (Add/Assign)
===================

9.5 ++ (Postfix Increment)
==========================

9.6 - (Subtract)
================

9.7 -= (Subtract/Assign)
========================

9.8 - (Postfix Decrement)
=========================

9.9 * (Multiply)
================

9.10 *= (Multiply/Assign)
=========================

9.11 / (Divide)
===============

9.12 /= (Divide/Assign)
=======================

9.13 \ (Integer Divide)
=======================

9.14 \= (Integer Divide/Assign)
===============================

9.15 # (Modulo)
===============

9.16 #= (Modulo/Assign)
=======================

9.17 ** (Exponentiate)
======================

9.18 **= (Exponentiate/Assign)
==============================

9.19 < (Less Than)
==================

9.20 <= (Less Than or Equal To)
===============================

9.21 > (Greater Than)
=====================

9.22 >= (Greater Than or Equal To)
==================================

9.23 _ (Concatenate)
====================

9.24 _= (Concatenate/Assign)
============================

9.25 = (Equals)
===============

9.26 [ (Contains)
=================

9.27 ] (Follows)
================

9.28 ]] (Sorts After)
=====================

9.29 ? (Pattern Match)
======================

9.30 & (Logical AND)
====================

9.31 ! (Logical OR)
===================

9.32 ' (Logical NOT)
====================

9.33 @ (Indirect)
=================

10 Sequential I/O
*****************

11 Network I/O
**************

Network I/O in FreeM is supplied through I/O channels 100-255.  The
normal 'READ' and 'WRITE' syntax will work with network sockets, with a
few exceptions.

11.1 Opening and Connecting a Client Socket
===========================================

To open a client socket and connect to it, you will need to call the
'OPEN' command and the 'USE' command:

       ;
       ; Set socket read terminator to LF
       ;
       SET ^$DEVICE(100,"TERMINATOR")=$C(10)
       ;
       ; Open an IPv4 TCP socket to mail.mydomain.com on port 25 (SMTP)
       ; and connect to it
       ;
       OPEN 100:"mail.mydomain.com:25:IPV4:TCP"
       USE 100:/CONNECT
       ;
       ; Read a line of input from the remote host and write it to the terminal
       ;
       NEW LINE
       READ LINE
       USE 0
       WRITE LINE,!
       ;
       ; CLOSE the socket and disconnect
       ;
       CLOSE 100
       QUIT

12 Extended Global References
*****************************

12.1 Standard Extended Global References
========================================

FreeM supports extended global references, allowing the user to access
globals in namespaces other than the current default namespace and the
'SYSTEM' namespace, without switching to the other namespace.

   For example, if you are in the 'USER' namespace, the following code
will print the value of '^VA(200,0)' in the 'VISTA' namespace:

       WRITE ^|"VISTA"|VA(200,0),!

   You may also use an expression that resolves to a string containing a
valid namespace name:

       SET NS="VISTA"
       WRITE ^|NS|VA(200,0),!

12.2 File Path Extended Global References
=========================================

If a namespace is configured to use the 'BUILTIN' global handler, FreeM
supports accessing a global database file by way of its filesystem path.

   The following file path extended global reference will write the
value of '^VA(200,0)', assuming the '^VA' database file exists at path
'/home/jpw/^VA':

       WRITE ^/home/jpw/VA(200,0),!

13 Global Aliasing
******************

FreeM provides the ability to set alternative names for M global
variables.

   To create an alias of '^FOO' named '^BAR', use the following command:

       SET ^$JOB($JOB,"ALIASES","^BAR")="^FOO"

   If such an alias is set, any reference to global variable '^BAR' will
affect '^FOO' instead of '^BAR' until '^$JOB($JOB,"ALIASES","^BAR")' is
'KILL'ed.  If '^BAR' existed prior to the definition of this alias, its
data will be unavailable to and unaffected by application code.

14 Global Mappings
******************

FreeM supports creating persistent mappings through which arbitrary
global names may be mapped to specific namespaces.  This allows non-'%'
globals to be stored in the 'SYSTEM' namespace, or '%' globals to be
stored in non-'SYSTEM' namespaces.

   To map the '^FOO' global to the 'SYSTEM' namespace, any of the
following will work:

       MAP GLOBAL ^FOO="SYSTEM"
       SET ^$GLOBAL("FOO","NAMESPACE")="SYSTEM"
       SET ^$SYSTEM("MAPPINGS","GLOBAL","^FOO")="SYSTEM"

   There is no functional difference in any of the three approaches; the
method you choose is a matter of personal preference.

   To remove the above mapping, any of the following examples will also
work:

       UNMAP GLOBAL ^FOO
       KILL ^$GLOBAL("FOO","NAMESPACE")
       KILL ^$SYSTEM("MAPPINGS","GLOBAL","^FOO")

15 Transaction Processing
*************************

FreeM implements a significant subset of the transaction processing
features from _ANSI X11.1-1995_.  This allows a series of database
operations to be conducted all at once, either in batch mode (where
concurrency is not disturbed), or in serial mode (where writes are
guaranteed to be atomic, consistent, isolated, and durable.

15.1 Theory of Operation
========================

FreeM uses a pessimistic concurrency control mechanism for 'SERIAL'
transactions, meaning that any 'TSTART' command that includes the
'SERIAL' transaction parameter will cause the process to acquire the
transaction processing mutex, which prevents any process but the one
holding the mutex from performing any database access (read or write)
until either 'TCOMMIT' or 'TROLLBACK' is called, either committing or
rolling back the transaction, respectively.

   Any transaction in between its 'TSTART' and 'TCOMMIT'/'TROLLBACK' is
said to be _in-flight_.  During the in-flight stage, pending database
operations are held only in memory and after-image journals.

   FreeM maintains a list of all globals affected during a transaction
in-flight.  When a 'TCOMMIT' is reached, FreeM will generate a
_checkpoint_ of each global database file to be changed by the
transaction.  These checkpoints allow all FreeM globals to be restored
to their pre-transaction state if a 'TCOMMIT' should fail part of the
way through its operation.

   Checkpoints can have one of two modes:

'CP_REMOVE'
     Used for globals that did not exist prior to the beginning of this
     transaction.  Simply marks the entire global database file for
     deletion in case of 'TCOMMIT' failure.

'CP_RESTORE'
     Used for globals that _did_ exist prior to the beginning of this
     transaction.  In this case, the entire global database file is
     copied to a new file with a '.chk' extension.  In cases of
     'TCOMMIT' failure, 'CP_RESTORE' checkpoint files will be restored
     over the partially-modified live database file.

   The below example shows a few database operations and checkpoints for
a transaction in-flight using the 'trantab' direct-mode command:

TL1:USER> trantab
 $TLEVEL 1*
  Operations for Transaction ID: 6ea14aad-b8f1-47f9-9f52-4f513f892bc0 [RESTARTABLE SERIAL]

   OP. NO.   ACTION         KEY/DATA
   -------   ------         --------
   1         SET            ^FOO=3
   2         KILL           ^FOO
   3         SET            ^jpw=10
   4         SET            ^BRANDNEW=6

  Global database checkpoints:

   GLOBAL                        MODE                FILES
   ------                        ----                -----
   ^BRANDNEW                     CP_REMOVE           IN:   /usr/local/var/freem/USER/globals/^BRANDNEW
   ^jpw                          CP_RESTORE          IN:   /usr/local/var/freem/USER/globals/^jpw
                                                     OUT:  /usr/local/var/freem/USER/globals/^jpw.23390.1.chk
   ^FOO                          CP_RESTORE          IN:   /usr/local/var/freem/USER/globals/^FOO
                                                     OUT:  /usr/local/var/freem/USER/globals/^FOO.23390.1.chk

   In the above example, 'IN' files are the live database file that will
be overwritten or removed, and 'OUT' files are the checkpoints
themselves.  Note that 'OUT' files are only used for 'CP_RESTORE'
checkpoints.

16 Asynchronous Event Handling
******************************

Asynchronous event handling in FreeM follows the specifications of the
unpublished MDC _Millennium Draft Standard_.

16.1 Setting Up Async Event Handlers
====================================

Asynchronous event handlers are configured through the '^$JOB'
structured system variable for job-specific events, and the '^$SYSTEM'
structured system variable for system-wide events.  In order to become
proficient in writing asynchronous event handling code, you need to be
aware of several important concepts:

_Event Classes_
     _Event classes_ denote particular categories of events.  These
     include 'COMM', 'HALT', 'IPC', 'INTERRUPT', 'POWER', 'TIMER',
     'TRIGGER', and 'USER' event classes.  At present, only 'INTERRUPT'
     and 'TRIGGER' event classes are supported.

_Event Identifiers_
     _Event identifiers_ denote the precise nature of the event that has
     occurred.  For instance, resizing the terminal window in which a
     FreeM job is running will send an event of class 'INTERRUPT' with
     an event identifier of 'SIGWINCH' (short for _SIGnal WINdow
     CHange_).

_Event Handlers_
     _Event handlers_ are M routines or subroutines that can be
     registered to run when an event of a certain event class occurs.

_Event Registration_
     _Event registration_ is the process of modifying the '^$JOB' or
     '^$SYSTEM' SSVN to associate a particular event class and event
     identifier with an event handler routine or subroutine.

_Event Blocking and Unblocking_
     _Event blocking_ is the means by which asynchronous event handling
     can be temporarily suspended.  For example, asynchronous events are
     temporarily and implicitly blocked for the duration of event
     handler execution, unless explicitly un-blocked within the event
     handler.  Event handling can also be blocked and unblocked
     programatically from M code using the 'ABLOCK' and 'AUNBLOCK'
     commands.

   The following sections of this chapter will take you step-by-step
through setting up an event handler for 'SIGWINCH' signal handling.

16.2 Registering an Asynchronous Event Handler
==============================================

To register a job-specific event handler that will only execute in the
current FreeM process, use the following syntax:

       SET ^$JOB($JOB,"EVENT",_event-class_,_event-identifier_)=_entryref_

   To register a system-wide event handler that will execute in every
FreeM process, use the following syntax:

       SET ^$SYSTEM("EVENT",_event-class_,_event-identifier_)=_entryref_

   For example, use the following to register '^RESIZE' as an
asynchronous event handler for 'SIGWINCH' events:

       SET ^$JOB($JOB,"EVENT","INTERRUPT","SIGWINCH")="^RESIZE"

   This by itself will not enable asynchronous event handling, as it
merely _registers_ an event handler, associating it with event class
'INTERRUPT' and event identifier 'SIGWINCH'.

16.3 Enabling Asynchronous Event Handling
=========================================

In order to enable asyncronous event handling, the 'ASTART' command is
used.  In the following example, we will enable asynchronous event
handling for the 'INTERRUPT' event class:

       ASTART "INTERRUPT"

   Omitting the '"INTERRUPT"' argument will enable asynchronous event
handling for _all_ event classes.  See 'ASTART' in the commands section
for more details.

   Once this is done, any event handlers registered for the 'INTERRUPT'
event class in '^$JOB' will be executed asynchronously as appropriate.

   Please note that 'ASTART "TRIGGER"' is run implicitly at FreeM
startup, to ensure consistency in applications depending on business
logic contained in system-wide database triggers.  To disable this
behavior, add 'ASTOP "TRIGGER"' to the 'LOCAL.STARTUP' routine in the
'USER' namespace.  If 'LOCAL.STARTUP' does not yet exist in your
environment, you may create it by typing 'fmadm edit routine USER
LOCAL.STARTUP' from your UNIX command-line shell.

16.4 Disabling Asynchronous Event Handling
==========================================

To disable asynchronous event handling, the 'ASTOP' command is used.  In
the following example, we will disable asynchronous event handling for
the 'INTERRUPT' event class:

       ASTOP "INTERRUPT"

   Omitting the '"INTERRUPT"' argument will disable asynchronous event
handling for _all_ event classes.  See 'ASTOP' in the commands section
for more details.

   You may also disable asynchronous event handling for a specific event
identifier by 'KILL'ing the appropriate node in the '^$JOB' SSVN, which
unregisters the event handler altogether.  The following example will
unregister the event handler for the 'SIGWINCH' event identifier:

       KILL ^$JOB($JOB,"EVENT","INTERRUPT","SIGWINCH")

16.5 Temporarily Blocking Asynchronous Event Handling
=====================================================

To temporarily block processing of specific event classes, you will use
the 'ABLOCK' command.  'ABLOCK' functions incrementally, that is, each
successive call to 'ABLOCK' will increment a counter of blocks held for
the specified event class or classes, and each successive call to
'AUNBLOCK' will decrement that counter.  Event handling for the
specified event classes will be blocked as long as the 'ABLOCK' counter
for those classes is greater than zero.  Thus, event blocking is
cumulative, in a manner similar to M incremental locks.

   The following example blocks asynchronous event handling for the
'INTERRUPT' event class:

       ABLOCK "INTERRUPT"

   Note that entering an event handler causes an implicit 'ABLOCK' of
_all_ event classes, to prevent event handlers from interrupting other
event handlers during their execution.  This may be overridden by
calling 'AUNBLOCK' for one or more event classes within an event
handler.  However, unblocking event handling during an event handler
should be done with great caution, as this can make the flow of code
execution somewhat unpredictable, especially if M globals are modified
inside of an event handler routine or subroutine.

   Modifying M globals within event handlers is allowed but strongly
discouraged, as doing so can lead to logical corruption of the database.
If you must modify an M global within an event handler, guard all such
operations with prodigious and careful use of 'LOCK's, ensuring that
such modifications occur in the desired logical order.

17 Database Triggers
********************

Database triggers use the FreeM asynchronous event handling subsystem to
allow a FreeM process to execute arbitrary M code when a particular
action occurs on a particular global.

   To set up a database trigger, you must set up an event handler for
event class 'TRIGGER'.  The event identifier must be in the format of
'"<action>:<gvn>"', where _<gvn>_ is a global variable name, and
_<action>_ is one of the following:

'DATA'
     Trigger will fire when the '$DATA' intrinsic function is called on
     _<gvn>_.

'GET'
     Trigger will fire when _<gvn>_ is read from.

'INCREMENT'
     Trigger will fire when intrinsic function '$INCREMENT' is called on
     _<gvn>_.

'KILL'
     Trigger will fire when _<gvn>_ is 'KILL'ed.

'NEXT'
     Trigger will fire when intrinsic function '$NEXT' is called on
     _<gvn>_.

'ORDER'
     Trigger will fire when intrinsic function '$ORDER' is called on
     _<gvn>_.

'QUERY'
     Trigger will fire when intrinsic function '$QUERY' is called on
     _<gvn>_.

'SET'
     Trigger will fire when 'SET _<gvn>_=_value_' occurs.

'ZDATA'
     Trigger will fire when intrinsic function 'ZDATA' is called on
     _<gvn>_.

   When a 'TRIGGER' event occurs, the '"GLOBAL"' node of the '^$EVENT'
structured system variable will be populated with the global reference
that invoked the trigger event.

   If a 'SET' or 'KILL' trigger was the source of the 'TRIGGER' event,
the 'OLD_VALUE' node of '^$EVENT' will be populated with original value
of '^$EVENT("GLOBAL")' prior to the change, and 'NEW_VALUE' will be
populated with the new value.  This allows triggers to contain logic to
undo database changes.  This functionality can also be used to provide
auditing of specific global changes.

   The following example shows a trigger implemented for 'SET'
operations on the '^DD' global.

     TRIGGER ;
         ;
         ; Set up a SET trigger on ^DD
         ;
         SET ^$JOB($JOB,"EVENT","TRIGGER","SET:^DD")="ONSET^TRIGGER"
         ;
         ; Enable the TRIGGER event class
         ;
         ASTART "TRIGGER"
         ;
         ; Try setting a node in ^DD
         ;
         SET ^DD(1)="Test"
         ;
         ; Quit
         ;
         QUIT
         ;
         ;
     ONSET ;
         WRITE "The "_^$EVENT("GLOBAL")_" global node was SET.",!
         QUIT

   You can also set up a trigger that applies to all FreeM processes by
setting descendant subscripts of '^$SYSTEM("EVENT","TRIGGER",...)'
instead of using '^$JOB($JOB,"EVENT","TRIGGER",...)'.

18 Synchronous Event Handling
*****************************

19 GUI Programming with MWAPI
*****************************

20 User-Defined Z Commands
**************************

21 User-Defined Z Functions
***************************

22 User-Defined SSVNs
*********************

23 Language Dialects
********************

24 System Library Routines
**************************

24.1 ^%ZCOLUMNS
===============

This routine is the implementation of the '$ZCOLUMNS' intrinsic special
variable.

24.2 ^%SYS.INIT
===============

This routine is the default startup routine for FreeM running in direct
mode.

   Running 'DO INFO' from direct mode will use this routine to display
information about the current FreeM status and namespace configuration.

24.3 ^%ZHELP
============

This routine implements the online help feature of FreeM, invoked by
typing '?' in direct mode.  It simply asks the underlying system to
execute the command 'info freem'.

24.4 ^%ZROWS
============

This routine is the implementation of the '$ZROWS' intrinsic special
variable.

25 Interrupt Handling
*********************

When FreeM receives the 'SIGINT' signal, either by pressing 'Ctrl-C'
during program execution, or by external signal from the operating
system, the FreeM daemon, or another external process, one of two things
can happen, depending on the state of the '$ZI' special variable:

'$ZI' evaluates _true_
     In this case, the 'ZINRPT' error is raised, and normal error
     handling procedures apply.  If neither '$ZTRAP' nor '$ETRAP' are
     set, FreeM prints an error diagnostic on the home device and will
     exit the FreeM process in application mode (i.e., the 'freem'
     executable was started with the '--routine' or '-r' flag), or
     return to the direct mode prompt otherwise.

     This is the default behavior of FreeM.
'$ZI' evaluates _false_
     In this case, no error is raised, but the '$ZCONTROLC' flag is set.
     In this mode of operation, it is up to program code to check for
     '$ZCONTROLC' and take appropriate action.

     Checking the value of '$ZCONTROLC' will reset it to _false_.

   In either case, if asynchronous event handling is enabled for the
'INTERRUPT' event class (i.e., 'ASTART "INTERRUPT"' or 'ASTART' have
been invoked by the current process), an asynchronous event of event
class 'INTERRUPT' and event identifier 'SIGINT' will be enqueued.

26 Error Processing
*******************

FreeM exposes three means of processing M program execution errors:

_FreeM-style error processing_
     FreeM-style error processing exposes a read/write error trap in
     '$ZTRAP'.  The contents of '$ZTRAP' must be either empty or a valid
     M entryref, to which FreeM will 'GOTO' if an error occurs.  Each
     program stack execution level can have its own '$ZTRAP' error
     handler enabled.

_DSM 2.0-style error processing_
     DSM 2.0-style error processing emulates the '$ZTRAP' behavior of
     Digital Standard MUMPS v2.  It has the same behavior as FreeM-style
     error handling, with the exception that in DSM 2.0-style error
     processing, only one '$ZTRAP' error handler is set across all
     program stack execution levels.

_Standard error processing_
     Standard error processing uses the 'NEW'-able '$ETRAP' variable to
     store error handler code, which may be any valid M code.  The code
     in '$ETRAP' will run when an error occurs or the '$ECODE' ISV
     becomes non-empty.  Stack information for standard error handling
     is provided by the '$STACK' ISV, the '$STACK()' intrinsic
     pseudo-function, and the 'NEW'-able '$ESTACK' ISV.

     If '$ETRAP' is non-empty when an error condition occurs, '$ZTRAP'
     is ignored, regardless of whether FreeM-style or DSM 2.0-style
     error processing is enabled at the time of the error.

   For further information on switching between FreeM-style and DSM
2.0-style '$ZTRAP' error handling, see the documentation for the 'BREAK'
command.

27 FreeM Error Codes
********************

'ZINRPT' - _interrupt_
     Raised when an interrupt signal is received.

'ZBKERR' - _BREAK point_
     Raised when a 'BREAK' point is reached.

'ZNOSTAND' - _non standard syntax_
     Raised when features incompatible with the current value of
     '$DIALECT' are used.

'ZUNDEF' - _variable not found_
     Raised when an undefined local or global variable is accessed.
     This error code has been deprecated in favor of standard error
     codes 'M6' and 'M7'.

'ZLBLUNDEF' - _label not found_
     Raised when a referenced label is not found.

'ZMISSOPD' - _missing operand_
     Raised when an operand is missing from an expression.

'ZMISSOP' - _missing operator_
     Raised when an operator is missing from an expression.

'ZILLOP' - _unrecognized operator_
     Raised when an unrecognized operator is encountered in an
     expression.

'ZQUOTER' - _unmatched quotes_
     Raised when unbalanced quotes are encountered.

'ZCOMMAER' - _comma expected_
     Raised when a comma is expected in program syntax but is not found.

'ZASSIGNER' - _equals '=' expected_
     Raised when an equals sign is expected in program syntax but is not
     found.

'ZARGER' - _argument not permitted_
     Raised when an argument is encountered in a syntactic position
     where arguments are not permitted.

'ZSPACER' - _blank ' ' expected_
     Raised when a space character is expected in program syntax but is
     not found.

'ZBRAER' - _unmatched parentheses_
     Raised when unbalanced parentheses are detected in program syntax.

'ZLVLERR' - _level error_
     Raised when a level error occurs.

'ZDIVER' - _divide by zero_
     Raised when program code attempts to divide by zero.  Deprecated in
     favor of standard error code 'M9'.

'ZILLFUN' - _function not found_
     Raised when program code attempts to call intrinsic or extrinsic
     functions that are not defined.

'ZFUNARG' - _wrong number of function arguments_
     Raised when an intrinsic or extrinsic function is called with the
     wrong number of arguments.

'ZZTERR' - _ZTRAP error_
     Raised when a '$ZTRAP' error occurs.

'ZNEXTERR' - _$NEXT/$ORDER error_
     Raised when an error occurs in '$NEXT' or '$ORDER'.

'ZSELER' - _$SELECT error_
     Raised when an error occurs in '$SELECT'

'ZCMMND' - _illegal command_
     Raised when program code attempts to execute an illegal command.

'ZARGLIST' - _argument list incorrect_
     Raised when the argument list supplied to an M language element
     does not match that language element's syntactic requirements.

'ZINVEXPR' - _invalid expression_
     Raised when an invalid expression is encountered.

'ZINVREF' - _invalid reference_
     Raised when an invalid variable reference is encountered.

'ZMXSTR' - _string too long_
     Raised when a string is encountered that exceeds
     '^$SYSTEM("STRING_MAX")'.

'ZTOOPARA' - _too many parameters_
     Raised when too many parameters are passed to a function or
     subroutine.

'ZNOPEN' - _unit not open_
     Raised when attempting to access an I/O channel that has not been
     opened.

'ZNODEVICE' - _unit does not exist_
     Raised when attempting to access a device that does not exist.

'ZPROTECT' - _file protection violation_
     Raised when attempting to access a file or device to which you do
     not have permission.

'ZGLOBER' - _global not permitted_
     Raised when attempting to use a global in a syntactic element where
     global variables are not permitted.

'ZFILERR' - _file not found_
     Raised when attempting to access a file that does not exist.

'ZPGMOV' - _program overflow_
     Raised when a program overflows the limits of a routine buffer.

'ZSTKOV' - _stack overflow_
     Raised when 'DO', 'FOR', or 'XECUTE' nesting levels exceed the
     value in '^$SYSTEM("NESTLEVLS")'.

'ZSTORE' - _symbol table overflow_
     Raised when program code attempts to store too much data in the
     local symbol table.  Should not occur unless symbol table
     auto-adjust is disabled.

'ZNOREAD' - _file won't read_
     Raised when program code attempts to read from an unreadable file.

'ZNOWRITE' - _file won't write_
     Raised when program code attempts to write to an unwritable file.

'ZNOPGM' - _routine not found_
     Raised when an attempt is made to load or execute a routine that
     does not exist in the current namespace.

'ZNAKED' - _illegal naked reference_
     Raised when an attempt is made to use an illegal naked reference.

'ZSBSCR' - _illegal subscript_
     Raised when an illegal subscript access is attempted.

'ZISYNTX' - _insert syntax_
     Raised when illegal insert syntax is used.

'ZDBDGD' - _database degradation_
     Raised when database corruption is detected.

'ZKILLER' - _job kill signal_
     Raised on a job kill signal.

'ZHUPER' - _hangup signal_
     Raised on a job hangup signal.

'ZMXNUM' - _numeric overflow_
     Raised when an assignment or expression result exceeds
     '$ZPRECISION'.

'ZNOVAL' - _function returns no value_
     Raised when a function does not return a value.  Extrinsic
     functions must 'QUIT' with a value.

'ZTYPEMISMATCH' - _type mismatch_
     Raised when a type mismatch occurs.

'ZMEMOV' - _out of memory_
     Raised when FreeM runs out of heap memory.

'ZNAMERES' - _error in name resolution_
     Raised when an attempted name resolution fails.

'ZSCKCREAT' - _error creating socket_
     Raised when an error occurs creating a socket for network I/O.

'ZSCKIFAM' - _invalid address family (must be IPV4 or IPV6)_
     Raised when the address family specified in an 'OPEN' command for a
     socket I/O channel is not IPV4 or IPV6.

'ZSCKITYP' - _invalid connection type (must be TCP or UDP)_
     Raised when the connection type specified in an 'OPEN' command for
     a socket I/O channel is not 'TCP' or 'UDP'.

'ZSCKIPRT' - _invalid port number_
     Raised when the port number specified in an 'OPEN' command for a
     socket I/O channel is invalid.  Valid TCP and UDP ports are in the
     range of 1-65535.

'ZSCKCERR' - _connection error_
     Raised when an error occurs on a 'USE <channel>:/CONNECT' command.

'ZSCKAERR' - _USE action invalid for connection type (possibly CONNECT on UDP socket?)_
     Raised when an attempt is made to 'USE <channel>:/CONNECT' on a UDP
     socket I/O channel.  The UDP protocol is connectionless.

'ZSCKACON' - _attempted to CONNECT an already-connected socket_
     Raised when an attempt is made to 'USE <channel>:/CONNECT' on a TCP
     socket I/O channel that is already connected.

'ZSCKNCON' - _attempted to READ from a disconnected TCP socket_
     Raised when an attempt is made to 'READ' a TCP socket that has not
     yet been connected.

'ZSCKEOPT' - _error setting socket options_
     Raised when an error is encountered while setting socket options.

'ZSCKERCV' - _error in READ from socket_
     Raised when an error occurs in a socket I/O channel 'READ'.

'ZSCKESND' - _error in WRITE to socket_
     Raised when an error occurs while attempting to 'WRITE' to a socket
     I/O channel.

'ZNORPI' - _^$ZRPI only supported on Raspberry Pi hardware_
     Raised when an attempt is made to use the '^$ZRPI' structured
     system variable on a platform other than the Raspberry Pi
     single-board computer.

'ZCREDEF' - _cannot redefine CONST_
     Raised when attempts are made to redefine a 'CONST' after its
     initial definition.

'ZCMODIFY' - _cannot modify CONST_
     Raised when attempts are made to change the value of a 'CONST'.

'ZFILEXWR' - _cannot open existing file for WRITE_
     Raised when an attempt is made to open an existing file in write
     (but not append) mode.

'INEWMULT' - _initializing NEW with multiple setarguments not supported_
     Raised when you attempt to use multiple setarguments with
     initializing 'NEW', e.g.  'NEW X=2,Y=3'.

'ZECODEINV' - _invalid value for $ECODE_
     Raised when attempts are made to set '$ECODE' to an invalid error
     code value.  Obsolete and replaced by standard error code 'M101'.

'ZASSERT' - _programmer assertion failed_
     Raised when an 'ASSERT' expression's result is not true.

'ZUSERERR' - _user-defined error_
     Raised when program code calls 'THROW' with an error code argument
     for which the first character is 'U', or when '$ECODE' is set to an
     error code for which the first character is 'U'.

     Custom error messages for 'ZUSERERR' may be set in
     '^$JOB($JOB,"USER_ERRORS",<user_error_code>)', where
     '<user_error_code>' represents the custom error code.

     For example:

          USER> S ^$JOB($JOB,"USER_ERRORS","UBLACKHOLE")="black hole encountered"

          USER> THROW UBLACKHOLE

          >> Error UBLACKHOLE:  black hole encountered in SYSTEM::^%SYS.INIT  [$STACK = 0]
          >> THROW UBLACKHOLE
                            ^

'ZSYNTERR' - _syntax error_
     Raised when a syntax error without a more specific error code is
     encountered.

'ZCTRLB' - _break_
     Pseudo-error used by the FreeM debugger.  Not visibly raised in
     normal program operation.

'ZASYNC' - _asynchronous interruption_
     Pseudo-error used by the FreeM asynchronous events subsystem.  Not
     visibly raised in normal program operation.

'M1' - _naked indicator undefined_
     Raised when an attempt is made to use a naked reference before the
     naked indicator is set.

'M2' - _invalid combination with $FNUMBER code atom_

'M3' - _$RANDOM seed less than 1_

'M4' - _no true condition in $SELECT_

'M5' - _line reference less than zero_

'M6' - _undefined local variable_

'M7' - _undefined global variable_

'M8' - _undefined intrinsic special variable_

'M9' - _divide by zero_

'M10' - _invalid pattern match range_

'M11' - _no parameters passed_

'M12' - _invalid line reference (negative offset)_

'M13' - _invalid line reference (line not found)_

'M14' - _line level not 1_

'M15' - _undefined index variable_

'M16' - _argumented QUIT not allowed_

'M17' - _argumented QUIT required_

'M18' - _fixed length READ not greater than zero_

'M19' - _cannot copy a tree or subtree onto itself_

'M20' - _line must have a formal parameter list_

'M21' - _algorithm specification invalid_

'M22' - _SET or KILL to ^$GLOBAL when data in global_

'M23' - _SET or KILL to ^$JOB for non-existent job number_

'M24' - _change to collation algorithm while subscripted local variables defined_

'M26' - _non-existent environment_

'M27' - _attempt to rollback a transaction that is not restartable_

'M28' - _mathematical function, parameter out of range_

'M29' - _SET or KILL on structured system variable not allowed by implementation_

'M30' - _reference to global variable with different collating sequence within a collating algorithm_

'M31' - _control mnemonic used for device without a mnemonic space selected_

'M32' - _control mnemonic used in user-defined mnemonic space which has no associated line_

'M33' - _SET or KILL to ^$ROUTINE when routine exists_

'M35' - _device does not support mnemonic space_

'M36' - _incompatible mnemonic spaces_

'M37' - _READ from device identified by empty string_

'M38' - _invalid structured system variable subscript_

'M39' - _invalid $NAME argument_

'M40' - _call-by-reference in JOB actual parameter_

'M41' - _invalid LOCK argument within a transaction_

'M42' - _invalid QUIT within a transaction_

'M43' - _invalid range value ($X, $Y_

'M44' - _invalid command outside of a transaction_

'M45' - _invalid GOTO reference_

'M56' - _identifier exceeds maximum length_

'M57' - _more than one defining occurrence of label in routine_

'M58' - _too few formal parameters_

'M60' - _illegal attempt to use an undefined SSVN_

'M101' - _invalid value for $ECODE_

'M102' - _synchronous and asynchronous event processing cannot be simultaneously enabled for the same event class_

'M103' - _invalid event identifier_

'M104' - _ETRIGGER event identifier for IPC event class does not match job process identifier_

28 Debugging
************

29 System Configuration
***********************

29.1 Installing FreeM
=====================

29.2 Build Configuration
========================

When configuring FreeM with the supplied 'configure' script, there are
some FreeM-specific options that may be used to compile in optional
features, or exclude default ones:

'--enable-mwapigtk' (EXPERIMENTAL)
     Enables experimental support for the M Windowing API using the GTK3
     libraries.  Requires that you have GTK 3 libraries, their headers,
     and their dependencies installed on your system.

     Please consult your operating system's documentation for the
     correct commands to install the required libraries.

     _Example_

          $ ./configure --enable-mwapigtk
          $ make
          $ sudo make install

'--enable-berkeleydb' (EXPERIMENTAL)
     Enables experimental support for using the BerkeleyDB database as a
     global handler for FreeM global namespaces.  Requires that you have
     the 'libdb' library, headers, and dependencies installed on your
     system.

     Please consult your operating system's documentation for the
     correct commands to install the required libraries.

     _Example_

          $ ./configure --enable-berkeleydb
          $ make
          $ sudo make install

'--without-readline'
     Builds FreeM without GNU 'readline' support, even if 'readline' is
     installed on your system.

     Please note that building FreeM without GNU 'readline' will also
     exclude REPL functionality and all direct-mode utility commands,
     i.e.  'events', 'tdump', 'shmstat', and 'shmpages'.

     _Example_

          $ ./configure --without-readline
          $ make
          $ sudo make install

30 Accessing FreeM from C Programs
**********************************

FreeM provides a library, 'libfreem.so', as well as corresponding header
file 'freem.h', allowing C programmers to write programs that access
FreeM globals, locals, structured system variables, subroutines, and
extrinsic functions.  This functionality can be used to implement
language bindings and database drivers for external systems.

   In order to be used in your C programs, your C programs must link
with 'libfreem.so' and include 'freem.h'.  This will allow your C code
access to the function prototypes, data structures, and constants
required for calling the 'libfreem.so' APIs.

   You must exercise caution in developing programs that interface with
FreeM through 'libfreem.so' to ensure that all 'libfreem.so' API calls
are serialized, as FreeM and the 'libfreem.so' library are neither
thread-safe nor reentrant.

   You must also avoid setting signal handlers for 'SIGALRM', as FreeM
uses 'SIGALRM' to manage timeouts for 'LOCK', 'READ', and 'WRITE'.

30.1 freem_ref_t Data Structure
===============================

The 'libfreem' API uses a 'struct' of type 'freem_ref_t' in order to
communicate state, pass in values, and return results.

   The data structure, defined in 'freem.h', looks like this:

typedef struct freem_ref_t {

    /*
     * The 'reftype' field can be one of:
     *
     *  MREF_RT_LOCAL
     *  MREF_RT_GLOBAL
     *  MREF_RT_SSV
     */
    short reftype;

    /*
     * The 'name' field is the name of the local variable,
     * global variable, or SSVN (without ^ or ^$).
     */
    char name[256];

    /*
     * Returned data goes in a string, so you've got to figure out the
     * whole M canonical number thing yourself. Good luck. :-)
     */
    char value[STRLEN];

    short status;

    unsigned int subscript_count;
    char subscripts[255][256];

} freem_ref_t;

   _freem_ref_t Members_

'reftype'
     The 'reftype' member determines whether we are operating on a local
     variable, a global variable, or a structured system variable.  It
     may be set to any of following constants: 'MREF_RT_LOCAL',
     'MREF_RT_GLOBAL', or 'MREF_RT_SSV'.

'name'
     The 'name' member contains the name of the global, local, or SSVN
     to be accessed.  You _must not_ include leading characters, such as
     '^' or '^$'.

'value'
     This member contains the value read from or the value to be written
     to the global, local, or SSVN.

'status'
     This member gives us various API status values after the API call
     returns.  In general, this value is also returned by each API
     function.

'subscript_count'
     The number of subscripts to be passed into the API function being
     called.  This value represents the maximum index into the first
     dimension of the 'subscripts' array.

'subscripts'
     A two-dimensional array containing the subscripts to which we are
     referring in this API call.

30.2 freem_ent_t Data Structure
===============================

The 'freem_function()' and 'freem_procedure()' APIs in 'libfreem' use
the 'freem_ent_t' struct in order to indicate the name of the entry
point being called, any arguments being passed to it, and the return
value of the called function (not used for 'freem_procedure()').

   The data structure, defined in 'freem.h', looks like this:

typedef struct freem_ent_t {

    /* name of function or procedure entry point */
    char name[256];

    /* return value */
    char value[STRLEN];

    /* value of ierr on return */
    short status;

    /* argument count and array */
    unsigned int argument_count;
    char arguments[255][256];

} freem_ent_t;

   _freem_ent_t Members_

'name'
     The 'name' member contains the name of the extrinsic function or
     procedure to be called.

'value'
     This member contains the value returned by the function called.
     Not used by 'freem_procedure()'.

'status'
     This member gives us the value of 'ierr' after the function or
     procedure call returns.  The possible values of 'ierr' are listed
     in 'merr.h'.

'argument_count'
     The number of arguments to be passed into the extrinsic function or
     procedure being called.  This value represents the maximum index
     into the first dimension of the 'arguments' array.

'arguments'
     A two-dimensional array containing the arguments to be passed into
     the extrinsic function or procedure being called.

30.3 freem_init()
=================

Initializes 'libfreem' in preparation for calling other APIs.

   _Synopsis_

   'pid_t freem_init(char *namespace_name);'

   _Parameters_

'namespace_name'
     Specifies the namespace to use.

   _Return Values_

   Returns the process ID of the 'libfreem' process on success, or '-1'
on failure.

   _Example_

   This example prompts the user to enter a FreeM namespace and then
attempts to initialize 'libfreem' to use the selected namespace.

#include <stdio.h>
#include <string.h>
#include <freem.h>

int main(int argc, char **argv, char **envp)
{
    char namespace[256];

    /* get the namespace name to use */
    printf("Enter FreeM namespace to use: ");
    fgets(namespace, 255, stdin);

    /* remove the trailing newline */
    namespace[strcspn(buffer, "\n")] = '\0';

    /* initialize libfreem using the provided namespace */
    if(freem_init(namespace) == TRUE) {
        printf("\nSuccess\n");
    }
    else {
        printf("\nFailure\n");
    }

    return 0;
}

30.4 freem_version()
====================

Returns the version of FreeM in use.

   _Synopsis_

   'short freem_version(char *result);'

   _Parameters_

'result'
     The 'result' parameter is a pointer to a buffer in which the FreeM
     version information will be returned.  The caller must allocate
     memory for this buffer prior to calling this API. It should be at
     least 20 bytes in length.

   _Return Value_

   Returns '0'.

   _Example_

   This example will display the FreeM version on standard output.

#include <stdio.h>
#include <string.h>
#include <freem.h>

int main(int argc, char **argv, char **envp)
{
    char version[20] = {0};

    freem_init(``USER'');
    freem_version(version);

    printf(``FreeM version:  %s\n'', version);

}

30.5 freem_set()
================

Sets a FreeM local node, global node, or writable SSVN node.

   _Synopsis_

   'short freem_set(freem_ref_t *ref);'

   _Parameters_

'freem_ref_t'
     This parameter is a pointer to a 'freem_ref_t' struct.  The caller
     must allocate the memory for this struct.

   _Return Value_

   Returns 'OK' on success, or one of the other error values defined in
'merr.h'.

   _Example_

   This example sets the value 'blue' into global node '^car("color")'.

#include <stdio.h>
#include <string.h>
#include <freem.h>

int main(int argc, char **argv, char **envp)
{
    freem_ref_t ref;

    /* we're setting a global */
    ref.reftype = MREF_RT_GLOBAL;

    /* access global "car" */
    strcpy(ref.name, "car");

    /* set up the subscripts */
    ref.subscript_count = 1;
    strcpy(ref.subscripts[0], "color");

    /* use the USER namespace */
    freem_init("USER");

    /* write the data out */
    freem_set(&ref);

}

30.6 freem_get()
================

Retrieves a FreeM local node, global node, or writable SSVN node.

   _Synopsis_

   'short freem_get(freem_ref_t *ref);'

   _Parameters_

'freem_ref_t'
     This parameter is a pointer to a 'freem_ref_t' struct.  The caller
     must allocate the memory for this struct.

   _Return Value_

   Returns 'OK' on success, or one of the other error values defined in
'merr.h'.

   _Example_

   This example retrieves the character set of the current process.

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <freem.h>

int main(int argc, char **argv, char)
{
    pid_t pid;
    freem_ref_t ref;

    /* get the PID of this process */
    pid = getpid();

    /* we want to access an SSVN */
    ref.reftype = MREF_RT_SSV;

    /* set up the name and subscripts */
    strcpy(ref.name, "JOB");

    ref.subscript_count = 2;
    sprintf(ref.subscripts[0], "%d", pid);
    strcpy(ref.subscripts[1], "CHARACTER");

    /* initialize libfreem, using the USER namespace */
    freem_init("USER");

    /* call libfreem API */
    freem_get(&ref);

    /* output the character set info */
    printf("PID %d character set is '%s'\n", pid, ref.value);
}

30.7 freem_kill()
=================

Deletes a FreeM local node, global node, or killable SSVN node, as well
as all of its children.

   _short freem_kill(freem_ref_t *ref);_

   _Parameters_

'freem_ref_t'
     This parameter is a pointer to a 'freem_ref_t' struct.  The caller
     must allocate the memory for this struct.

   _Return Value_

   Returns 'OK' on success, or one of the other error values defined in
'merr.h'.

   _Example_

#include <stdio.h>
#include <string.h>
#include <freem.h>

int main(int argc, char **argv, char **envp)
{
    freem_ref_t ref;

    /* we're killing a global node */
    ref.reftype = MREF_RT_GLOBAL;

    /* access global "car" */
    strcpy(ref.name, "car");

    /* set up the subscripts */
    ref.subscript_count = 0;

    /* use the USER namespace */
    freem_init("USER");

    /* kill the global and all its descendant subscripts */
    freem_kill(&ref);
}

30.8 freem_data()
=================

30.9 freem_order()
==================

30.10 freem_query()
===================

30.11 freem_lock()
==================

30.12 freem_unlock()
====================

30.13 freem_tstart()
====================

30.14 freem_trestart()
======================

30.15 freem_trollback()
=======================

30.16 freem_tlevel()
====================

30.17 freem_tcommit()
=====================

30.18 freem_function()
======================

30.19 freem_procedure()
=======================

Appendix A FreeM Administrator
******************************

The 'fmadm' utility is the preferred method of managing a FreeM
installation, and will eventually replace all of the existing utilities.
Unlike the existing, legacy utilities, 'fmadm' presents a consistent,
simple interface for all FreeM management tasks, and is namespace-aware.
This appendix will document each 'fmadm' facility as it is implemented,
until all of the legacy utilities have been replaced.

   The 'fmadm' utility's functions all follow the below, consistent
syntax:

     usage:  fmadm <action> <object> <namespace> [OPTIONS]

   The _action_ keyword can be one of the following:

_list_
     Lists instances of _object_

_examine_
     Examines a single instance of _object_

_verify_
     Verifies the integrity of _object_

_compact_
     Compacts _object_

_repair_
     Repairs integrity problems in _object_

_create_
     Creates an instance of _object_

_remove_
     Removes an instance of _object_

_import_
     Imports an _object_

_export_
     Exports an _object_

_backup_
     Creates a backup of _object_

_restore_
     Restores a backup of _object_

_migrate_
     Migrates an instance of _object_ from an older FreeM version to the
     current version

_edit_
     Edits an instance of _object_

   The _object_ keyword can be one of the following:

_lock_
     The FreeM 'LOCK' table.

     Supported actions are 'list' and 'remove'.

_zallocate_
     The FreeM 'ZALLOCATE' table.

     No actions yet implemented.

_journal_
     FreeM after-image journaling.

     Supported actions are 'examine' and 'restore'.

     The 'examine' action will dump the after-image journal entries for
     the selected namespace in human-readable format.

     The 'restore' action will play after-image journals forward for the
     selected namespace.

_namespace_
     FreeM namespaces (collections of M routines and globals).

     No actions yet implemented.

_global_
     The database files representing each FreeM _global_.

     Supported actions are 'list', 'examine', 'remove', and 'verify'.

_routine_
     An M routine, stored as a '.m' file.

     Supported actions are 'list', 'examine', 'remove', 'import',
     'export', 'backup', and 'edit'.

_job_
     A UNIX process representing an instance of the FreeM runtime.

     Supported actions are 'list' and 'examine'.

Appendix B FreeM Legacy Utilities
*********************************

B.1 Global Compactor (gcompact)
===============================

Compacts the specified global in place.

   _Syntax_

     gcompact _/path/to/global/file_

B.2 Block Examiner (gfix)
=========================

The _gfix_ interactive utility program permits navigation of the B-tree
structure of the specified global a block at a time.

   _Syntax_

     gfix _</path/to/global/file>_

B.3 Global Repair Tool (grestore)
=================================

This utility will fix problems with the specified global.

   _Syntax_

     grestore _</path/to/global/file>_

Appendix C FreeM VIEW Commands and Functions
********************************************

C.1 VIEW 16: Total Count of Error Messages/View Single Error Message
====================================================================

Unknown semantics

C.2 VIEW 17: Intrinsic Z-Commands
=================================

Allows the user to retrieve or specify the list of intrinsic Z-commands
that FreeM will attempt to run internally, allowing intrinsic Z-commands
implemented internally to be replaced with M equivalents implemented as
%-routines in the 'SYSTEM' namespace.

C.3 VIEW 18: Intrinsic Z-Functions
==================================

Allows the user to retrieve or specify the list of intrinsic Z-functions
that FreeM will attempt to run internally, allowing intrinsic
Z-functions implemented internally to be replaced with M equivalents
implemented as %-routines in the 'SYSTEM' namespace.

C.4 VIEW 19: Intrinsic Special Variables
========================================

Allows the user to retrieve or specify which special variables are
implemented internally.

C.5 VIEW 20: Break Service Code
===============================

Allows the user to view or specify the code that will be run when a
'BREAK' is encountered.

C.6 VIEW 21: View Size of Last Global
=====================================

Allows the user to view the size of the last referenced global.

C.7 VIEW 22: Count VIEW 22 Aliases
==================================

Retrieves the number of VIEW 22 aliases in effect.

C.8 VIEW 23: View Contents of Input Buffer
==========================================

Retrieves the contents of the I/O input buffer.

C.9 VIEW 24: Maximum Number of Screen Rows
==========================================

Retrieves the maximum number of screen rows supported in the current
FreeM build.

C.10 VIEW 25: Maximum Number of Screen Columns
==============================================

Retrieves the maximum number of screen columns supported in the current
FreeM build.

C.11 VIEW 26: DO/FOR/XECUTE Stack Pointer
=========================================

Retrieves the 'DO', 'FOR', and 'XECUTE' stack pointer.

C.12 VIEW 27: DO/FOR/XECUTE Stack Pointer (On Error)
====================================================

Retrieves the 'DO', 'FOR', and 'XECUTE' stack pointer (on error).

C.13 VIEW 29: Copy Symbol Table
===============================

Copies the symbol table?  We aren't currently aware of what this means.

C.14 VIEW 30: Inspect Arguments
===============================

Retrieves the arguments passed to the 'freem' executable.

C.15 VIEW 31: Count Environment Variables
=========================================

Allows the user to inspect the number of variables in the process
environment table.

   _Syntax_

     WRITE $VIEW(31),!

Appendix D Implementation Limits
********************************

Appendix E US-ASCII Character Set
*********************************

Code   Character
000    '<NUL>'
001    '<SOH>'
002    '<STX>'
003    '<ETX>'
004    '<EOT>'
005    '<ENQ>'
006    '<ACK>'
007    '<BEL>'
008    '<BS>'
009    '<HT>'
010    '<LF>'
011    '<VT>'
012    '<FF>'
013    '<CR>'
014    '<SO>'
015    '<SI>'
016    '<DLE>'
017    '<DC1>'
018    '<DC2>'
019    '<DC3>'
020    '<DC4>'
021    '<NAK>'
022    '<SYN>'
023    '<ETB>'
024    '<CAN>'
025    '<EM>'
026    '<SUB>'
027    '<ESC>'
028    '<FS>'
029    '<GS>'
030    '<RS>'
031    '<US>'
032    '<space>'
033    !
034    "
035    #

Appendix F FreeM Project Coding Standards
*****************************************

F.1 Module Headers
==================

Module headers should adhere to the following format:

/*
 *                            *
 *                           * *
 *                          *   *
 *                     ***************
 *                      * *       * *
 *                       *  MUMPS  *
 *                      * *       * *
 *                     ***************
 *                          *   *
 *                           * *
 *                            *
 *
 *   mlib.h
 *    Function prototypes, structs, and macros for FreeM
 *    binding library
 *
 *
 *   Author: John P. Willis <jpw@coherent-logic.com>
 *    Copyright (C) 1998 MUG Deutschland
 *    Copyright (C) 2020 Coherent Logic Development LLC
 *
 *   Last modified: 29 February 2020
 *
 **/
   The Star of David in module headers is a convention started by Shalom
ha-Ashkenaz, the unidentified original author of FreeMUMPS/FreeM. We
will continue to employ it in honor of his most valuable contribution to
the M community.

F.2 Variable Naming
===================

Variables should be named in all lowercase letters, and words within
them delimited by underscores, such as 'my_useful_variable'.
'PascalCase' and 'camelCase' are not to be used in this codebase under
any circumstances.

   Constants defined via the C preprocessor should be in all uppercase
letters, with words within them likewise delimited by underscores, such
as:

#define MY_USEFUL_CONSTANT 1

F.3 Indentation and General Layout
==================================

This project uses four spaces for indentation.  Tabs are not to be used
under any circumstances, and all source files must use a linefeed
character to delineate lines.  If you are working on a Windows machine,
you must take care to follow this, as Windows will use a carriage return
followed by a linefeed by default.

   This project follows a modified version of what is known as the
Stroustrup indentation style.

F.4 Brace Placement (Functions)
===============================

We use modern, ANSI-style function prototypes, with the type specifier
on the same line as the function name.  You may encounter other styles
in the code, but we are transitioning to the new style as time permits.

   Below is a correct example:

int main(int argc, char **argv, char **envp)
{

}

F.5 Brace Placement (if-for-while-do)
=====================================

The 'if' keyword should be followed by one space, then the opening paren
and conditional expression.  We also use Stroustrup-style 'else' blocks,
rather than the K&R 'cuddled' 'else':

if (x) {
...
}
else {
...
}

while (1) {
...
}

for (i = 1; i < 10; i++) {
...
}

do {
...
} while (x);

   Single-statement if blocks should be isolated to a single line:

if (x) stmt();

   not:

if (x)
    stmt ();

   Notice that there is a space between 'if' and '(x)', and also between
'stmt' and '()'.  This should be followed throughout the code.

   If an 'if' block has an 'else if' or 'else', all parts of the
construct must be bracketed, even if one or more of them contain only
one statement:

if (x) {
    foo();
}
else if (y) {
    bar();
}
else {
    bas();
}

F.6 Labels and goto
===================

Labels must begin in column 1, and have two lines of vertical space
above and one beneath.

F.7 Preprocessor Conditionals
=============================

F.8 coding standards, preprocessor conditionals
===============================================

I have struggled with this, but have settled upon the standard practice
of keeping them in column 1.

F.9 Overall Program Spacing
===========================

   * Variable declarations fall immediately beneath the opening curly
     brace, and should initialize the variable right there whenever
     initialization is used.

   * One line between the last variable declaration and the first line
     of real code.

   * The 'return' statement of a function (when used as the last line of
     a function) should have one blank line above it and none below it.

   * Really long functions (those whose entire body is longer than 24
     lines) should have a comment immediately following the closing
     curly brace of the function, telling you what function the closing
     brace terminates.

F.10 The switch() Statement
===========================

We indent 'case' one level beneath 'switch()', and the code within each
'case' beneath the 'case'.  Each 'case' should have one line of vertical
whitespace above it:

switch(foo) {

    case some_const:
        foo();

        break;

    case some_other_const:
        bar();

        break;

    default:
        exit(1);

        break;
}

F.11 Comments
=============

We use C-style comments ('/* comment */') exclusively, even on
single-line comments.  C++ comments ('// comment') are not permitted.