\input texinfo @paragraphindent 0 @setfilename freem.info @settitle The FreeM Manual @copying This manual is for FreeM, (version 0.27.1), which is a free and open-source implementation of the M programming language and database system. Copyright @copyright{} 2020 Coherent Logic Development LLC @quotation 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. @end quotation @end copying @titlepage @title The FreeM Manual @subtitle @sc{The Official Manual of FreeM} @subtitle Version 0.27.1 @c@vskip 10pt @c@center @image{freem-logo-sm,,,,.png} @author John P. Willis @page @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @ifnottex @node Top @top The FreeM Manual This is the official manual for the FreeM programming language and database. @end ifnottex @dircategory The FreeM Manual @direntry * FreeM: (freem). The FreeM M programming language and database. @end direntry @menu * Introduction:: About the FreeM Project, its history, and its goals. * FreeM Invocation:: How to invoke FreeM from the command line. * The FreeM Direct-Mode Environment:: Executing M programs interactively. * Intrinsic Special Variables:: Intrinsic Special Variables. * Intrinsic Functions:: Intrinsic Functions. * Commands:: Commands. * Structured System Variables:: Structured System Variables. * Operators:: FreeM Operators. * Sequential I/O:: Processing sequential files in FreeM. * Network I/O:: Handling network sockets in FreeM. * Asynchronous Event Handling:: Handling asynchronous events in FreeM. * Synchronous Event Handling:: Synchronous events in FreeM. * GUI Programming with MWAPI:: Creating graphical interfaces in FreeM. * User-Defined Z Commands:: Adding your own Z commands to FreeM. * User-Defined Z Functions:: Adding your own Z functions to FreeM. * User-Defined SSVs:: Adding your own SSVs to FreeM. * System Library Routines:: FreeM built-in library of M routines. * Error Processing:: How to handle errors in M program code. * Debugging:: The program development cycle of FreeM. * System Configuration:: Configuring your FreeM installation. * Accessing FreeM from C Programs:: How to use the mlib interface. * FreeM Administrator:: The fmadm system manager tool. * FreeM Legacy Utilities:: FreeM legacy system manager utilities. * FreeM VIEW Commands and Functions:: Getting and setting info about FreeM internals. * Implementation Limits:: FreeM limitations. * US-ASCII Character Set:: The US-ASCII character set. * FreeM Project Coding Standards:: How to write code for submission to the FreeM project. * Conformance Clause:: FreeM conformance to ANSI X11 Standard M. * Index:: Complete index. @end menu @node Introduction @unnumbered Introduction FreeM started its life as @emph{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 @code{$VIEW} functions were added to retrieve the terminal size information. @code{$X} and @code{$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. @section Production Readiness FreeM is not yet production-ready. There are several show-stopping bugs that preclude a general release for public use: @itemize @bullet @item SSVs, aside from @code{^$JOB}, @code{^$DEVICE}, @code{^$EVENT}, and @code{^$ZPROCESS} are not implemented. @item @code{VIEW} commands and @code{$VIEW} functions are used extensively to configure and inspect the run-time behavior of FreeM, rather than the "canonical" SSV-based approach. @item Server sockets are not yet implemented. @end itemize @section Contributors Current contributors denoted with a @emph{+} following their name and role. @cindex contributors, ha-Ashkenaz, Shalom @cindex contributors, Best, John @cindex contributors, Diamond, Jon @cindex contributors, Fox, Ronald L. @cindex contributors, Gerum, Winfried @cindex contributors, Kreis, Greg @cindex contributors, Landis, Larry @cindex contributors, Marshall, Frederick D.S. @cindex contributors, Milligan, Lloyd @cindex contributors, Morris, Steve @cindex contributors, Murray, John @cindex contributors, Pastoors, Wilhelm @cindex contributors, Schell, Kate @cindex contributors, Schofield, Lyle @cindex contributors, Stefanik, Jim @cindex contributors, Trocha, Axel @cindex contributors, Walters, Dick @cindex contributors, Whitten, David @cindex contributors, Wicksell, David @cindex contributors, Willis, John P. @cindex contributors, Zeck, Steve @itemize @bullet @item Shalom ha-Ashkenaz (Original Implementer) @item John Best (IBM i and OS/400) @item Jon Diamond (Library, Utilities, Conformance) @item Ronald L. Fox (Initial port to Red Hat 5/libc-6) @item Winfried Gerum (Code, Advice, MTA coordination) @item Greg Kreis (Hardhats coordination, Dependencies) @item Larry Landis (Coordination, Code, Documentation) @item Frederick D.S. Marshall (MDC Standards Conformance) @emph{+} @item Lloyd Milligan (Code, Testing, Documentation) @item Steve Morris (Code, Microsoft) @item John Murray (Code, Conformance) @item Wilhelm Pastoors (Testing, Documentation) @item Kate Schell (Coordination, Conformance, MTA, MDC, Advice) @item Lyle Schofield (Advice, Prioritization, Tracking, Project Management) @item Jim Stefanik (GNU/Linux on s390x, IBM AIX, IBM z/OS) @item Axel Trocha (Code, Utilities) @item Dick Walters (Project Lead, Chief Coordinator, MTA) @item David Whitten (QA Test Suite, MDC, Advice) @emph{+} @item David Wicksell (Debugging, Code, Testing) @emph{+} @item John Willis (Current Maintainer and Project Lead) @emph{+} @item Steve Zeck (Code) @end itemize @node FreeM Invocation @chapter FreeM Invocation @cindex invocation, command-line @cindex options, command-line @section Synopsis @example $ @command{./freem} [@emph{OPTIONS}...] [[-r ] | [--routine=]] @end example When FreeM loads, it searches the @code{SYSTEM} namespace for the @code{^%ZFREEM} routine, and begins executing it. When @code{-r} or @code{--routine} are passed on the command line, FreeM will load and run the specified routine instead of @code{^ZFREEM}. Beginning with FreeM 0.1.7, routines invoked in this manner are no longer required to perform their own namespace setup with @code{VIEW} commands. @section Command-Line Options @table @asis @item @option{-h}, @option{--hardcopy} Enables hardcopy mode, echoing all output to a disk file. By default, this disk file is @file{\$freem_base/@emph{}/freem.hardcopy}, but can be changed with the following command: @example USER> VIEW 13:"@option{}" @end example The file used for hardcopy mode may also be specified in @file{/etc/freem.conf} or @file{~/.freemrc}. @item @option{-f}, @option{--filter} Allows your M routines to be used as UNIX filters. @item @option{-n}, @option{--noclear} Disables automatic screen clearing when FreeM loads. @item @option{-s}, @option{--standard} Restricts the use of non-standard language features, including @code{$Z...} intrinsic special variables, @code{$Z...} intrinsic functions, @code{Z...} commands, as well as @code{VIEW} and @code{$VIEW}. @item @option{-i}, @option{--import} Causes your UNIX environment variables to be imported into FreeM's local symbol table. @item @option{-r @emph{}}, @option{--routine=@emph{}} Causes @code{} to be executed at load, instead of @code{^%ZFREEM}. @item @option{-n @emph{}}, @option{--namespace=@emph{}} Selects the FreeM namespace to be entered on startup. Must be defined in @file{/etc/freem.conf}. @end table @section Using FreeM for Shell Scripting @cindex routines, as shell scripts @cindex shebang line @cindex shell scripting FreeM M routines can be used as shell scripts by providing a @emph{shebang} line beginning with @code{#!/path/to/freem} as the first line of the routine. The following example presumes that FreeM is installed at @file{/usr/local/bin/freem} and uses the @code{USER} namespace: @example #!/usr/local/bin/freem MYSCRIPT ; SET ^$JOB($JOB,"NAMESPACE")="USER" WRITE "This is output from an M routine used as a shell script.",! Q @end example Currently, the script needs to have a @file{.m} file extension. You will also need to select an appropriate namespace in your script using the @code{SET ^$JOB($JOB,"NAMESPACE")="@emph{}"} command before attempting to call other routines or access globals. You will also need to set the script's permissions to @emph{executable} in order for this to work: @example $ chmod +x @emph{myscript.m} @end example @node The FreeM Direct-Mode Environment @chapter The FreeM Direct-Mode Environment @cindex command line interface @cindex direct mode @cindex execution, interactive @cindex modes, programmer The FreeM direct-mode environment is the mode entered when FreeM is loaded without the use of @option{-r @emph{}} or @option{--routine=@emph{}}: @example Coherent Logic Development FreeM Version 0.27.1-x86_64-Linux (commit 4ececff; jpw AT pasithea Tue 13 Oct 2020 09:03:27 AM MDT) * * * * * *************** * * * * * FreeM * * * * * *************** * * * * Copyright (C) 1998 MUG Deutschland * Copyright (C) 2014, 2020 Coherent Logic Development LLC This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . PID: 3343 Principal I/O: 0:"/dev/pts/5" USER> @end example The prompt (@code{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 @code{$TLEVEL}: @example TL1:USER> @end example In the above example, @code{TL1} indicates that @code{$TLEVEL} is currently @emph{1}. @section 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: @table @asis @item @command{?} Accesses FreeM online help. Requires GNU @command{info(1)} to be installed on your local system. @item @command{events} Writes a list of @emph{event classes} and their @code{ABLOCK} counts: @example 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 @end example @item @command{history} Prints a list of all the direct-mode commands you have entered across all sessions. @item @command{rcl @emph{}} Allows you to recall command number @emph{} and run it again. Obtain the value for @emph{} from the output of the @command{history} command. @item @command{!@emph{}} Invokes a shell to run @emph{} from within FreeM. This temporarily disables @command{SIGALRM} handling in FreeM, which may interrupt the use of event-driven M programming commands including @command{ESTART} and @command{ESTOP}. If the @command{<} character is supplied immediately preceding @emph{}, FreeM will append the contents of M local variable @code{%} to @emph{} as standard input. If the @command{>} character is supplied immediately preceding @emph{}, FreeM will take the standard output stream of @emph{} and store it in M local variable @code{%}. @code{%} contains the number of lines in the input or output. @code{%(1)..%(@emph{n})} contains the data for lines 1-@emph{n}. @item @command{tdump} Writes detailed information about the status of any pending transactions to @code{$PRINCIPAL}. @end table @cindex HALT, in direct-mode If you issue a @code{HALT} command at the direct-mode prompt, you will exit out of FreeM. However, if you issue a @code{HALT} command when @code{$TLEVEL} is greater than zero, you will be given the opportunity to commit or rollback any pending transactions: @example 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. @end example In the above example, the user selected @code{r} to rollback the single pending transaction. @section REPL Functionality @cindex REPL, direct-mode FreeM direct mode allows you to enter M expressions directly from the direct-mode prompt, as long as they begin with a number: @example USER> S DENOM=10 USER> 100/DENOM 10 USER> @end example Such expressions will be immediately evaluated, and the result printed on @code{$PRINCIPAL}. @node Intrinsic Special Variables @chapter Intrinsic Special Variables @cindex variables, intrinsic special @section $DEVICE @cindex $DEVICE @cindex intrinsic special variables, $DEVICE Returns the status of the device currently in use, and is writable. If @code{$DEVICE} returns @emph{1}, an error condition exists on the current device. @section $ECODE @cindex $ECODE @cindex intrinsic special variables, $ECODE Returns a comma-delimited list of error conditions currently present, and is writable. An empty @code{$ECODE} indicates no errors. @section $ESTACK @cindex $ESTACK @cindex intrinsic special variables, $ESTACK Returns the depth of the program execution stack since the last time @code{$ESTACK} was @code{NEW}ed. @code{NEW}-able, but not @code{SET}-able. Differs from the @code{$STACK} ISV in that it is @code{NEW}-able, and resets to a value of 0 when @code{NEW}ed. @section $ETRAP @cindex $ETRAP @cindex intrinsic special variables, $ETRAP Sets or retrieves the M code that is run when an error is encountered or @code{$ECODE} is set to a non-blank value. @code{$ETRAP} code executes when @code{$ECODE} becomes non-blank. @section $HOROLOG @cindex $HOROLOG @cindex intrinsic special variables, $HOROLOG Returns a string containing the current date and time as @code{,}, where @code{} represents the number of days since the M epoch (midnight on 31 December 1840), and @code{} represents the number of seconds since the most recent midnight. @section $IO @cindex $IO @cindex intrinsic special variables, $IO Represents the current input/output device. Read-only. @section $JOB @cindex $JOB @cindex intrinsic special variables, $JOB Represents the process ID of the FreeM instance currently in use. @section $KEY @cindex $KEY @cindex intrinsic special variables, $KEY Represents the sequence of control characters that terminated the last @code{READ} command on @code{$IO}. @section $PRINCIPAL @cindex $PRINCIPAL @cindex intrinsic special variables, $PRINCIPAL Represents the primary input/output device. Usually a terminal or virtual terminal. @section $QUIT @cindex $QUIT @cindex intrinsic special variables, $QUIT If the current execution context was invoked as an extrinsic function, @code{$QUIT} returns @emph{1}. Otherwise, returns @emph{0}. When @code{$QUIT} returns @emph{1}, a subsequent @code{QUIT} command must have an argument. @section $STACK @cindex $STACK @cindex intrinsic special variables, $STACK Represents the current stack level. @section $STORAGE @cindex $STORAGE @cindex intrinsic special variables, $STORAGE Represents the number of bytes of free space available in FreeM's heap. @section $SYSTEM @cindex $SYSTEM @cindex intrinsic special variables, $SYSTEM Returns the MDC system ID of FreeM. @section $TEST @cindex $TEST @cindex intrinsic special variables, $TEST @code{$TEST} is a writable, @code{NEW}-able ISV that is @emph{1} if the most recently evaluated expression was @emph{true}. Otherwise, returns @emph{0}. @code{$TEST} is implicitly @code{NEW}ed when entering a new stack frame for extrinsic functions and argumentless @code{DO}. @code{$TEST} is @emph{not} implicitly @code{NEW}ed when a new stack frame is entered with an argumented @code{DO}. @section $TLEVEL @cindex $TLEVEL @cindex intrinsic special variables, $TLEVEL Returns a numeric value indicating the current level of transaction nesting in the process. When @code{$TLEVEL} is greater than @emph{0}, uncommitted transactions exist. @section $TRESTART @cindex $TRESTART @cindex intrinsic special variables, $TRESTART @cindex intrinsic special variables, unimplemented Returns an empty string, as FreeM transaction processing does not yet support restartable transactions. @section $X @cindex $X @cindex intrinsic special variables, $X Represents the current column position of the FreeM cursor. @cartouche @quotation @emph{Non-Standard Behavior} In FreeM, setting @code{$X} will move the FreeM cursor. @end quotation @end cartouche @section $Y @cindex $Y @cindex intrinsic special variables, $Y Represents the current row position of the FreeM cursor. @cartouche @quotation @emph{Non-Standard Behavior} In FreeM, setting @code{$Y} will move the FreeM cursor. @end quotation @end cartouche @section $ZA @cindex $ZA @cindex intrinsic special variables, $ZA @cindex intrinsic special variables, implementation-specific On the @code{HOME} device, always @code{0}. On other devices, represents the byte offset to the beginning of the file. @section $ZB @cindex $ZB @cindex intrinsic special variables, $ZB @cindex intrinsic special variables, implementation-specific Represents the last keystroke. @section $ZCONTROLC @cindex $ZCONTROLC @cindex intrinsic special variables, $ZCONTROLC @cindex intrinsic special variables, implementation-specific @section $ZDATE @cindex $ZDATE @cindex intrinsic special variables, $ZDATE @cindex intrinsic special variables, implementation-specific Returns the current date, in @code{YYYY/MM/DD} format. @section $ZERROR @cindex $ZERROR @cindex intrinsic special variables, $ZERROR @cindex intrinsic special variables, implementation-specific Returns the last error message. @section $ZF @cindex $ZF @cindex intrinsic special variables, $ZF @cindex intrinsic special variables, implementation-specific @section $ZHOROLOG @cindex $ZHOROLOG @cindex intrinsic special variables, $ZHOROLOG @cindex intrinsic special variables, implementation-specific Output @code{$HOROLOG}-style time, with the addition of milliseconds. @section $ZINRPT @cindex $ZINRPT @cindex intrinsic special variables, $ZINRPT @cindex intrinsic special variables, implementation-specific Gets or sets the interrupt enable/disable flag. @section $ZJOB @cindex $ZJOB @cindex intrinsic special variables, $ZJOB @cindex intrinsic special variables, implementation-specific Returns the @code{$JOB} value of the parent process (used in subroutines started with the @code{JOB} command). @section $ZLOCAL @cindex $ZLOCAL @cindex intrinsic special variables, $ZLOCAL @cindex intrinsic special variables, implementation-specific Returns the last local variable referenced. @section $ZMATCHCONTROL @cindex $ZMATCHCONTROL @cindex intrinsic special variables, $ZMATCHCONTROL @cindex intrinsic special variables, implementation-specific Returns control characters. @section $ZMATCHNUMERIC @cindex $ZMATCHNUMERIC @cindex intrinsic special variables, $ZMATCHNUMERIC @cindex intrinsic special variables, implementation-specific Returns all numbers @code{0}-@code{9}. @section $ZMATCHPUNCTUATION @cindex $ZMATCHPUNCTUATION @cindex intrinsic special variables, $ZMATCHPUNCTUATION @cindex intrinsic special variables, implementation-specific Returns all punctuation characters. @section $ZMATCHALPHABETIC @cindex $ZMATCHALPHABETIC @cindex intrinsic special variables, $ZMATCHALPHABETIC @cindex intrinsic special variables, implementation-specific Returns all alphabetic characters. @section $ZMATCHLOWERCASE @cindex $ZMATCHLOWERCASE @cindex intrinsic special variables, $ZMATCHLOWERCASE @cindex intrinsic special variables, implementation-specific Returns all lowercase characters. @section $ZMATCHUPPERCASE @cindex $ZMATCHUPPERCASE @cindex intrinsic special variables, $ZMATCHUPPERCASE @cindex intrinsic special variables, implementation-specific Returns all uppercase characters. @section $ZMATCHEVERYTHING @cindex $ZMATCHEVERYTHING @cindex intrinsic special variables, $ZMATCHEVERYTHING @cindex intrinsic special variables, implementation-specific Returns control characters, numbers, punctuation, and alphabetic characters. @section $ZPRECISION @cindex $ZPRECISION @cindex intrinsic special variables, $ZPRECISION @cindex intrinsic special variables, implementation-specific Gets or sets the number of digits of numeric precision used for fixed-point decimal arithmetic. Defaults to 100 digits. @section $ZREFERENCE @cindex $ZREFERENCE @cindex intrinsic special variables, $ZREFERENCE @cindex intrinsic special variables, implementation-specific Returns the last @emph{glvn} referenced. @section $ZSYSTEM @cindex $ZSYSTEM @cindex intrinsic special variables, $ZSYSTEM @cindex intrinsic special variables, implementation-specific @section $ZTIME @cindex $ZTIME @cindex intrinsic special variables, $ZTIME @cindex intrinsic special variables, implementation-specific Returns the system time in @code{HH:MM:SS} (24-hour) format. @section $ZTRAP @cindex $ZTRAP @cindex intrinsic special variables, $ZTRAP @cindex intrinsic special variables, implementation-specific 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, @code{$ZTRAP} is specific to each program execution stack level. In DSM 2.0-style error processing, @code{$ZTRAP} is the same for all program execution stack levels. When FreeM encounters an error, if @code{$ZTRAP} is nonempty and @code{$ETRAP} is empty, FreeM will perform an implicit @code{GOTO} to the entryref indicated in @code{$ZTRAP}. If @code{$ETRAP} is nonempty when FreeM encounters an error, the value of @code{$ZTRAP} is ignored, whether FreeM-style or DSM 2.0-style error processing is enabled. @section $ZVERSION @cindex $ZVERSION @cindex intrinsic special variables, $ZVERSION @cindex intrinsic special variables, implementation-specific Returns the version of FreeM in use, as well as the git commit hash, username, host, and date and time of the build in use. @node Intrinsic Functions @chapter Intrinsic Functions @section $ASCII @cindex $ASCII @cindex intrinsic functions, $ASCII Returns the ASCII code (in decimal) for one character in a string. @example SET RESULT=$ASCII(@emph{}[,@emph{}]) @end example If @emph{} is not supplied, @code{$ASCII} will return the ASCII code of the first character. Otherwise, returns the ASCII code of the character at position @emph{}. @section $CHAR @cindex $CHAR @cindex intrinsic functions, $CHAR Returns a string of characters corresponding to a list of ASCII codes. @example SET RESULT=$CHAR(@emph{}[,@emph{},...]) @end example @section $DATA @cindex $DATA @cindex intrinsic functions, $DATA Returns a numeric value 0, 1, 10, or 11, depending on whether a referenced node is defined, has data, or has children: @example SET RESULT=$DATA(@emph{}) @end example The return values are as follows: @example 0: @emph{} is undefined 1: @emph{} has data but no children 10: @emph{} has children but no data 11: @emph{} has children and data @end example @section $EXTRACT @cindex $EXTRACT @cindex intrinsic functions, $EXTRACT @section $FIND @cindex $FIND @cindex intrinsic functions, $FIND @section $FNUMBER @cindex $FNUMBER @cindex intrinsic functions, $FNUMBER @section $GET @cindex $GET @cindex intrinsic functions, $GET @section $JUSTIFY @cindex $JUSTIFY @cindex intrinsic functions, $JUSTIFY @section $LENGTH @cindex $LENGTH @cindex intrinsic functions, $LENGTH @section $NAME @cindex $NAME @cindex intrinsic functions, $NAME @section $NEXT @cindex $NEXT @cindex intrinsic functions, $NEXT @section $ORDER @cindex $ORDER @cindex intrinsic functions, $ORDER @section $PIECE @cindex $PIECE @cindex intrinsic functions, $PIECE @section $QLENGTH @cindex $QLENGTH @cindex intrinsic functions, $QLENGTH @section $QSUBSCRIPT @cindex $QSUBSCRIPT @cindex intrinsic functions, $QSUBSCRIPT @section $QUERY @cindex $QUERY @cindex intrinsic functions, $QUERY @section $RANDOM @cindex $RANDOM @cindex intrinsic functions, $RANDOM @section $REVERSE @cindex $REVERSE @cindex intrinsic functions, $REVERSE @section $SELECT @cindex $SELECT @cindex intrinsic functions, $SELECT @section $STACK @cindex $STACK @cindex intrinsic functions, $STACK Returns information about the program execution stack. The @code{$STACK} intrinsic function has both a one-argument form and a two-argument form. @emph{Syntax (One-Argument)} @example $STACK(@emph{}) @end example If @emph{num} is @code{0}, returns the command with which this FreeM instance was invoked. If @emph{num} is @code{-1}, returns the current program execution stack level. If @emph{num} represents a valid program execution stack depth above @code{0}, returns one of the following values indicating the reason for which the referenced program execution stack level was created: @table @asis @item @code{$$} If @code{$STACK(@emph{})="$$"}, program execution stack level @code{num} was created as the result of an extrinsic function call @item @emph{} If @code{$STACK(@emph{})} returns a valid M command, the referenced program execution stack level was created as a result of the @emph{m-command} command. @end table @emph{Syntax (Two-Argument}) @example $STACK(@emph{},"[ECODE|MCODE|PLACE]") @end example Returns the error codes, M program code, or entryref applicable to the action that created program execution stack level @emph{num}. @section $TEXT @cindex $TEXT @cindex intrinsic functions, $TEXT @section $TRANSLATE @cindex $TRANSLATE @cindex intrinsic functions, $TRANSLATE @section $VIEW @cindex $VIEW @cindex intrinsic functions, $VIEW @section $ZBOOLEAN @cindex $ZBOOLEAN @cindex intrinsic functions, $ZBOOLEAN @cindex intrinsic functions, implementation-specific Performs @emph{boolean-operation} on numeric arguments @emph{A} and @emph{B}. @emph{Syntax} @example SET RESULT=$ZBOOLEAN(@emph{A},@emph{B},@emph{boolean-operation}) @end example @code{$ZBOOLEAN} Operations (@emph{boolean-operation} values) @table @code @item 0 Always @emph{false} @item 1 @code{A AND B} @item 2 @code{A AND NOT B} @item 3 @code{A} @item 4 @code{NOT A AND B} @item 5 @code{B} @item 6 @code{A XOR B} @item 7 @code{A OR B} @item 8 @code{A NOR B} @item 9 @code{A EQUALS B} @item 10 @code{NOT B} @item 11 @code{A OR NOT B} @item 12 @code{NOT A} @item 13 @code{NOT A OR B} @item 14 @code{A NAND B} @item 15 Always @emph{true} @end table @section $ZCALL @cindex $ZCALL @cindex intrinsic functions, $ZCALL @cindex intrinsic functions, implementation-specific @section $ZCR @cindex $ZCR @cindex intrinsic functions, $ZCR @cindex intrinsic functions, implementation-specific @section $ZCRC @cindex $ZCRC @cindex intrinsic functions, $ZCRC @cindex intrinsic functions, implementation-specific @section $ZDATA @cindex $ZCRC @cindex intrinsic functions, $ZCRC @cindex intrinsic functions, implementation-specific @section $ZDATE @cindex $ZDATE @cindex intrinsic functions, $ZDATE @cindex intrinsic functions, implementation-specific @section $ZEDIT @cindex $ZEDIT @cindex intrinsic functions, $ZEDIT @cindex intrinsic functions, implementation-specific @section $ZHOROLOG @cindex $ZHOROLOG @cindex intrinsic functions, $ZHOROLOG @cindex intrinsic functions, implementation-specific @section $ZHT @cindex $ZHT @cindex intrinsic functions, $ZHT @cindex intrinsic functions, implementation-specific @section $ZKEY @cindex $ZKEY @cindex intrinsic functions, $ZKEY @cindex intrinsic functions, implementation-specific @section $ZLENGTH @cindex $ZLENGTH @cindex intrinsic functions, $ZLENGTH @cindex intrinsic functions, implementation-specific @section $ZLSD @cindex $ZLSD @cindex intrinsic functions, $ZLSD @cindex intrinsic functions, implementation-specific @section $ZM @cindex $ZM @cindex intrinsic functions, $ZM @cindex intrinsic functions, implementation-specific @section $ZNAME @cindex $ZNAME @cindex intrinsic functions, $ZNAME @cindex intrinsic functions, implementation-specific @section $ZNEXT @cindex $ZNEXT @cindex intrinsic functions, $ZNEXT @cindex intrinsic functions, implementation-specific @section $ZORDER @cindex $ZORDER @cindex intrinsic functions, $ZORDER @cindex intrinsic functions, implementation-specific @section $ZPIECE @cindex $ZPIECE @cindex intrinsic functions, $ZPIECE @cindex intrinsic functions, implementation-specific @section $ZPREVIOUS @cindex $ZPREVIOUS @cindex intrinsic functions, $ZPREVIOUS @cindex intrinsic functions, implementation-specific @section $ZREPLACE @cindex $ZREPLACE @cindex intrinsic functions, $ZREPLACE @cindex intrinsic functions, implementation-specific @section $ZSYNTAX @cindex $ZSYNTAX @cindex intrinsic functions, $ZSYNTAX @cindex intrinsic functions, implementation-specific @section $ZSORT @cindex $ZSORT @cindex intrinsic functions, $ZSORT @cindex intrinsic functions, implementation-specific @section $ZTIME @cindex $ZTIME @cindex intrinsic functions, $ZTIME @cindex intrinsic functions, implementation-specific @node Commands @chapter Commands @cindex commands @section ! @cindex ! @cindex commands, ! @cindex commands, external Invokes a shell to run @emph{} from within FreeM. This temporarily disables @command{SIGALRM} handling in FreeM, which may interrupt the use of event-driven M programming commands including @command{ESTART} and @command{ESTOP}. If the @command{<} character is supplied immediately preceding @emph{}, FreeM will append the contents of M local variable @code{%} to @emph{} as standard input. If the @command{>} character is supplied immediately preceding @emph{}, FreeM will take the standard output stream of @emph{} and store it in M local variable @code{%}. @code{%} contains the number of lines in the input or output. @code{%(1)..%(@emph{n})} contains the data for lines 1-@emph{n}. @section ABLOCK @cindex ABLOCK @cindex commands, 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 @code{ABLOCK} on all event classes occurs when an event handler subroutine is executing. As soon as a @code{QUIT} is reached within an event handler, an implicit @code{ABLOCK} will occur. @emph{Syntax} @example ABLOCK@emph{:postcondition} @end example In its argumentless form, @code{ABLOCK} increments the block counter for @emph{all} event classes, provided the optional @emph{postcondition} is either @emph{true} or omitted. @example ABLOCK@emph{:postcondition} @emph{evclass1}...,@emph{evclassN} @end example In its inclusive form, @code{ABLOCK} increments the block counters for all event classes named in the list, provided the optional @emph{postcondition} is either @emph{true} or omitted. @example ABLOCK@emph{:postcondition} (@emph{evclass1}...,@emph{evclassN} @end example In its exclusive form, @code{ABLOCK} increments the block counters for all event classes @emph{except for} those named in the list, provided the optional @emph{postcondition} is either @emph{true} or omitted. @section ASTART @cindex ASTART @cindex commands, ASTART Enables asynchronous event handling for one or more event classes. @emph{Syntax} @example ASTART@emph{:postcondition} @end example In its argumentless form, @code{ASTART} enables asynchronous event handling for all event classes, provided the optional @emph{postcondition} is either @emph{true} or omitted. @example ASTART@emph{:postcondition} @emph{evclass1}...,@emph{evclassN} @end example In its inclusive form, @code{ASTART} enables asynchronous event handling for all event classes named in the list, provided the optional @emph{postcondition} is either @emph{true} or omitted. @example ASTART@emph{:postcondition} (@emph{evclass1}...,@emph{evclassN}) @end example In its exclusive form, @code{ASTART} enables asynchronous event handling for all event classes @emph{except for} those named in the list, provided the optional @emph{postcondition} is either @emph{true} or omitted. @section ASTOP @cindex ASTOP @cindex commands, ASTOP Disables asynchronous event handling for one or more event classes. @emph{Syntax} @example ASTOP@emph{:postcondition} @end example In its argumentless form, @code{ASTOP} disables asynchronous event handling for all event classes, provided the optional @emph{postcondition} is either @emph{true} or omitted. @example ASTOP@emph{:postcondition} @emph{evclass1}...,@emph{evclassN} @end example In its inclusive form, @code{ASTOP} disables asynchronous event handling for all event classes named in the list, provided the optional @emph{postcondition} is either @emph{true} or omitted. @example ASTOP@emph{:postcondition} (@emph{evclass1}...,@emph{evclassN}) @end example In its exclusive form, @code{ASTOP} disables asynchronous event handling for all event classes @emph{except for} those named in the list, provided the optional @emph{postcondition} is either @emph{true} or omitted. @section AUNBLOCK @cindex AUNBLOCK @cindex commands, AUNBLOCK Decrements the event block counter for one or more event classes. @emph{Syntax} @example AUNBLOCK@emph{:postcondition} @end example In its argumentless form, @code{AUNBLOCK} decrements the block counter for @emph{all} event classes, provided the optional @emph{postcondition} is either @emph{true} or omitted. @example AUNBLOCK@emph{:postcondition} @emph{evclass1}...,@emph{evclassN} @end example In its inclusive form, @code{AUNBLOCK} decrements the block counters for all event classes named in the list, provided the optional @emph{postcondition} is either @emph{true} or omitted. @example AUNBLOCK@emph{:postcondition} (@emph{evclass1}...,@emph{evclassN} @end example In its exclusive form, @code{AUNBLOCK} decrements the block counters for all event classes @emph{except for} those named in the list, provided the optional @emph{postcondition} is either @emph{true} or omitted. @section BREAK @cindex BREAK @cindex commands, BREAK Interrupts running routine to allow interactive debugging. @emph{Syntax} @example @code{BREAK@emph{:postcondition}} @end example In its argumentless form, @code{BREAK} suspends execution of running code, provided the optional @emph{postcondition} is @emph{true} or omitted. @example @code{BREAK@emph{:postcondition} @emph{breakflag}} @end example In its single-argument form, @code{BREAK} sets @emph{Ctrl-C} handling and error handling characteristics, provided the optional @emph{postcondition} is @emph{true} or omitted. The following table enumerates the possible values of @emph{breakflag} @table @code @item 0 Disables @emph{Ctrl-C} handling @item -2 Enables normal FreeM error handling @item 2 Enables @emph{Digital Standard MUMPS} v2 error handling @item "default" Enables @emph{Ctrl-C} handling @end table @section CLOSE @cindex CLOSE @cindex commands, CLOSE Closes an input/output device. @emph{Syntax} @example @code{CLOSE@emph{:postcondition}} @end example In its argumentless form, @code{CLOSE} closes all I/O devices except for device 0 (the @code{HOME} device), provided the optional @emph{postcondition} is @emph{true} or omitted. @example @code{CLOSE@emph{:postcondition} @emph{channel}} @end example In its single-argument form, @code{CLOSE} closes the I/O device associated with channel @emph{channel}, provided that @emph{channel} represents a currently-open device, and the optional @emph{postcondition} is @emph{true} or omitted. @section DO @cindex DO @cindex commands, DO @section ELSE @cindex ELSE @cindex commands, ELSE @section FOR @cindex FOR @cindex commands, FOR @section GOTO @cindex GOTO @cindex commands, GOTO @section HALT @cindex HALT @cindex commands, HALT @section HANG @cindex HANG @cindex commands, HANG @section IF @cindex IF @cindex commands, IF @section JOB @cindex JOB @cindex commands, JOB @section KILL @cindex KILL @cindex commands, KILL @section KSUBSCRIPTS @cindex KSUBSCRIPTS @cindex commands, KSUBSCRIPTS Kills only the descendant subscripts (but not the data value) of a referenced global, local, or SSV (where allowed). @emph{Syntax} @example KSUBSCRIPTS@emph{:postcondition} @emph{var1},... @end example In the above @emph{inclusive} form, @code{KVALUE} will kill the descendant subscripts at each local, global, or SSV node specified in the list (provided that the optional @emph{postcondition} is @emph{true} or omitted), but will leave the data value intact. @cartouche @quotation @emph{Note} The below @emph{argumentless} and @emph{exclusive} forms of @code{KSUBSCRIPTS} are not implemented in FreeM, as of version 0.3.3, but are planned for a future release. @end quotation @end cartouche @example KSUBSCRIPTS@emph{:postcondition} @end example In the above @emph{argumentless} form, @code{KSUBSCRIPTS} will kill the descendant subscripts at the root of each local variable (provided that the optional @emph{postcondition} is @emph{true} or omitted), but will leave data values intact. @example KSUBSCRIPTS@emph{:postcondition} (@emph{var1},...) @end example In the above @emph{exclusive} form, @code{KSUBSCRIPTS} will kill the descendant subscripts of all local variables, @emph{with the exception of} those named in the list, provided that the optional @emph{postcondition} is @emph{true} or omitted, while leaving their data values intact. @section KVALUE @cindex KVALUE @cindex commands, KVALUE Kills only the data value (but not descendant subscripts) of a referenced global, local, or SSV (where allowed). @emph{Syntax} @example KVALUE@emph{:postcondition} @emph{var1},... @end example In the above @emph{inclusive} form, @code{KVALUE} will kill the data values at each local, global, or SSV node specified in the list (provided that the optional @emph{postcondition} is @emph{true} or omitted), but will leave descendant subscripts intact. @cartouche @quotation @emph{Note} The below @emph{argumentless} and @emph{exclusive} forms of @code{KVALUE} are not implemented in FreeM, as of version 0.27.1, but are planned for a future release. @end quotation @end cartouche @example KVALUE@emph{:postcondition} @end example In the above @emph{argumentless} form, @code{KVALUE} will kill the data values at the root of each local variable (provided that the optional @emph{postcondition} is @emph{true} or omitted), but will leave descendant subscripts intact. @example KVALUE@emph{:postcondition} (@emph{var1},...) @end example In the above @emph{exclusive} form, @code{KVALUE} will kill the data values of all local variables, @emph{with the exception of} those named in the list, provided that the optional @emph{postcondition} is @emph{true} or omitted, while leaving their descendant subscripts intact. @section LOCK @cindex LOCK @cindex commands, LOCK @section MERGE @cindex MERGE @cindex commands, MERGE Merges the contents of one global, local, or SSV subtree to another global, local, or SSV. @emph{Syntax} @example @code{MERGE A=^$JOB} @end example The above example will merge the @code{^$JOB} SSV into the @code{A} local. Note that the FreeM implementation of @code{MERGE} does not yet support multiple merge arguments. Returns error @code{M19} if either the source or the target variable are descendants of each other. @section NEW @cindex NEW @cindex commands, NEW @section OPEN @cindex OPEN @cindex commands, OPEN Opens sequential or socket I/O devices and files and associates them with a numeric FreeM input/output channel. @emph{Syntax (Sequential Files)} @example @code{OPEN@emph{:postcondition} @emph{channel}:"@emph{filename}/@emph{access-mode}"} @end example Opens @emph{filename} for reading and/or writing, and associates the file with FreeM I/O channel @emph{channel}, provided that the optional @emph{postcondition} is @emph{true} or omitted. The below table lists the valid options for @emph{access-mode}: @table @code @item r Read-only access @item w Create a new file for write access @item a Write access; append to existing file @item r+ Read/write access @end table @cartouche @quotation @emph{I/O Path} You cannot specify a fully-qualified filesystem path in the FreeM @code{OPEN} command. By default, FreeM will assume that @emph{filename} exists in the directory indicated in @code{^$JOB($JOB,"CWD")}. If you wish to access files in other directories, you must first set the @emph{I/O Path} in @code{^$JOB($JOB,"IOPATH")}. The following example will set the I/O path to @code{/etc}: @example @code{SET ^$JOB($JOB,"IOPATH")="/etc"} @end example @end quotation @end cartouche If @emph{channel} was already @code{OPEN}ed in the current process, calling @code{OPEN} on the same channel again implicitly closes the file or device currently associated with @emph{channel}. @emph{Syntax (Network Sockets)} Network sockets use a dedicated range of FreeM I/O channels ranging from 100-255. @code{OPEN}ing a socket I/O channel does @emph{not} implicitly connect the socket. Connecting the socket to the specified remote host is accomplished by the @code{/CONNECT} control mnemonic supplied to the @code{USE} command. @example OPEN@emph{:postcondition} @emph{socket-channel}:"@emph{hostname-or-address}:@emph{port}:@emph{address-family}:@emph{connection-type}" @end example @emph{Socket Parameters} @table @emph @item socket-channel The socket I/O channel to use. This must be in the range of 100-255. @item hostname-or-address The hostname or IP address to connect to. If a hostname is supplied, @code{OPEN} will implictly do a name lookup, the mechanism of which is typically determined by the configuration of @code{/etc/nsswitch.conf} on most UNIX and UNIX-like platforms. @item port The TCP or UDP port to which the socket will connect on the remote host. @item address-family The address family to use. Either @emph{IPV4} or @emph{IPV6}. @item connection-type Which connection type to use. Either @emph{TCP} or @emph{UDP}. @end table If you do not specify the address family and connection type, they will default to @emph{IPV4} and @emph{TCP}, respectively. @section QUIT @cindex QUIT @cindex commands, QUIT @section READ @cindex READ @cindex commands, READ @section SET @cindex SET @cindex commands, SET @section TCOMMIT @cindex TCOMMIT @cindex commands, TCOMMIT @section TRESTART @cindex TRESTART @cindex commands, TRESTART @cindex commands, unimplemented @section TROLLBACK @cindex TROLLBACK @cindex commands, TROLLBACK @section TSTART @cindex TSTART @cindex commands, TSTART @section USE @cindex USE @cindex commands, USE Sets @code{$IO} to a particular FreeM I/O channel, allowing @code{READ}s from and @code{WRITE}s to the associated terminal, sequential file, or network socket. Also sets various device parameters. @emph{Syntax (Terminal)} @example USE@emph{:postcondition} @emph{io-channel}[:(@emph{right-margin}:@emph{input-field-length}:@emph{device-status-word}:@emph{position}:@emph{line-terminator}:@emph{break-key})] @end example For terminals, @emph{io-channel} must be 0. Semantic and functional description of each device parameter TBA. @emph{Syntax (Sequential Files)} @example USE@emph{:postcondition} @emph{io-channel}[:@emph{seek-position}:@emph{terminator}:@emph{nodelay})] @end example For sequential files, @emph{io-channel} must be in the range 1-99. Semantic and functional description of each device parameter TBA. @emph{Syntax (Network Sockets)} @example USE@emph{:postcondition} @emph{io-channel} @end example The above syntax will set @code{$IO} to @emph{io-channel}, directing successive @code{READ}s and @code{WRITE}s to @emph{io-channel}, provided the optional @emph{postcondition} is @emph{true} or omitted. @example USE@emph{:postcondition} @emph{io-channel}:/CONNECT @end example The above syntax will set @code{$IO} to @emph{io-channel}, as in the prior example, but will also attempt to connect to the host and port specified for @emph{io-channel} when it was @code{OPEN}ed. The @code{/CONNECT} control mnemonic is only valid for socket channels whose connection type is @code{TCP}. Using @code{/CONNECT} on a @code{UDP} socket channel will throw @code{SCKAERR} (error code 55). For network sockets, @emph{io-channel} must be in the range 100-255. @section VIEW @cindex VIEW @cindex commands, VIEW @section WRITE @cindex WRITE @cindex commands, WRITE @section XECUTE @cindex XECUTE @cindex commands, XECUTE @section ZALLOCATE @cindex ZALLOCATE @cindex commands, ZALLOCATE @cindex commands, implementation-specific @section ZASSERT @cindex ZASSERT @cindex commands, ZASSERT @cindex commands, debugging @cindex commands, implementation-specific Triggers error @code{ZASSERT} if the supplied truth-valued expression @emph{tvexpr} is @emph{false} (@emph{1} is @emph{true}, and @emph{0} is @emph{false}). The @code{ZASSERT} error is catchable whether using standard-style, FreeM-style, or DSM 2.0-style error processing. @emph{Syntax} @example ZASSERT @emph{} @end example @emph{Example} @example USER> ZASSERT 1=1 USER> ZASSERT 1=0 >> Error ZASSERT: programmer assertion failed in SYSTEM::^%ZFREEM [$STACK = 0] >> ZASSERT 1=0 ^ @end example @section ZBREAK @cindex ZBREAK @cindex commands, ZBREAK @cindex commands, debugging @cindex commands, implementation-specific @section ZDEALLOCATE @cindex ZDEALLOCATE @cindex commands, ZDEALLOCATE @cindex commands, implementation-specific @section ZGO @cindex ZGO @cindex commands, ZGO @cindex commands, implementation-specific @section ZHALT @cindex ZHALT @cindex commands, ZHALT @cindex commands, implementation-specific @section ZINSERT @cindex ZINSERT @cindex commands, ZINSERT @cindex commands, implementation-specific @section ZJOB @cindex ZJOB @cindex commands, ZJOB @cindex commands, implementation-specific @section ZLOAD @cindex ZLOAD @cindex commands, ZLOAD @cindex commands, implementation-specific @section ZNEW @cindex ZNEW @cindex commands, ZNEW @cindex commands, implementation-specific @section ZPRINT @cindex ZPRINT @cindex commands, ZPRINT @cindex commands, implementation-specific @section ZQUIT @cindex ZQUIT @cindex commands, ZQUIT @cindex commands, implementation-specific @section ZREMOVE @cindex ZREMOVE @cindex commands, ZREMOVE @cindex commands, implementation-specific @section ZSAVE @cindex ZSAVE @cindex commands, ZSAVE @cindex commands, implementation-specific @section ZTRAP @cindex ZTRAP @cindex commands, ZTRAP @cindex commands, debugging @cindex commands, implementation-specific @section ZWATCH @cindex ZWATCH @cindex commands, ZWATCH @cindex commands, debugging @cindex commands, implementation-specific Sets a watchpoint on a global, local, or SSV node. @emph{Syntax} In its @emph{argumentless} form, @code{ZWATCH} toggles watchpoints on and off, provided the optional @emph{postcondition} is @emph{true} or omitted. @example ZWATCH@emph{:postcondition} @end example In its @emph{inclusive} form, @code{ZWATCH} adds, removes, or examines watchpoints, provided the optional @emph{postcondition} is @emph{true} or omitted. A @code{+} adds a new watchpoint to the following variable. A @code{-} removes an existing watchpoint for the following variable. A @code{?} examines the status of a watchpoint for the following variable. @example ZWATCH@emph{:postcondition} [+|-|?]@emph{var1}...,[+|-|?]@emph{varN} @end example The following example demonstrates turning watchpoint processing on and adding a watchpoint for global variable @code{^jpw(1)}. It then changes the value of @code{^jpw(1)}. @example USER [LEGACY]> ZWATCH Watchpoints enabled. USER [LEGACY]> ZWATCH +^JPW(1) Added '^JPW("1")' to the watchlist. USER [LEGACY]> SET ^JPW(1)="new value" >> WATCHPOINT: ^JPW("1") => 'new value' (changed 1 times) @end example The following example will remove that watchpoint: @example USER [LEGACY]> ZWATCH -^JPW(1) Removed '^JPW("1")' from the watchlist. USER [LEGACY]> ZWATCH ?^JPW(1) '^JPW("1")' is not being watched. @end example @section ZWRITE @cindex ZWRITE @cindex commands, ZWRITE @cindex commands, implementation-specific Writes the names and values of M variables to @code{$IO}. @emph{Syntax} @example ZWRITE@emph{:postcondition} @end example In the argumentless form, writes the names and values of all local variables to @code{$IO} if the optional @emph{postcondition} is @emph{true} or omitted. @example ZWRITE@emph{:postcondition} @emph{ArrayName},@dots{} @end example In the inclusive form, writes the names and values of all local, global, or structured system variables specified in the list of @emph{ArrayName}s to @code{$IO} if the optional @emph{postcondition} is @emph{true} or omitted. @example ZWRITE@emph{:postcondition} (@emph{ArrayName},@dots{}) @end example In the exclusive form, writes all local variables @emph{except} those specified in the list of @emph{ArrayName}s to @code{$IO} if the optional @emph{postcondition} is @emph{true} or omitted. @node Structured System Variables @chapter Structured System Variables @cindex variables, structured system @cindex structured system variables @cindex SSVs SSV subscripts are each described in the following format: @table @asis @item @code{@emph{}} +/-R +/-U +/-D @end table The R, U, and D flags represent Read, Update, and Delete. A minus sign indicates that the given operation is @emph{not} allowed, and a plus sign indicates that the given operation @emph{is} allowed. @section ^$CHARACTER @cindex ^$CHARACTER @cindex structured system variables, ^$CHARACTER The @code{^$CHARACTER} SSV is not yet implemented. @section ^$DEVICE @cindex ^$DEVICE @cindex structured system variables, ^$DEVICE FreeM implements several important pieces of functionality in the @code{^$DEVICE} SSV. The first subscript of @code{^$DEVICE} represents the I/O channel of an @code{OPEN}ed device. The following values for the second subscript are supported: @table @asis @item @code{EOF} +R -U -D Returns @code{1} if the I/O channel has encountered an end-of-file condition; @code{0} otherwise. Only valid if the I/O channel is connected to a sequential file. @item @code{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. @item @code{MNEMONICSPACE} +R -U -D Returns the current @emph{mnemonic-space} in use for the referenced I/O channel. Always @code{X364} for terminals and blank for sequential files. @item @code{DSW} +R +U -D Sets or returns the current @emph{Device Status Word} controlling terminal characteristics. Only valid for I/O channel 0. @item @code{TERMINATOR} +R +U -D Sets or returns the @code{READ} terminator for the specified I/O channel. Must be either @code{$C(13,10)} or @code{$C(10)}. Currently only supported for socket devices (those having an I/O channel of 100-255). @item @code{TERMID} +R -U -D Returns the type of terminal connected to channel 0. Only valid for I/O channel 0. @item @code{ECHOON} +R +U -D Enables or disables local echo of characters typed in a @code{READ} command. Only valid for I/O channel 0. Corresponds to bit 0 of the Device Status Word. @item @code{DELMODE} +R +U -D Enables or disables visual backspace during a @code{READ} command. Only valid for I/O channel 0. Corresponds to bit 2 of the Device Status Word. @item @code{ESCSEQPROC} +R +U -D Enables or disables escape sequence processing during a @code{READ} command. Only valid for I/O channel 0. Corresponds to bit 6 of the Device Status Word. @item @code{CONVUPPER} +R +U -D Enables or disables automatic conversion to uppercase of alphabetical characters during a @code{READ} command. Only valid for I/O channel 0. Corresponds to bit 14 of the Device Status Word. @item @code{DELEMPTY} +R +U -D Enables or disables the automatic deletion of empty strings supplied to a @code{READ} command. Only valid for I/O channel 0. Corresponds to bit 19 of the Device Status Word. @item @code{NOCTRLS} +R +U -D TBD. Only valid for I/O channel 0. Corresponds to bit 20 of the Device Status Word. @item @code{CTRLOPROC} +R +U -D Enables or disables @emph{Ctrl-O} processing during @code{READ} commands. Only valid for I/O channel 0. Corresponds to bit 21 of the Device Status Word. @item @code{NOTYPEAHEAD} +R +U -D Enables or disables typeahead buffering during @code{READ} commands. Only valid for I/O channel 0. Corresponds to bit 25 of the Device Status Word. @end table @emph{Example} The following example M code opens @code{/etc/freem.conf} and reads its contents line-by-line until the end of the file is reached. @example 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 @end example @section ^$DISPLAY @cindex ^$DISPLAY @cindex structured system variables, ^$DISPLAY The @code{^$DISPLAY} SSV is not yet implemented. @section ^$EVENT @cindex ^$EVENT @cindex structured system variables, ^$EVENT The @code{^$EVENT} SSV is not yet implemented. @section ^$GLOBAL @cindex ^$GLOBAL @cindex structured system variables, ^$GLOBAL The @code{^$GLOBAL} SSV is not yet implemented. @section ^$JOB @cindex ^$JOB @cindex structured system variables, ^$JOB FreeM fully implements @code{^$JOB} per ANSI X11.1-1995, as well as several extensions proposed in the M Millennium Draft Standard. The first subscript of @code{^$JOB} represents the @code{$JOB} of the process. If you @code{KILL} a first-level subscript of @code{^$JOB}, the @code{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: @table @asis @item @code{CHARACTER} +R -U -D Returns the character set of the job. @item @code{CWD} +R +U -D Returns or sets the current working directory of the job. @item @code{EVENT} +R +U +D The subtree contained under @code{^$JOB($J,"EVENT")} defines asynchronous event handlers for the current job. Please see @emph{Asynchronous Event Handling} for more information. @item @code{GLOBAL} +R -U -D Returns the global environment of the job. @item @code{IOPATH} +R +U -D Returns or sets the @emph{I/O path} to be used by the @code{OPEN} command. @item @code{PRIORITY} +R +U -D Returns or sets the @emph{nice} value of the FreeM job. @item @code{ROUTINE} +R -U -D Returns the name of the routine currently being executed by the job. @item @code{$PRINCIPAL} +R -U -D Returns the value of @code{$PRINCIPAL} for the job. @item @code{$TLEVEL} +R -U -D Returns the current transaction level (value of @code{$TLEVEL} for the job. @item @code{$IO} +R -U -D Returns the current value of @code{$IO} for the job. @item @code{USER} +R -U -D Returns the UID of the user owning the job. @item @code{GROUP} +R -U -D Returns the GID of the group owning the job. @item @code{NAMESPACE} +R +U -D Returns or sets the name of the job's currently-active namespace. @item @code{MATH} +R +U -D Returns or sets the mode in which decimal comparisons and arithmetic calculations are conducted. Valid values are @code{FIXED}, for fixed-point decimals having up to 20,000 digits of precision, as determined by the @code{$ZPRECISION} intrinsic special variable, and @code{IEEE754}, to use IEEE 754 floating-point decimals. When in @code{IEEE754} mode, floating-point numbers maintain 18 digits of numeric precision. @code{IEEE754} mode will make mathematical calculations significantly faster, especially when accelerated by a floating-point processor, at the expense of precision and accuracy. @code{FIXED} mode is recommended for financial calculations, or where precision and accuracy are valued over performance. @code{FIXED} is the default mode of FreeM operation, except on ARM processors, where only @code{IEEE754} mode is presently supported. Attempting to @code{SET} this node to values other than @code{FIXED} or @code{IEEE754} will set @code{$ECODE} to @code{M29}. @end table @section ^$LOCK @cindex ^$LOCK @cindex structured system variables, ^$LOCK The @code{^$LOCK} SSV is not yet implemented. @section ^$PDISPLAY @cindex ^$PDISPLAY @cindex structured system variables, ^$PDISPLAY The @code{^$PDISPLAY} SSV is not yet implemented. @section ^$ROUTINE @cindex ^$ROUTINE @cindex structured system variables, ^$ROUTINE The @code{^$ROUTINE} SSV is not yet implemented. @section ^$SYSTEM @cindex ^$SYSTEM @cindex structured system variables, ^$SYSTEM The @code{^$SYSTEM} SSV is not yet implemented. @section ^$WINDOW @cindex ^$WINDOW @cindex structured system variables, ^$WINDOW The @code{^$WINDOW} SSV is not yet implemented. @section ^$ZPROCESS @cindex ^$ZPROCESS @cindex structured system variables, ^$ZPROCESS Provides access to @code{procfs}, which is a filesystem-like abstraction for UNIX process metadata contained in @code{/proc}, as well as features for examining and controlling the state of processes external to the FreeM interpreter. The first subscript always represents the @emph{process ID} of the external process being acted upon. The following values for the second subscript are supported: @table @asis @item @code{EXISTS} +R -U -D Returns 1 if the referenced process exists; 0 otherwise. @item @code{ATTRIBUTES} +R -U -D Exposes the @code{/proc} files as descendant subscripts, i.e., @code{WRITE ^$ZPROCESS(2900,"ATTRIBUTES","cmdline"),!} would print the initial command line used to invoke process ID 2900. @item @code{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 @code{kill -l}. @end table @node Operators @chapter Operators @section Unary + @cindex operators, unary + @section Unary - @cindex operators, unary - @section + (Add) @cindex operators, + @section += (Add/Assign) @cindex operators, += @section ++ (Postfix Increment) @cindex operators, ++ @section - (Subtract) @cindex operators, - @section -= (Subtract/Assign) @cindex operators, -= @section -- (Postfix Decrement) @cindex operators, -- @section * (Multiply) @cindex operators, * @section *= (Multiply/Assign) @cindex operators, *= @section / (Divide) @cindex operators, / @section /= (Divide/Assign) @cindex operators, /= @section \ (Integer Divide) @cindex operators, \ @section \= (Integer Divide/Assign) @cindex operators, \= @section # (Modulo) @cindex operators, # @section #= (Modulo/Assign) @cindex operators, #= @section ** (Exponentiate) @cindex operators, ** @section **= (Exponentiate/Assign) @cindex operators, **= @section < (Less Than) @cindex operators, < @section <= (Less Than or Equal To) @cindex operators, <= @section > (Greater Than) @cindex operators, > @section >= (Greater Than or Equal To) @cindex operators, >= @section _ (Concatenate) @cindex operators, _ @section _= (Concatenate/Assign) @cindex operators, _= @section = (Equals) @cindex operators, = @section [ (Contains) @cindex operators, [ @section ] (Follows) @cindex operators, ] @section ]] (Sorts After) @cindex operators, ]] @section ? (Pattern Match) @cindex operators, ? @section & (Logical AND) @cindex operators, & @section ! (Logical OR) @cindex operators, ! @section ' (Logical NOT) @cindex operators, ' @section @@ (Indirect) @cindex operators, @@ @node Sequential I/O @chapter Sequential I/O @node Network I/O @chapter Network I/O @cindex networks, input and output Network I/O in FreeM is supplied through I/O channels 100-255. The normal @code{READ} and @code{WRITE} syntax will work with network sockets, with a few exceptions. @section Opening and Connecting a Client Socket @cindex networks, opening and connecting client sockets To open a client socket and connect to it, you will need to call the @code{OPEN} command and the @code{USE} command: @example ; ; 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 @end example @node Asynchronous Event Handling @chapter Asynchronous Event Handling @cindex event handling, asynchronous Asynchronous event handling in FreeM follows the specifications of the unpublished MDC @emph{Millennium Draft Standard}. @section Setting Up Async Event Handlers Asynchronous handlers are configured through the @code{^$JOB} SSV. In order to become proficient in writing asynchronous event handling code, you need to be aware of several important concepts: @table @emph @item Event Classes @emph{Event classes} denote particular categories of events. These include @code{COMM}, @code{HALT}, @code{IPC}, @code{INTERRUPT}, @code{POWER}, @code{TIMER}, and @code{USER} event classes. At present, only @code{INTERRUPT} events are supported. @item Event Identifiers @emph{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 @code{INTERRUPT} with an event identifier of @code{SIGWINCH} (short for @emph{SIGnal WINdow CHange}). @item Event Handlers @emph{Event handlers} are M routines or subroutines that can be registered to run when an event of a certain event class occurs. @item Event Registration @emph{Event registration} is the process of modifying the @code{^$JOB} SSV to associate a particular event class and event identifier with an event handler routine or subroutine. @item Event Block @emph{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 @code{ABLOCK} and @code{AUNBLOCK} commands. @end table The following sections of this chapter will take you step-by-step through setting up an event handler for @code{SIGWINCH} signal handling. @section Registering an Asynchronous Event Handler @cindex event handlers, registration To register an event handler, use the following syntax: @example SET ^$JOB($JOB,"EVENT",@emph{event-class},@emph{event-identifier})=@emph{entryref} @end example For example, use the following to register @code{^RESIZE} as an asynchronous event handler for @code{SIGWINCH} events: @example SET ^$JOB($JOB,"EVENT","INTERRUPT","SIGWINCH")="^RESIZE" @end example This by itself will not enable asynchronous event handling, as it merely @emph{registers} an event handler, associating it with event class @code{INTERRUPT} and event identifier @code{SIGWINCH}. @section Enabling Asynchronous Event Handling @cindex event handlers, enabling In order to enable asyncronous event handling, the @code{ASTART} command is used. In the following example, we will enable asynchronous event handling for the @code{INTERRUPT} event class: @example ASTART "INTERRUPT" @end example Omitting the @code{"INTERRUPT"} argument will enable asynchronous event handling for @emph{all} event classes. See @code{ASTART} in the commands section for more details. Once this is done, any event handlers registered for the @code{INTERRUPT} event class in @code{^$JOB} will be executed asynchronously as appropriate. @section Disabling Asynchronous Event Handling @cindex event handlers, disabling To disable asynchronous event handling, the @code{ASTOP} command is used. In the following example, we will disable asynchronous event handling for the @code{INTERRUPT} event class: @example ASTOP "INTERRUPT" @end example Omitting the @code{"INTERRUPT"} argument will disable asynchronous event handling for @emph{all} event classes. See @code{ASTOP} in the commands section for more details. You may also disable asynchronous event handling for a specific event identifier by @code{KILL}ing the appropriate node in the @code{^$JOB} SSV, which unregisters the event handler altogether. The following example will unregister the event handler for the @code{SIGWINCH} event identifier: @example KILL ^$JOB($JOB,"EVENT","INTERRUPT","SIGWINCH") @end example @section Temporarily Blocking Asynchronous Event Handling @cindex event handlers, blocking To temporarily block processing of specific event classes, you will use the @code{ABLOCK} command. @code{ABLOCK} functions incrementally, that is, each successive call to @code{ABLOCK} will increment a counter of blocks held for the specified event class or classes, and each successive call to @code{AUNBLOCK} will decrement that counter. Event handling for the specified event classes will be blocked as long as the @code{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 @code{INTERRUPT} event class: @example ABLOCK "INTERRUPT" @end example Note that entering an event handler causes an implicit @code{ABLOCK} of @emph{all} event classes, to prevent event handlers from interrupting other event handlers during their execution. This may be overridden by calling @code{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 @code{LOCK}s, ensuring that such modifications occur in the desired logical order. @node Synchronous Event Handling @chapter Synchronous Event Handling @node GUI Programming with MWAPI @chapter GUI Programming with MWAPI @node User-Defined Z Commands @chapter User-Defined Z Commands @node User-Defined Z Functions @chapter User-Defined Z Functions @cindex z functions, user-defined @node User-Defined SSVs @chapter User-Defined SSVs @cindex structured system variables, user-defined @cindex structured system variables @node System Library Routines @chapter System Library Routines @cindex system library routines @section ^%ZCOLUMNS @cindex ^%ZCOLUMNS @cindex system library routines, ^%ZCOLUMNS This routine is the implementation of the @code{$ZCOLUMNS} intrinsic special variable. @section ^%ZFREEM @cindex ^%ZFREEM @cindex system library routines, ^%ZFREEM This routine is the default startup routine for FreeM running in direct mode. Running @code{DO INFO} from direct mode will use this routine to display information about the current FreeM status and namespace configuration. @section ^%ZHELP @cindex ^%ZHELP @cindex system library routines, ^%ZHELP This routine implements the online help feature of FreeM, invoked by typing @code{?} in direct mode. It simply asks the underlying system to execute the command @command{info freem}. @section ^%ZROWS @cindex ^%ZROWS @cindex system library routines, ^%ZROWS This routine is the implementation of the @code{$ZROWS} intrinsic special variable. @node Error Processing @chapter Error Processing @cindex error processing FreeM exposes three means of processing M program execution errors: @table @emph @item FreeM-style error processing FreeM-style error processing exposes a read/write error trap in @code{$ZTRAP}. The contents of @code{$ZTRAP} must be either empty or a valid M entryref, to which FreeM will @code{GOTO} if an error occurs. Each program stack execution level can have its own @code{$ZTRAP} error handler enabled. @item DSM 2.0-style error processing DSM 2.0-style error processing emulates the @code{$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 @code{$ZTRAP} error handler is set across all program stack execution levels. @item Standard error processing Standard error processing uses the @code{NEW}-able @code{$ETRAP} variable to store error handler code, which may be any valid M code. The code in @code{$ETRAP} will run when an error occurs or the @code{$ECODE} ISV becomes non-empty. Stack information for standard error handling is provided by the @code{$STACK} ISV, the @code{$STACK()} intrinsic pseudo-function, and the @code{NEW}-able @code{$ESTACK} ISV. If @code{$ETRAP} is non-empty when an error condition occurs, @code{$ZTRAP} is ignored, regardless of whether FreeM-style or DSM 2.0-style error processing is enabled at the time of the error. @end table For further information on switching between FreeM-style and DSM 2.0-style @code{$ZTRAP} error handling, see the documentation for the @code{BREAK} command. @node Debugging @chapter Debugging @cindex debugging @node System Configuration @chapter System Configuration @cindex configuration, system @section Installing FreeM @cindex installation, FreeM @section Namespaces Overview @cindex namespaces, overview Configuration and administration of FreeM and the applications it hosts centers around the concept of @emph{namespaces}, which represent a collection of M routines and globals existing within a well-defined directory hierarchy. Beneath the FreeM installation directory (typically @code{/var/local/freem}) exists a number of subdirectories, each corresponding to a single FreeM namespace. In the example below, two namespaces have been defined, named @code{SYSTEM} and @code{USER}. This is a fairly typical configuration, and routines and globals whose names begin with the @code{%} character, which are generally considered to be code and data to be shared among all namespaces in a FreeM system, are typically stored in the @code{SYSTEM} namespace, while each individual application or related set of applications will be managed beneath another namespace, such as the @code{USER} namespace presented below: @example @emph{$freem_base} +- SYSTEM | +- routines | | +- %ZFREEM.m | | +- %ZCOLUMNS.m | | +- %ZFRMXEC.m | | +- %ZFRMSAMP.m | | +- %ZROWS.m | | +- %ZHELP.m | +- globals | +- ^%SYS +- USER +- routines | +- MYAPP.m +- globals +- ^MYGLOBAL @end example @section Listing Namespaces @cindex namespaces, listing To list all namespaces defined in @file{freem.conf}, type the following command: @example $ @emph{namespace list} Namespaces Defined in /etc/freem.conf: SYSTEM USER @end example In this example, the @code{SYSTEM} and @code{USER} namespaces are the only ones defined. @section Adding Namespaces @cindex namespaces, adding When adding new applications to your FreeM installation, it is important to plan an appropriate namespace configuration. In general, it is advisable to place each application in its own namespace, as this will prevent conflicts in routine and global names, which can easily lead to data corruption. However, there are cases where it is preferable (or even essential) to combine multiple applications into a single namespace, i.e., when two applications rely on the ability to access each other's routines and/or globals, both applications must reside in a shared namespace. In order to add a namespace to FreeM, you use the @command{namespace add} command. In the following example, we will add a new namespace called @code{MVTS}, for installing the M Validation and Test Suite: @example $ @emph{namespace add MVTS} Adding namespace MVTS... Namespace MVTS has been created. Access it with the following command: $ freem --namespace=MVTS Or if FreeM is already running: SYSTEM> SET ^$JOB($JOB,"NAMESPACE")="MVTS" @end example The @command{namespace} utility supports customization of a great many namespace options, including configuration of journaling and lock table location, among others. For more information on the @command{namespace} utility, please consult the relevant section of the manual in Appendix A (FreeM Legacy Utilities). @section Removing Namespaces @cindex namespaces, removing Not yet implemented. @section Importing Routines @cindex routines, importing @cindex import, %RO format @cindex utilities, ri @cindex ri utility FreeM fully supports the @code{%RO/%RI} distribution format for the transport of collections of application routines. The @command{ri} utility, located in @code{$freem_base/sbin/ri}, will allow you to import such a file directly into a defined namespace with minimal effort. In this example, we will create a @code{VPE} namespace and import the @emph{Victory Programming Environment} into it: @example $ @emph{namespace add VPE} Adding namespace VPE... Namespace VPE has been created. Access it with the following command: $ freem --namespace=VPE Or if FreeM is already running: SYSTEM> SET ^$JOB($JOB,"NAMESPACE")="VPE" $ @emph{ri --namespace=VPE --file=VPE15P2.RSA} FreeM Routine Import from 'VPE15P2.RSA' * Using FreeM namespace VPE * Percent routines will be loaded into /home/jpw/.freem/SYSTEM/routines * User routines will be loaded into /home/jpw/.freem/VPE/routines Routines Routines: XVEMBLDA XVEMBLDB XVEMBLDL XVEMBLD XVEMD1 XVEMDC XVEMSYN @emph{...lines omitted...} XVVMI00S XVVMINI1 XVVMINI2 XVVMINI3 XVVMINI4 XVVMINI5 XVVMINIS XVVMINIT XVVMVPE Loaded 246 user routines and 0 percent routines (246 total). @end example @node Accessing FreeM from C Programs @chapter Accessing FreeM from C Programs FreeM provides a library, @file{libfreem.so}, as well as corresponding header file @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 @file{libfreem.so} and include @file{freem.h}. This will allow your C code access to the function prototypes, data structures, and constants required for calling the @file{libfreem.so} APIs. You must exercise caution in developing programs that interface with FreeM through @file{libfreem.so} to ensure that all @file{libfreem.so} API calls are serialized, as FreeM and the @file{libfreem.so} library are neither thread-safe nor reentrant. You must also avoid setting signal handlers for @code{SIGALRM}, as FreeM uses @code{SIGALRM} to manage timeouts for @command{LOCK}, @command{READ}, and @command{WRITE}. @section freem_ref_t Data Structure @cindex libfreem, data structures: freem_ref_t The @code{libfreem} API uses a @code{struct} of type @code{freem_ref_t} in order to communicate state, pass in values, and return results. The data structure, defined in @file{freem.h}, looks like this: @verbatim 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 SSV (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; @end verbatim @emph{freem_ref_t Members} @table @asis @cindex libfreem, freem_ref_t.reftype @item @option{reftype} The @option{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: @code{MREF_RT_LOCAL}, @code{MREF_RT_GLOBAL}, or @code{MREF_RT_SSV}. @cindex libfreem, freem_ref_t.name @item @option{name} The @option{name} member contains the name of the global, local, or SSV to be accessed. You @emph{must not} include leading characters, such as @code{^} or @code{^$}. @cindex libfreem, freem_ref_t.value @item @option{value} This member contains the value read from or the value to be written to the global, local, or SSV. @cindex libfreem, freem_ref_t.status @item @option{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. @cindex libfreem, freem_ref_t.subscript_count @item @option{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 @code{subscripts} array. @cindex libfreem, freem_ref_t.subscripts @item @option{subscripts} A two-dimensional array containing the subscripts to which we are referring in this API call. @end table @section freem_ent_t Data Structure @cindex libfreem, data structures: freem_ent_t The @code{freem_function()} and @code{freem_procedure()} APIs in @code{libfreem} use the @code{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 @code{freem_procedure()}). The data structure, defined in @file{freem.h}, looks like this: @verbatim 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; @end verbatim @emph{freem_ent_t Members} @table @asis @item @option{name} @cindex libfreem, freem_ent_t.name The @option{name} member contains the name of the extrinsic function or procedure to be called. @cindex libfreem, freem_ent_t.value @item @option{value} This member contains the value returned by the function called. Not used by @code{freem_procedure()}. @cindex libfreem, freem_ent_t.status @item @option{status} This member gives us the value of @code{ierr} after the function or procedure call returns. The possible values of @code{ierr} are listed in @code{merr.h}. @cindex libfreem, freem_ent_t.argument_count @item @option{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 @code{arguments} array. @cindex libfreem, freem_ent_t.arguments @item @option{arguments} A two-dimensional array containing the arguments to be passed into the extrinsic function or procedure being called. @end table @section freem_init() @cindex libfreem, freem_init() Initializes @code{libfreem} in preparation for calling other APIs. @emph{Synopsis} @code{pid_t freem_init(char *namespace_name);} @emph{Parameters} @table @asis @item @code{namespace_name} Specifies the namespace to use. @end table @emph{Return Values} Returns the process ID of the @code{libfreem} process on success, or @code{-1} on failure. @emph{Example} This example prompts the user to enter a FreeM namespace and then attempts to initialize @code{libfreem} to use the selected namespace. @verbatim #include #include #include 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; } @end verbatim @section freem_version() @cindex libfreem, freem_version() Returns the version of FreeM in use. @emph{Synopsis} @code{short freem_version(char *result);} @emph{Parameters} @table @asis @item @code{result} The @code{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. @end table @emph{Return Value} Returns @code{0}. @emph{Example} This example will display the FreeM version on standard output. @verbatim #include #include #include int main(int argc, char **argv, char **envp) { char version[20] = {0}; freem_init(``USER''); freem_version(version); printf(``FreeM version: %s\n'', version); } @end verbatim @section freem_set() @cindex libfreem, freem_set() Sets a FreeM local node, global node, or writable SSV node. @emph{Synopsis} @code{short freem_set(freem_ref_t *ref);} @emph{Parameters} @table @asis @item @code{freem_ref_t} This parameter is a pointer to a @code{freem_ref_t} struct. The caller must allocate the memory for this struct. @end table @emph{Return Value} Returns @code{OK} on success, or one of the other error values defined in @code{merr.h}. @emph{Example} This example sets the value @code{blue} into global node @code{^car("color")}. @verbatim #include #include #include 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); } @end verbatim @section freem_get() @cindex libfreem, freem_get() Retrieves a FreeM local node, global node, or writable SSV node. @emph{Synopsis} @code{short freem_get(freem_ref_t *ref);} @emph{Parameters} @table @asis @item @code{freem_ref_t} This parameter is a pointer to a @code{freem_ref_t} struct. The caller must allocate the memory for this struct. @end table @emph{Return Value} Returns @code{OK} on success, or one of the other error values defined in @code{merr.h}. @emph{Example} This example retrieves the character set of the current process. @verbatim #include #include #include #include #include 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 SSV */ 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); } @end verbatim @section freem_kill() @cindex libfreem, freem_kill() Deletes a FreeM local node, global node, or killable SSV node, as well as all of its children. @emph{short freem_kill(freem_ref_t *ref);} @emph{Parameters} @table @asis @item @code{freem_ref_t} This parameter is a pointer to a @code{freem_ref_t} struct. The caller must allocate the memory for this struct. @end table @emph{Return Value} Returns @code{OK} on success, or one of the other error values defined in @code{merr.h}. @emph{Example} @verbatim #include #include #include 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); } @end verbatim @section freem_data() @cindex libfreem, freem_data() @section freem_order() @cindex libfreem, freem_order() @section freem_query() @cindex libfreem, freem_query() @section freem_lock() @cindex libfreem, freem_lock() @section freem_unlock() @cindex libfreem, freem_unlock() @section freem_tstart() @cindex libfreem, freem_tstart() @section freem_trestart() @cindex libfreem, freem_trestart() @section freem_trollback() @cindex libfreem, freem_trollback() @section freem_tlevel() @cindex libfreem, freem_tlevel() @section freem_tcommit() @cindex libfreem, freem_tcommit() @section freem_function() @cindex libfreem, freem_function() @section freem_procedure() @cindex libfreem, freem_procedure() @node FreeM Administrator @appendix FreeM Administrator @cindex utilities, system management @cindex utilities, fmadm @cindex fmadm The @code{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, @code{fmadm} presents a consistent, simple interface for all FreeM management tasks, and is namespace-aware. This appendix will document each @code{fmadm} facility as it is implemented, until all of the legacy utilities have been replaced. The @code{fmadm} utility's functions all follow the below, consistent syntax: @example usage: fmadm [OPTIONS] @end example The @emph{action} keyword can be one of the following: @table @emph @item list Lists instances of @emph{object} @item examine Examines a single instance of @emph{object} @item verify Verifies the integrity of @emph{object} @item compact Compacts @emph{object} @item repair Repairs integrity problems in @emph{object} @item create Creates an instance of @emph{object} @item remove Removes an instance of @emph{object} @item import Imports an @emph{object} @item export Exports an @emph{object} @item backup Creates a backup of @emph{object} @item restore Restores a backup of @emph{object} @item migrate Migrates an instance of @emph{object} from an older FreeM version to the current version @item edit Edits an instance of @emph{object} @end table The @emph{object} keyword can be one of the following: @table @emph @item lock The FreeM @code{LOCK} table. Supported actions are @code{list} and @code{remove}. @item zallocate The FreeM @code{ZALLOCATE} table. No actions yet implemented. @item journal FreeM after-image journaling. Supported actions are @code{examine} and @code{restore}. The @code{examine} action will dump the after-image journal entries for the selected namespace in human-readable format. The @code{restore} action will play after-image journals forward for the selected namespace. @item namespace FreeM namespaces (collections of M routines and globals). No actions yet implemented. @item global The database files representing each FreeM @emph{global}. Supported actions are @code{list}, @code{examine}, @code{remove}, and @code{verify}. @item routine An M routine, stored as a @code{.m} file. Supported actions are @code{list}, @code{examine}, @code{remove}, @code{import}, @code{export}, @code{backup}, and @code{edit}. @item job A UNIX process representing an instance of the FreeM runtime. Supported actions are @code{list} and @code{examine}. @end table @node FreeM Legacy Utilities @appendix FreeM Legacy Utilities @cindex utilities, legacy @section Global Compactor (gcompact) @cindex utilities, legacy, gcompact Compacts the specified global in place. @emph{Syntax} @example gcompact @emph{/path/to/global/file} @end example @section Block Examiner (gfix) @cindex utilities, gfix The @emph{gfix} interactive utility program permits navigation of the B-tree structure of the specified global a block at a time. @emph{Syntax} @example gfix @emph{} @end example @section Global Repair Tool (grestore) @cindex utilities, legacy, grestore This utility will fix problems with the specified global. @emph{Syntax} @example grestore @emph{} @end example @section Namespace Manager (namespace) @cindex utilities, legacy, namespace Adds, removes, lists, or displays the configuration of FreeM namespaces, allowing the user to specify all relevant configuration options. @emph{Syntax} @example namespace [add | remove | show] [-n @emph{} | --namespace=@emph{}] [OPTIONS...] namespace list @end example @emph{Options} @table @asis @item @option{-h}, @option{--help} Displays a summary of @command{namespace} syntax and command-line options. @item @option{-n @emph{}}, @option{--namespace=@emph{}} Sets the namespace being acted upon. @item @option{-m [inactive | read | write]}, @option{--jnlmode=[inactive | read | write]} Sets the journaling mode for the namespace; @option{inactive} by default. @item @option{-f <@emph{journal-file>}}, @option{--jnlfile=@emph{}} Sets the file that FreeM will use for after-image journaling; @file{/tmp/freem.journal} by default. @item @option{-l @emph{}}, @option{--locktab=@emph{}} Sets the file that FreeM will use for maintaining the @command{LOCK} table; @file{/tmp/freem.locktab} by default. @item @option{-z @emph{}}, @option{--zalloctab=@emph{}} Sets the file that FreeM will use for maintaining the @command{ZALLOCATE} table; @file{/tmp/freem.zalloctab} by default. @item @option{-c @emph{}}, @option{--hardcopy=@emph{}} Sets the file FreeM will use when invoked in hardcopy mode; @file{/tmp/freem.hardcopy} by default. @item @option{-p @emph{}}, @option{--path=@emph{}} Informs this program of the location where FreeM is installed. You must upply the @option{-p} or @option{--path} option if the @code{$freem_base} environment variable is not set. @end table @section Routine Import (ri) @cindex utilities, legacy, routine import @cindex utilities, legacy, ri Allows the user to import routines in the @code{%RO/%RI} distribution format into a FreeM namespace. @emph{Syntax} @example ri --file=@emph{} --namespace=@emph{} [--overwrite] @end example @emph{Options} @table @asis @item @option{--file=@emph{}} Specifies the @code{%RO/%RI}-format file whose routines you wish to import. @item @option{--namespace=@emph{}} Specifies the FreeM namespace into which routines from @emph{} will be loaded. @item @option{--overwrite} Indicates that @command{ri} should overwrite any routines from @emph{} that already exist in @emph{}. Use with a preponderance of caution. @end table @node FreeM VIEW Commands and Functions @appendix FreeM VIEW Commands and Functions @section VIEW 16: Total Count of Error Messages/View Single Error Message @cindex VIEW commands/functions, 16, total count of error messages/view single error message Unknown semantics @section VIEW 17: Intrinsic Z-Commands @cindex VIEW commands/functions, 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 @code{SYSTEM} namespace. @section VIEW 18: Intrinsic Z-Functions @cindex VIEW commands/functions, 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 @code{SYSTEM} namespace. @section VIEW 19: Intrinsic Special Variables @cindex VIEW commands/functions, 19, intrinsic special variables Allows the user to retrieve or specify which special variables are implemented internally. @section VIEW 20: Break Service Code @cindex VIEW commands/functions, 20, break service code Allows the user to view or specify the code that will be run when a @code{BREAK} is encountered. @section VIEW 21: View Size of Last Global @cindex VIEW commands/functions, 21, view size of last global Allows the user to view the size of the last referenced global. @section VIEW 22: Count VIEW 22 Aliases @cindex VIEW commands/functions, 22, count VIEW 22 aliases Retrieves the number of VIEW 22 aliases in effect. @section VIEW 23: View Contents of Input Buffer @cindex VIEW commands/functions, 23, input buffer contents Retrieves the contents of the I/O input buffer. @section VIEW 24: Maximum Number of Screen Rows @cindex VIEW commands/functions, 24, maximum number of screen rows Retrieves the maximum number of screen rows supported in the current FreeM build. @section VIEW 25: Maximum Number of Screen Columns @cindex VIEW commands/functions, 25, maximum number of screen columns Retrieves the maximum number of screen columns supported in the current FreeM build. @section VIEW 26: DO/FOR/XECUTE Stack Pointer @cindex VIEW commands/functions, 26, DO/FOR/XECUTE stack pointer Retrieves the @code{DO}, @code{FOR}, and @code{XECUTE} stack pointer. @section VIEW 27: DO/FOR/XECUTE Stack Pointer (On Error) @cindex VIEW commands/functions, 27, DO/FOR/XECUTE stack pointer, on error Retrieves the @code{DO}, @code{FOR}, and @code{XECUTE} stack pointer (on error). @section VIEW 28: Switch Symbol Table @cindex VIEW commands/functions, 28, switch symbol table Switches the symbol table? We aren't currently aware of what this means. @section VIEW 29: Copy Symbol Table @cindex VIEW commands/functions, 29, copy symbol table Copies the symbol table? We aren't currently aware of what this means. @section VIEW 30: Inspect Arguments @cindex VIEW commands/functions, 30, inspect arguments Retrieves the arguments passed to the @code{freem} executable. @section VIEW 31: Count Environment Variables @cindex VIEW commands/functions, 31, count environment variables Allows the user to inspect the number of variables in the process environment table. @emph{Syntax} @example WRITE $VIEW(31),! @end example @node Implementation Limits @appendix Implementation Limits @cindex limitations, memory @cindex maximum size, routine @cindex maximum size, global @cindex maximum size, string @node US-ASCII Character Set @appendix US-ASCII Character Set @multitable {Code} {Character} @item Code @tab Character @item 000 @tab @code{} @item 001 @tab @code{} @item 002 @tab @code{} @item 003 @tab @code{} @item 004 @tab @code{} @item 005 @tab @code{} @item 006 @tab @code{} @item 007 @tab @code{} @item 008 @tab @code{} @item 009 @tab @code{} @item 010 @tab @code{} @item 011 @tab @code{} @item 012 @tab @code{} @item 013 @tab @code{} @item 014 @tab @code{} @item 015 @tab @code{} @item 016 @tab @code{} @item 017 @tab @code{} @item 018 @tab @code{} @item 019 @tab @code{} @item 020 @tab @code{} @item 021 @tab @code{} @item 022 @tab @code{} @item 023 @tab @code{} @item 024 @tab @code{} @item 025 @tab @code{} @item 026 @tab @code{} @item 027 @tab @code{} @item 028 @tab @code{} @item 029 @tab @code{} @item 030 @tab @code{} @item 031 @tab @code{} @item 032 @tab @code{} @item 033 @tab ! @item 034 @tab `` @item 035 @tab # @end multitable @node FreeM Project Coding Standards @appendix FreeM Project Coding Standards @section Module Headers @cindex coding standards, module headers Module headers should adhere to the following format: @verbatim /* * * * * * * * * * *************** * * * * * * * MUMPS * * * * * * * *************** * * * * * * * * * * mlib.h * Function prototypes, structs, and macros for FreeM * binding library * * * Author: John P. Willis * Copyright (C) 1998 MUG Deutschland * Copyright (C) 2020 Coherent Logic Development LLC * * Last modified: 29 February 2020 * **/ @end verbatim @cindex ha-Ashkenaz, Shalom 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. @section Variable Naming @cindex coding standards, variable naming Variables should be named in all lowercase letters, and words within them delimited by underscores, such as @code{my_useful_variable}. @code{PascalCase} and @code{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: @verbatim #define MY_USEFUL_CONSTANT 1 @end verbatim @section Indentation and General Layout @cindex coding standards, indentation @cindex coding standards, 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. @section Brace Placement (Functions) @cindex coding standards, 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: @verbatim int main(int argc, char **argv, char **envp) { } @end verbatim @section Brace Placement (if-for-while-do) @cindex coding standards, brace placement, if-for-while-do The @code{if} keyword should be followed by one space, then the opening paren and conditional expression. We also use Stroustrup-style @code{else} blocks, rather than the K&R 'cuddled' @code{else}: @verbatim if (x) { ... } else { ... } while (1) { ... } for (i = 1; i < 10; i++) { ... } do { ... } while (x); @end verbatim Single-statement if blocks should be isolated to a single line: @verbatim if (x) stmt(); @end verbatim not: @verbatim if(x) stmt(); @end verbatim Notice that there is a space between @code{if} and @code{(x)}, but not between @code{stmt} and @code{()}. This should be followed throughout the code. If an @code{if} block has an @code{else if} or @code{else}, all parts of the construct must be bracketed, even if one or more of them contain only one statement: @verbatim if (x) { foo(); } else if (y) { bar(); } else { bas(); } @end verbatim @section Labels and goto @cindex coding standards, labels @cindex coding standards, goto Labels must begin in column 1, and have two lines of vertical space above and one beneath. @section Preprocessor Conditionals @section coding standards, preprocessor conditionals I have struggled with this, but have settled upon the standard practice of keeping them in column 1. @section Overall Program Spacing @cindex coding standards, spacing of programs @itemize @bullet @item Variable declarations fall immediately beneath the opening curly brace, and should initialize the variable right there whenever initialization is used. @item One line between the last variable declaration and the first line of real code. @item The @code{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. @item 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. @end itemize @section The switch() Statement @cindex coding standards, switch() We indent @code{case} one level beneath @code{switch()}, and the code within each @code{case} beneath the @code{case}. Each @code{case} should have one line of vertical whitespace above it: @verbatim switch(foo) { case some_const: foo(); break; case some_other_const: bar(); break; default: exit(1); break; } @end verbatim @section Comments @cindex coding standards, comments We use C-style comments (@code{/* comment */}) exclusively, even on single-line comments. C++ comments (@code{// comment}) are not permitted. @node Conformance Clause @appendix Conformance Clause @cindex standards, ANSI @cindex standards, implementation conformance clause @node Index @unnumbered Index @printindex cp @bye