Annotation of freem/doc/freem.texi, revision 1.63
1.1 snw 1: \input texinfo
2: @paragraphindent 0
3: @setfilename freem.info
4: @settitle The FreeM Manual
5:
6: @copying
1.62 snw 7: This manual is for FreeM, (version 0.65.1-rc1), which is a free software implementation of the M programming language.
1.1 snw 8:
1.39 snw 9: Print-optimized versions of this book are typeset in @emph{Computer Modern} by the author using the @emph{GNU Texinfo} tools.
1.1 snw 10:
1.5 snw 11: Copyright @copyright{} 2014-2025 Coherent Logic Development LLC
1.1 snw 12:
13: @quotation
14: 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.
15: @end quotation
16: @end copying
17:
18: @titlepage
19:
20: @title The FreeM Manual
21: @subtitle @sc{The Official Manual of FreeM}
1.62 snw 22: @subtitle Version 0.65.1-rc1
1.1 snw 23: @c@vskip 10pt
24: @c@center @image{freem-logo-sm,,,,.png}
25: @author Serena Willis
26: @page
27: @vskip 0pt plus 1filll
28: @insertcopying
29: @end titlepage
30: @contents
31:
32: @ifnottex
33: @node Top
34: @top The FreeM Manual
35:
36: This is the official manual for the FreeM programming language.
37: @end ifnottex
38:
39: @dircategory The FreeM Manual
40: @direntry
41: * FreeM: (freem). The FreeM M programming language.
42: @end direntry
43:
44: @menu
45: * Introduction:: About the FreeM Project, its history, and its goals.
1.36 snw 46: * Document Conventions:: Conventions used in this manual.
1.39 snw 47: * A Note on Standards:: FreeM positioning regarding the M Development Committee.
1.1 snw 48: * FreeM Invocation:: How to invoke FreeM from the command line.
1.22 snw 49: * The FreeM Environment Daemon:: Managing shared resources in the FreeM environment.
1.1 snw 50: * The FreeM Direct-Mode Environment:: Executing M programs interactively.
1.36 snw 51: * Debugging:: The program development cycle of FreeM.
1.58 snw 52: * Program Development Cycle:: How to create, edit, test, and run FreeM programs.
1.1 snw 53:
54: * Directives:: Per-Routine Language Directives.
55: * Intrinsic Special Variables:: Intrinsic Special Variables.
56: * Intrinsic Functions:: Intrinsic Functions.
57: * OBJECT Methods:: Methods for OBJECT variables.
58: * STRING Methods:: Methods for STRING variables.
59: * Commands:: Commands.
60: * Structured System Variables:: Structured System Variables.
61: * Operators:: FreeM Operators.
62:
63: * Routines:: The units of M code in FreeM.
64: * Types:: FreeM data types.
65: * Globals:: FreeM persistent sparse arrays.
66: * Concurrency Control:: @code{LOCK}ing and transaction processing.
67: * Local Variables:: In-memory variables.
68: * Scoping:: Scoping in FreeM.
69: * Decision Constructs:: @code{IF}, @code{THEN}, @code{ELSE}, @code{$SELECT}, and postconditionals.
70: * Branch Constructs:: Labels, @code{GOTO}, @code{DO}, and @code{JOB}.
71: * Loop Constructs:: The @code{FOR} loop.
72: * Modular Programming:: Extrinsic functions and subroutines.
73: * Object-Oriented Programming:: Classes and objects in FreeM.
74: * Libraries:: System and user libraries.
75: * Sequential I/O:: Processing sequential files in FreeM.
76: * Network I/O:: Handling network sockets in FreeM.
77: * Extended Global References:: Accessing globals in non-default namespaces.
78: * Global Aliasing:: Defining alternate names for globals.
79: * Global Mappings:: Mapping global names to non-default namespaces.
80:
81: * Asynchronous Event Handling:: Handling asynchronous events in FreeM.
82: * Global Triggers:: Responding to global accesses in M code.
83: * Synchronous Event Handling:: Synchronous events in FreeM.
84:
85:
86: * GUI Programming with MWAPI:: Creating graphical interfaces in FreeM.
87:
88: * User-Defined Z Commands:: Adding your own Z commands to FreeM.
89: * User-Defined Z Functions:: Adding your own Z functions to FreeM.
90: * User-Defined SSVNs:: Adding your own SSVNs to FreeM.
91:
92: * Language Dialects:: Controlling FreeM standards compliance.
93:
94: * System Library Routines:: FreeM built-in library of M routines.
95:
96: * Interrupt Handling:: How FreeM handles interrupts.
97: * Error Processing:: How to handle errors in M program code.
98: * FreeM Error Codes:: Explanations of each FreeM error code.
99:
100: * System Configuration:: Configuring your FreeM installation.
101: * Accessing FreeM from C Programs:: How to use the mlib interface.
102:
103: * FreeM Administrator:: The fmadm system manager tool.
104: * FreeM VIEW Commands and Functions:: Getting and setting info about FreeM internals.
105: * Implementation Limits:: FreeM limitations.
106: * US-ASCII Character Set:: The US-ASCII character set.
107: * FreeM Project Coding Standards:: How to write code for submission to the FreeM project.
108:
109: * Index:: Complete index.
110: @end menu
111:
112: @node Introduction
113: @unnumbered Introduction
114:
1.36 snw 115: 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 distribution 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.
1.1 snw 116:
117: 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 Serena 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.
118:
1.36 snw 119: 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 application.
1.1 snw 120:
1.39 snw 121: For more information on FreeM history, see @code{@emph{$PREFIX}/share/freem/doc/freem_history.*} (distributed in PostScript, PDF, and plain text formats).
122:
1.1 snw 123: @section Production Readiness
124:
125: FreeM is not yet production-ready. There are several show-stopping bugs that preclude a general release for public use:
126:
127: @itemize @bullet
128:
129: @item
130: @code{@ref{VIEW}} commands and @code{@ref{$VIEW()}} functions are used extensively to configure and inspect the run-time behavior of FreeM, rather than the "canonical" SSVN-based approach.
131:
132: @item
133: Server sockets are not yet implemented.
134:
135: @item
136: There are some situations that can result in segmentation faults and/or lock-ups.
137:
138: @item
139: In spite of our best efforts, this manual is not yet complete.
140:
141: @end itemize
142:
143: @section Contributors
144: Current contributors denoted with a @emph{+} following their name and role.
145: @cindex contributors, ha-Ashkenaz, Shalom
146: @cindex contributors, Best, John
147: @cindex contributors, Diamond, Jon
148: @cindex contributors, Fox, Ronald L.
149: @cindex contributors, Gerum, Winfried
150: @cindex contributors, Kreis, Greg
151: @cindex contributors, Landis, Larry
1.56 snw 152: @cindex contributors, McGlothlen, Ken
1.1 snw 153: @cindex contributors, Milligan, Lloyd
154: @cindex contributors, Morris, Steve
155: @cindex contributors, Murray, John
156: @cindex contributors, Pastoors, Wilhelm
157: @cindex contributors, Schell, Kate
158: @cindex contributors, Schofield, Lyle
159: @cindex contributors, Stefanik, Jim
160: @cindex contributors, Trocha, Axel
161: @cindex contributors, Walters, Dick
162: @cindex contributors, Whitten, David
163: @cindex contributors, Wicksell, David
164: @cindex contributors, Willis, Serena
165: @cindex contributors, Zeck, Steve
166:
167: @itemize @bullet
168:
169: @item
170: Shalom ha-Ashkenaz (Original Implementer)
171:
172: @item
173: John Best (IBM i and OS/400)
174:
175: @item
176: Jon Diamond (Library, Utilities, Conformance)
177:
178: @item
179: Ronald L. Fox (Initial port to Red Hat 5/libc-6)
180:
181: @item
182: Winfried Gerum (Code, Advice, MTA coordination)
183:
184: @item
185: Greg Kreis (Hardhats coordination, Dependencies)
186:
187: @item
188: Larry Landis (Coordination, Code, Documentation)
189:
190: @item
191: Rick Marshall (Testing, MDC Conformance) @emph{+}
192:
193: @item
1.56 snw 194: Ken McGlothlen (Apple Silicon build/test environment, proofreading of documentation) @emph{+}
195:
196: @item
1.1 snw 197: Lloyd Milligan (Code, Testing, Documentation)
198:
199: @item
200: Steve Morris (Code, Microsoft)
201:
202: @item
203: John Murray (Code, Conformance)
204:
205: @item
206: Wilhelm Pastoors (Testing, Documentation)
207:
208: @item
209: Kate Schell (Coordination, Conformance, MTA, MDC, Advice)
210:
211: @item
212: Lyle Schofield (Advice, Prioritization, Tracking, Project Management)
213:
214: @item
215: Jim Stefanik (GNU/Linux on s390x, IBM AIX, IBM z/OS)
216:
217: @item
218: Axel Trocha (Code, Utilities)
219:
220: @item
221: Dick Walters (Project Lead, Chief Coordinator, MTA)
222:
223: @item
224: David Whitten (QA Test Suite, MDC, Advice) @emph{+}
225:
226: @item
227: David Wicksell (Debugging, Code, Testing) @emph{+}
228:
229: @item
230: Serena Willis (Current Maintainer and Project Lead) @emph{+}
231:
232: @item
233: Steve Zeck (Code)
234:
235: @end itemize
1.36 snw 236:
237: @node Document Conventions
238: @chapter Document Conventions
239: @cindex document conventions
240: @cindex conventions
241:
242: @section Formatting Conventions
243:
244: This manual uses the following formatting conventions:
245: @itemize
246: @item Code examples, filesystem paths, and commands are presented in @code{monospace}
247: @item Placeholders where the reader is expected to supply a replacement value are presented in @code{@emph{monospace italics}}, and depending on context, may be surrounded by angle brackets
248: @item New terminology is introduced in @emph{proportional italics}
249: @end itemize
250:
251: @section Definitions
252:
253: FreeM uses abbreviations for common language elements:
254:
255: @table @asis
256: @item @emph{$PREFIX}
257: Refers to the base filesystem location within which FreeM is installed. For most distribution methods of FreeM, @emph{$PREFIX} represents either @code{/} or @code{/usr/local}.
1.37 snw 258: @item @emph{dlabel}
259: Refers to a label in an M routine, beginning in the first column of the line. Can be a @emph{name} or an @emph{intlit}.
260: @item @emph{entryref}
261: Refers to an M routine entry point, denoted in the format @code{@emph{dlabel} [+@emph{intexpr}][^@emph{routine}]}.
1.36 snw 262: @item @emph{expr}
263: Refers to any expression. Often presented in the format @emph{expr V <type>}, where @emph{V} means @emph{giving}; e.g., @emph{expr V lvn} means @emph{expression giving local variable name}.
264: @item @emph{glvn}
265: Refers to the name of an M global, local, or structured system variable.
266: @item @emph{gvn}
267: Refers to the name of an M global variable.
268: @item @emph{intexpr}
269: Refers to an integer expression.
1.37 snw 270: @item @emph{intlit}
271: Refers to an integer literal.
1.36 snw 272: @item @emph{ISV}, @emph{isv}
273: Refers to an M intrinsic special variable; @code{$JOB} and @code{$IO} are examples of ISVs.
274: @item @emph{L}
275: Indicates a @emph{list} of the following item, e.g., @emph{L gvn} means @emph{list of global variable names}.
276: @item @emph{lvn}
277: Refers to the name of an M local variable.
1.47 snw 278: @item @emph{postcondition}
279: A @emph{tvexpr} immediately following a command verb affecting that command's execution.
1.37 snw 280: @item @emph{strlit}
281: Refers to an M string literal.
1.36 snw 282: @item @emph{ssvn}
283: Refers to the name of an M structured system variable.
284: @item @emph{tvexpr}
1.47 snw 285: Refers to a truth-valued expression, i.e., an expression interpreted as a truth value.
1.36 snw 286: @end table
287:
1.39 snw 288: @node A Note on Standards
289: @chapter A Note on Standards
290: @cindex MDC
291: @cindex M Development Committee
292: @cindex ANSI X11.1
293: @cindex standards, ANSI
294: @cindex standards, MDC
295:
296: FreeM attempts to implement as many features as possible from the M Development Committee's unpublished @emph{Millennium Draft Standard}, as well as its predecessors.
297:
298: The maintainer of FreeM (who is also the author of this book) is largely in favor of standardization efforts, and hopes that the MDC will resume activities, and will happily participate if it does so in an open, public, transparent, and democratic manner. Until then, however, FreeM will attempt to improve the M language, in cooperation with other free software M implementers where possible. Any breaking changes introduced in future MDC releases of the @emph{Standard} (such as the rumored @emph{M5}) which prove incompatible with FreeM will be handled via the @code{$DIALECT} special variable (to be changed to @code{$ZDIALECT} in a coming release).
299:
300: The conformance document required per the @emph{Standard} should be installed as a @code{man} page on any computer system where FreeM is made available. Simply type @code{man freem_conformance} to access.
301:
1.1 snw 302: @node FreeM Invocation
303: @chapter FreeM Invocation
304: @cindex invocation, command-line
305: @cindex options, command-line
306:
307: @section Synopsis
308: @example
309: $ @command{./freem} [@emph{OPTIONS}...] [[-r <entryref>] | [--routine=<entryref>]]
310: @end example
311:
1.28 snw 312: When FreeM loads, it searches the @code{SYSTEM} namespace for the @code{%SYSINIT} routine, and begins executing it.
1.1 snw 313:
1.28 snw 314: When @code{-r} or @code{--routine} are passed on the command line, FreeM will load and run the specified routine after running @code{%SYSINIT}. 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.
1.22 snw 315:
316: @section %SYSINIT Routine
317:
1.36 snw 318: The @code{%SYSINIT} routine runs every time a FreeM interpreter process starts. This routine defines some useful constants, enables handling of @code{TRIGGER} events, and handles the execution of code passed via the @code{-x|--execute} or routines passed via @code{-r|--routine}.
1.22 snw 319:
1.28 snw 320: Do not modify the supplied @code{%SYSINIT} routine to add site-specific startup items. Instead, create a @code{LCLINIT} routine in the @code{USER} namespace of one or more environments. @code{%SYSINIT} will automatically run @code{LCLINIT} each time it starts.
1.1 snw 321:
322: @section Command-Line Options
1.22 snw 323: @cindex options, command-line
1.1 snw 324:
325: @table @asis
326:
327: @item @option{-d}, @option{--daemon}
1.22 snw 328: Starts the FreeM environment daemon, exactly one of which must be running at all times in order for FreeM interpreter and fmadm processes to function.
1.1 snw 329:
330: @item @option{-e}, @option{--environment}
331: Selects the environment to be used. If no environment is specified, @code{DEFAULT} is used.
332:
333: @item @option{-k}, @option{--nofork}
1.22 snw 334: When used with @option{-d} or @option{--daemon}, causes the FreeM environment daemon to run instead in the foreground. Useful for debugging.
1.1 snw 335:
336: @item @option{-S}, @option{--shmsize}
337: When used with @option{-d} or @option{--daemon}, specifies the number of bytes of shared memory FreeM will allocate for the @code{LOCK} table, job table, and IPC table. This will determine the maximum number of concurrent FreeM processes and @code{LOCK}s available in this environment.
338:
339: @item @option{-c}, @option{--config}
340: Specify a configuration file other than @code{$PREFIX/etc/freem.conf}.
341:
342: @item @option{-h}, @option{--help}
343: Display a help message showing valid FreeM options.
344:
345: @item @option{-i}, @option{--import}
346: Causes your UNIX environment variables to be imported into FreeM's local symbol table.
347:
348: @item @option{-f}, @option{--filter}
349: Allows your M routines to be used as UNIX filters.
350:
351: @item @option{-n @emph{<namespace-name>}}, @option{--namespace=@emph{<namespace-name>}}
1.22 snw 352: Selects the FreeM namespace to be entered on startup. Must be defined in @file{/etc/<environment>/freem.conf}.
1.1 snw 353:
354: @item @option{-r @emph{<entryref>}}, @option{--routine=@emph{<entryref>}}
1.28 snw 355: Causes @code{<entryref>} to be executed at load, instead of @code{%SYSINIT}.
1.1 snw 356:
357: @item @option{--standard=@emph{<standard>}}
358: Sets the default FreeM dialect to use for new routine buffers.
359:
360: Valid values for @code{@emph{<standard>}} are as follows:
361:
362: @table @code
363: @item @code{M77}
364: Restricts FreeM to use only features specified by the 1977 M standard.
365: @item @code{M84}
366: Restricts FreeM to use only features specified by the 1984 M standard.
367: @item @code{M90}
368: Restricts FreeM to use only features specified by the 1990 M standard.
369: @item @code{M95}
370: Restricts FreeM to use only features specified by the 1995 M standard.
371: @item @code{MDS}
372: Restricts FreeM to use only features proposed by the Millennium Draft Standard.
373: @item @code{M5}
374: Restricts FreeM to use only features proposed by the upcoming M5 standard.
375: @item @code{FREEM}, @code{EXTENDED}
376: Removes all standards-based restrictions and allows full access to all FreeM features. This is the default value of @code{$DIALECT}.
377: @end table
378:
379: Please note that FreeM is not entirely standards-compliant, regardless of the value of @code{@emph{<standard>}}.
380:
381: @item @option{-v}, @option{--version}
382: Displays FreeM version information.
383:
384: @item @option{-x @emph{<mcode>}}, @option{--execute=@emph{<mcode>}}
1.22 snw 385: Executes M code @code{<mcode>} at startup.
1.1 snw 386:
387: @end table
388:
389: @section Using FreeM for Shell Scripting
390: @cindex routines, as shell scripts
391: @cindex shebang line
392: @cindex shell scripting
393:
394: 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.
395: The following example presumes that FreeM is installed at @file{/usr/local/bin/freem} and uses the @code{USER} namespace:
396:
397: @example
398: #!/usr/local/bin/freem
399: MYSCRIPT ;
400: SET ^$JOB($JOB,"NAMESPACE")="USER"
401: WRITE "This is output from an M routine used as a shell script.",!
402: Q
403: @end example
404:
405: 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{<namespace>}"} command before attempting to call other routines or access globals.
406:
407: You will also need to set the script's permissions to @emph{executable} in order for this to work:
408:
409: @example
410: $ chmod +x @emph{myscript.m}
411: @end example
412:
1.22 snw 413: @node The FreeM Environment Daemon
414: @chapter The FreeM Environment Daemon
1.1 snw 415: @cindex daemon, freem
416:
1.22 snw 417: The FreeM environment daemon manages shared resources for a given FreeM environment. These include the lock table, job table, inter-process communication, and concurrency control for transaction processing. Unlike some M implementations, the FreeM environment daemon does @emph{not} function as a write daemon for global storage.
418:
419: One daemon process is required per FreeM environment, and can be started in the following ways, in order of preference:
1.1 snw 420:
1.22 snw 421: @example
422: $ sudo fmadm start environment [-e=<environment-name>]
423: @end example
1.1 snw 424:
425: @example
1.22 snw 426: $ freem --daemon [--nofork] [--environment=<environment-name>] [--shmsize=<bytes>]
1.1 snw 427: @end example
428:
429: If the daemon is started with @option{--nofork}, it will run in the foreground and its output will be reflected on the terminal. Otherwise, the daemon will run as a child process in the background and immediately return terminal control to the shell. The latter option is recommended in most cases.
430:
431: The @option{--environment} option will start the daemon for the specified @emph{environment-name}. The default environment, if unspecified, is called @code{DEFAULT}. If using an environment other than @code{DEFAULT}, interpreter processes that wish to also connect to the same environment must also use the @option{--environment} option when starting, and @code{libfreem} clients must also pass the environment name as the first argument to the @code{freem_init()} function. Environments allow you to run multiple, isolated instances of FreeM on the same machine, whose globals and routines are distinct and unique.
432:
1.58 snw 433: The @option{--shmsize} option specifies the size in bytes of the FreeM shared memory segment. The default is 16,777,216 bytes (16 megabytes). Increasing the size of the FreeM shared memory segment will, at the cost of increased memory usage, increase the number of concurrent jobs and lock table entries available to the environment; decreasing the size of the segment will have the expected opposite effect. Note that you must also pass @option{--shmsize} with the same number of bytes to any interpreter process to be used with an environment whose daemon uses a non-default shared memory segment size.
1.1 snw 434:
435: Attempting to start a FreeM interpreter process without a daemon running with the same environment name will result in an error.
436:
437: @node The FreeM Direct-Mode Environment
438: @chapter The FreeM Direct-Mode Environment
439: @cindex command line interface
440: @cindex direct mode
441: @cindex execution, interactive
442: @cindex modes, programmer
443:
444:
445: The FreeM direct-mode environment is the mode entered when FreeM is invoked without the use of @option{-r @emph{<entryref>}} or @option{--routine=@emph{<entryref>}}:
446:
447: @example
1.62 snw 448: Coherent Logic Development FreeM version 0.65.1-rc1 (x86_64-pc-linux-gnu)
1.1 snw 449: Copyright (C) 2014, 2020, 2021 Coherent Logic Development LLC
450:
451:
452: USER>
453: @end example
454:
1.25 snw 455: The prompt (@code{DEFAULT.USER>}) displays the current environment and namespace, @code{DEFAULT} and @code{USER}, respsectively. If any uncommitted direct-mode transactions have been started, the prompt will change to reflect the current value of @code{@ref{$TLEVEL}}:
1.1 snw 456:
457: @example
1.22 snw 458: TL1:DEFAULT.USER>
1.1 snw 459: @end example
460:
461: In the above example, @code{TL1} indicates that @code{@ref{$TLEVEL}} is currently @emph{1}.
462:
463: @section Direct-Mode Commands
464:
465: When you are in direct mode, in addition to M commands, a number of internal commands are available to help developers be more productive:
466:
467: @table @asis
468:
469: @item @command{?}
470: Accesses FreeM online help. Requires GNU @command{info(1)} to be installed on your local system.
471:
472: @item @command{events}
473: Writes a list of @emph{event classes} and their @code{ABLOCK} counts:
474:
475: @example
1.22 snw 476: DEFAULT.USER> events
1.1 snw 477:
478: Event Class Processing Mode ABLOCK Count
479: ----------- --------------- ------------
480: COMM Disabled 0
481: HALT Disabled 0
482: IPC Disabled 0
483: INTERRUPT Disabled 0
484: POWER Disabled 0
485: TIMER Disabled 0
486: USER Disabled 0
487: WAPI Disabled 0
488: TRIGGER Disabled 0
489: @end example
490:
491:
492: @anchor{trantab}
493: @item @command{trantab}
494: Displays information about any uncommitted transactions currently in-flight for this process.
495:
1.22 snw 496: @anchor{glstat}
497: @item @command{trantab}
498: Displays statistics about globals that have been opened in the current FreeM process.
499:
1.1 snw 500: @anchor{jobtab}
501: @item @command{jobtab}
502: Displays a summary of the FreeM job table.
503:
504: @anchor{locktab}
505: @item @command{locktab}
506: Displays a list of @code{LOCK}s held in the current environment.
507:
508: @anchor{rbuf}
509: @item @command{rbuf}
510: Lists the status of all FreeM routine buffers.
511:
512: @anchor{wh}
513: @item @command{wh}
514: Forces an immediate flush of this process's @code{readline} history buffer to disk.
515:
516: @anchor{shmstat}
517: @item @command{shmstat}
518: Displays the configuration of FreeM shared memory. Intended only for advanced debugging of the FreeM environment.
519:
520: @anchor{shmpages}
521: @item @command{shmpages}
522: Lists the status of each FreeM shared memory page. Intended only for advanced debugging of the FreeM environment.
523:
524: @anchor{history}
525: @item @command{history}
526: Prints a list of all the direct-mode commands you have entered across all sessions.
527:
528: @anchor{rcl}
529: @item @command{rcl @emph{<history-index>}}
530: Allows you to recall command number @emph{<history-index>} and run it again. Obtain the value for @emph{<history-index>} from the output of the @command{history} command.
531:
532: @item @command{!!}
533: Launches a subshell within the FreeM direct mode, allowing the user to run operating system commands.
534:
535: @example
1.22 snw 536: DEFAULT.USER> !!
1.1 snw 537:
538: Type Ctrl-D to exit from the shell
539: $ uname -a
540: Linux hesperos 4.19.0-17-amd64 #1 SMP Debian 4.19.194-3 (2021-07-18) x86_64 GNU/Linux
541: $ exit
542:
1.22 snw 543: DEFAULT.USER>
1.1 snw 544: @end example
545:
546: @item @command{!@emph{<external-command>}}
1.28 snw 547: Invokes a shell to run @emph{<external-command>} from within FreeM. This temporarily disables @command{SIGALRM} handling in FreeM, which may interrupt the use of event-driven M programming commands including @command{ASTART} and @command{ASTOP}.
1.1 snw 548:
549: If the @command{>} character is supplied immediately preceding @emph{<external-command>}, FreeM will append the contents of an M local or global variable referenced in @code{^$JOB($JOB,"PIPE_GLVN")} to the standard input stream of @emph{<external-command>}.
550:
551: If the @command{<} character is supplied immediately preceding @emph{<external-command>}, FreeM will take the standard output stream of @emph{<external-command>} and store it in M local or global variable referenced by @code{^$JOB($JOB,"PIPE_GLVN")}.
552:
553: The data value in the unsubscripted M local or global contains the number of lines in the input or output. Subscripts @code{(1)..(@emph{n})} contain the data for lines 1-@emph{n}.
554:
555: @end table
556:
557: @cindex HALT, in direct-mode
558: If you issue a @code{@ref{HALT}} command at the direct-mode prompt, you will exit out of FreeM. However, if you issue a @code{@ref{HALT}} command when @code{@ref{$TLEVEL}} is greater than zero, you will be given the opportunity to commit or rollback any pending transactions:
559:
560: @example
1.22 snw 561: DEFAULT.USER> TSTART
1.1 snw 562:
563:
1.22 snw 564: TL1:DEFAULT.USER> SET ^MYGLOBAL=1
1.1 snw 565:
566:
1.22 snw 567: TL1:DEFAULT.USER> HALT
1.1 snw 568:
569: UNCOMMITTED TRANSACTIONS EXIST:
570:
571: $TLEVEL 1*
572: Operations for Transaction ID: k8xj1de
573: 1: action = 0 key = ^MYGLOBAL data = 1
574:
575: Would you like to c)ommit or r)ollback the above transactions and their operations? ($TLEVEL = 1) r
576:
577:
578: Transactions have been rolled back.
579: @end example
580:
581: In the above example, the user selected @code{r} to rollback the single pending transaction.
582:
583: @section REPL Functionality
584: @cindex REPL, direct-mode
585:
586: FreeM direct mode allows you to enter M expressions directly from the direct-mode prompt, as long as they begin with a number:
587:
588: @example
1.22 snw 589: DEFAULT.USER> S DENOM=10
1.1 snw 590:
591:
1.22 snw 592: DEFAULT.USER> 100/DENOM
1.1 snw 593:
594: 10
1.22 snw 595: DEFAULT.USER>
1.1 snw 596: @end example
597:
598: Such expressions will be immediately evaluated, and the result printed on @code{@ref{$IO}}.
599:
1.36 snw 600: @node Debugging
601: @chapter Debugging
602: @cindex debugging
603:
604: @section Debugging Synopsis
605: FreeM includes an interactive debugger, entered using the @code{BREAK "DEBUG"} command. The debugger is also entered if @code{Ctrl-C} is pressed, @code{Ctrl-C} handling is enabled, and you are in direct mode.
606:
607: If you would like to enter the debugger automatically each time an error is encountered, add the following to your @code{LCLINIT} routine:
608:
609: @example
1.58 snw 610: S $ETRAP="B ""DEBUG"""
1.36 snw 611: @end example
612:
613: @section Debugging Commands
614: The debugger uses its own unique command language, where M commands are unavailable. Commands are as follows:
615:
616: @table @asis
617: @item @code{exit}, @code{quit}
618: Exits the debugger and returns to direct mode or normal program execution.
619: @item @code{e} @emph{glvn}, @code{examine} @emph{glvn}
620: Prints the value of @emph{glvn} to the terminal.
621: @item @code{t}, @code{trace}
622: Toggles @emph{trace mode} on and off. When trace mode is on, FreeM will display information about each @code{DO} or @code{GOTO} command encountered, including the routine which invoked the branch, which type of branch was invoked, and the target of the branch.
623: @item @code{s}, @code{step}
624: Single-steps through FreeM code command-by-command.
625: @item @code{n}, @code{next}
626: Single-steps through FreeM code line-by-line.
627: @item @code{c}, @code{cont}, @code{continue}
628: Resumes normal program execution, disabling single-step mode.
629: @item @code{bt}, @code{backtrace}
630: Produces a stack trace.
631: @item @code{h}, @code{halt}
632: Halts the process being debugged and returns control to the operating system.
633: @item @code{w [[+|-|?]@emph{<glvn>}]}, @code{watch [[+|-|?]@emph{<glvn>}]}
634: With no arguments, toggles watchpoints on and off. With @code{+}, adds @emph{<glvn>} to the watchlist. With @code{-}, removes @emph{<glvn>} from the watchlist. With @code{?}, queries the watch status of @emph{<glvn>}.
635: @end table
636:
1.58 snw 637: @node Program Development Cycle
638: @chapter Program Development Cycle
639: @cindex program development
640:
641: This chapter covers the essential activities of program development in the FreeM environment, including viewing, creating, editing, and running routines.
642:
1.1 snw 643: @node Directives
644: @chapter Directives
645: @cindex directives
646:
647: In FreeM, a directive is an instruction embedded in an M comment, and passed to the interpreter to affect a change that is specific to the current routine only.
648:
649: The format of a directive is @code{;%@emph{<directive-name>}}, where @code{@emph{<directive-name>}} is one of the directives listed below.
650:
651: @menu
652: * %DIALECT:: Sets the M dialect in effect.
653: @end menu
654:
655: @anchor{%DIALECT}
656: @section %DIALECT
657: @cindex %DIALECT
658: @cindex directives, %DIALECT
659:
660: Sets the M dialect in effect for the current routine buffer; also sets the @code{$DIALECT} special variable to match. See also @ref{$DIALECT}.
661:
662: @emph{Syntax}
663:
664: @example
665: ;%DIALECT @emph{<dialect>}
666: @end example
667:
668: Valid values for @code{@emph{<dialect>}} are as follows:
669:
670: @table @code
671: @item @code{M77}
672: Restricts FreeM to use only features specified by the 1977 M standard.
673: @item @code{M84}
674: Restricts FreeM to use only features specified by the 1984 M standard.
675: @item @code{M90}
676: Restricts FreeM to use only features specified by the 1990 M standard.
677: @item @code{M95}
678: Restricts FreeM to use only features specified by the 1995 M standard.
679: @item @code{MDS}
680: Restricts FreeM to use only features proposed by the Millennium Draft Standard.
681: @item @code{M5}
682: Restricts FreeM to use only features proposed by the upcoming M5 standard.
683: @item @code{FREEM}, @code{EXTENDED}
684: Removes all standards-based restrictions and allows full access to all FreeM features. This is the default value of @code{%DIALECT}.
685: @end table
686:
687: Please note that FreeM is not entirely standards-compliant, regardless of the value of @code{%DIALECT}.
688:
689:
690: @node Intrinsic Special Variables
691: @chapter Intrinsic Special Variables
692: @cindex variables, intrinsic special
693:
694: @menu
695: * $DEVICE:: $IO device status.
696: * $DIALECT:: Current M dialect.
697: * $ECODE:: Latest M error code.
698: * $ESTACK:: Error stack info.
699: * $ETRAP:: Standard error handler code.
700: * $HOROLOG:: Current date and time.
701: * $IO:: Current I/O device.
702: * $JOB:: PID of current process.
703: * $KEY:: Characters terminating last @code{READ} command.
704: * $PDISPLAY:: Current primary MWAPI display.
705: * $PRINCIPAL:: I/O channel of terminal.
706: * $REFERENCE:: Most recent global reference.
707: * $QUIT:: Whether a @code{QUIT} command requires an argument in the current execution context.
708: * $STACK:: Current program execution stack level.
709: * $STORAGE:: Number of bytes available in the heap.
710: * $SYSTEM:: MDC system ID of FreeM.
711: * $TEST:: Truth value of last conditional expression or result of certain @code{LOCK} operations.
712: * $TLEVEL:: Current level of transaction nesting.
1.42 snw 713: * $WITH:: Current variable prefix set by @code{ZWITH} command.
1.1 snw 714: * $X:: Current horizontal screen position.
715: * $Y:: Current vertical screen position.
716: * $ZA:: Current position of file on @code{$IO}.
717: * $ZB:: Most recent keystroke.
718: * $ZCONTROLC:: Control-C handling flag.
719: * $ZDATE:: Current date in locale-specific representation.
720: * $ZERROR:: Last error message.
721: * $ZHOROLOG:: Date and time, including milliseconds.
722: * $ZINRPT:: State of the interrupt enable/disable flag.
723: * $ZJOB:: PID of parent process, if applicable.
724: * $ZLOCAL:: Last local variable reference.
725: * $ZNAME:: Name of current M routine.
726: * $ZPRECISION:: Digits of arithmetical precision.
727: * $ZREFERENCE:: Last gvn referenced.
728: * $ZSYSTEM:: Return value of last external command.
729: * $ZTIME:: Current time in locale-specific representation.
730: * $ZTRAP:: Entryref to be executed on error condition.
731: * $ZUT:: Microseconds since the UNIX epoch.
732: * $ZVERSION:: Version of FreeM and GNU host triplet.
733: @end menu
734:
735: @node $DEVICE
736: @section $DEVICE
737: @cindex $DEVICE
738: @cindex intrinsic special variables, $DEVICE
739:
740: Returns the status of the device currently in use.
741:
742: If @code{$DEVICE} returns @emph{1}, an error condition exists on the current device. In this case, there will be two additional fields separated by commas, indicating the internal FreeM error code representing the error present on the device and a text explanation of the error.
743:
744: @node $DIALECT
745: @section $DIALECT
746: @cindex $DIALECT
747: @cindex intrinsic special variables, $DIALECT
748:
749: Returns or sets the language dialect of the current routine.
750:
751: Valid values for @code{$DIALECT} are as follows:
752:
753: @table @code
754: @item @code{M77}
755: Restricts FreeM to use only features specified by the 1977 M standard.
756: @item @code{M84}
757: Restricts FreeM to use only features specified by the 1984 M standard.
758: @item @code{M90}
759: Restricts FreeM to use only features specified by the 1990 M standard.
760: @item @code{M95}
761: Restricts FreeM to use only features specified by the 1995 M standard.
762: @item @code{MDS}
763: Restricts FreeM to use only features proposed by the Millennium Draft Standard.
764: @item @code{M5}
765: Restricts FreeM to use only features proposed by the upcoming M5 standard.
766: @item @code{FREEM}, @code{EXTENDED}
767: Removes all standards-based restrictions and allows full access to all FreeM features. This is the default value of @code{$DIALECT}.
768: @end table
769:
770: Please note that FreeM is not entirely standards-compliant, regardless of the value of @code{$DIALECT}.
771:
772: @node $ECODE
773: @section $ECODE
774: @cindex $ECODE
775: @cindex intrinsic special variables, $ECODE
776:
777: Returns a comma-delimited list of error conditions currently present, and is writable. An empty @code{$ECODE} indicates no errors.
778:
1.28 snw 779: Writing a value in the format @code{,<error-code>,} into @code{$ECODE} will raise that error condition.
780:
1.1 snw 781: @node $ESTACK
782: @section $ESTACK
783: @cindex $ESTACK
784: @cindex intrinsic special variables, $ESTACK
785:
786: 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{@ref{$STACK}} ISV in that it is @code{@ref{NEW}}-able, and resets to a value of 0 when @code{@ref{NEW}}ed.
787:
788: @node $ETRAP
789: @section $ETRAP
790: @cindex $ETRAP
791: @cindex intrinsic special variables, $ETRAP
792:
793: Sets or retrieves the M code that is run when an error is encountered or @code{@ref{$ECODE}} is set to a non-blank value. @code{$ETRAP} code executes when @code{$ECODE} becomes non-blank.
794:
795:
796: @node $HOROLOG
797: @section $HOROLOG
798: @cindex $HOROLOG
799: @cindex intrinsic special variables, $HOROLOG
800:
801: Returns a string containing the current date and time as @code{<days>,<seconds>}, where @code{<days>} represents the number of days since the M epoch (midnight on 31 December 1840),
802: and @code{<seconds>} represents the number of seconds since the most recent midnight.
803:
804: @cartouche
805: @quotation
806: @emph{FreeM Extension}
807:
808: In FreeM, @code{$HOROLOG} is @code{@ref{SET}}table. Setting @code{$HOROLOG} will set the system clock if your user account has the appropriate permissions. If your user account does not have permissions to modify the system clock, FreeM will raise a @code{ZPROTECT} error.
809: @end quotation
810: @end cartouche
811:
812: @node $IO
813: @section $IO
814: @cindex $IO
815: @cindex intrinsic special variables, $IO
816:
817: Represents the current input/output device. Read-only.
818:
819: @node $JOB
820: @section $JOB
821: @cindex $JOB
822: @cindex intrinsic special variables, $JOB
823:
824: Represents the process ID of the FreeM instance currently in use.
825:
826: @node $KEY
827: @section $KEY
828: @cindex $KEY
829: @cindex intrinsic special variables, $KEY
830:
831: Represents the sequence of control characters that terminated the last @code{@ref{READ}} command on @code{@ref{$IO}}.
832:
833: @node $PDISPLAY
834: @section $PDISPLAY
835: @cindex $PDISPLAY
836: @cindex intrinsic special variables, $PDISPLAY
837:
838: Represents the current principal display for M Windowing API operations. Commonly used as an index into the @code{@ref{^$DISPLAY}} structured system variable.
839:
840: @node $PRINCIPAL
841: @section $PRINCIPAL
842: @cindex $PRINCIPAL
843: @cindex intrinsic special variables, $PRINCIPAL
844:
845: Represents the primary input/output device. Usually a terminal or virtual terminal.
846:
847: @node $REFERENCE
848: @section $REFERENCE
849: @cindex $REFERENCE
850: @cindex intrinsic special variables, $REFERENCE
851:
852: Returns the last @emph{glvn} referenced. Can be @code{@ref{SET}}, and also stacked with @code{@ref{NEW}}.
853:
854: @node $QUIT
855: @section $QUIT
856: @cindex $QUIT
857: @cindex intrinsic special variables, $QUIT
858:
859: If the current execution context was invoked as an extrinsic function, @code{$QUIT} returns @emph{1}. Otherwise, returns @emph{0}.
860:
861: When @code{$QUIT} returns @emph{1}, a subsequent @code{@ref{QUIT}} command must have an argument.
862:
863: @node $STACK
864: @section $STACK
865: @cindex $STACK
866: @cindex intrinsic special variables, $STACK
867:
868: Represents the current stack level.
869:
870: @node $STORAGE
871: @section $STORAGE
872: @cindex $STORAGE
873: @cindex intrinsic special variables, $STORAGE
874:
875: Represents the number of bytes of free space available in FreeM's heap.
876:
877: @node $SYSTEM
878: @section $SYSTEM
879: @cindex $SYSTEM
880: @cindex intrinsic special variables, $SYSTEM
881:
882: Returns the MDC system ID of FreeM, as well as the environment ID of the current environment.
883:
884: @node $TEST
885: @section $TEST
886: @cindex $TEST
887: @cindex intrinsic special variables, $TEST
888:
889: @code{$TEST} is a writable, @code{@ref{NEW}}-able ISV that is @emph{1} if the most recently evaluated expression was @emph{true}. Otherwise, returns @emph{0}.
890:
891: @code{$TEST} is implicitly @code{NEW}ed when entering a new stack frame for extrinsic functions and argumentless @code{@ref{DO}}. @code{$TEST}
892: is @emph{not} implicitly @code{NEW}ed when a new stack frame is entered with an argumented @code{DO}.
893:
894: For single-line @code{@ref{IF}} or @code{@ref{ELSE}} expressions, you may use @code{@ref{THEN}} to stack @code{$TEST} until the end of the line. All new code should employ @code{THEN} in this manner, as stacking @code{$TEST} prevents a wide range of coding errors that can be very challenging to detect and eliminate.
895:
896: @node $TLEVEL
897: @section $TLEVEL
898: @cindex $TLEVEL
899: @cindex intrinsic special variables, $TLEVEL
900:
901: Returns a numeric value indicating the current level of transaction nesting in the process. When @code{$TLEVEL} is greater than @emph{0},
902: uncommitted transactions exist.
903:
904: @node $WITH
905: @section $WITH
906: @cindex $WITH
907: @cindex intrinsic special variables, $WITH
908:
1.42 snw 909: Returns the variable prefix set by the @code{@ref{ZWITH}} command.
1.1 snw 910:
911: @node $X
912: @section $X
913: @cindex $X
914: @cindex intrinsic special variables, $X
915:
916: Represents the current column position of the FreeM cursor.
917:
918: @cartouche
919: @quotation
920: In FreeM, setting @code{$X} will move the FreeM cursor.
921: @end quotation
922: @end cartouche
923:
924:
925: @node $Y
926: @section $Y
927: @cindex $Y
928: @cindex intrinsic special variables, $Y
929:
930: Represents the current row position of the FreeM cursor.
931:
932: @cartouche
933: @quotation
934: In FreeM, setting @code{$Y} will move the FreeM cursor.
935: @end quotation
936: @end cartouche
937:
938:
939: @node $ZA
940: @section $ZA
941: @cindex $ZA
942: @cindex intrinsic special variables, $ZA
943: @cindex intrinsic special variables, implementation-specific
944:
945: On the @code{HOME} device, always @code{0}. On other devices, returns the current position of the file opened on I/O channel @code{@ref{$IO}}.
946:
947: @node $ZB
948: @section $ZB
949: @cindex $ZB
950: @cindex intrinsic special variables, $ZB
951: @cindex intrinsic special variables, implementation-specific
952:
953: Represents the last keystroke.
954:
955: @node $ZCONTROLC
956: @section $ZCONTROLC
957: @cindex $ZCONTROLC
958: @cindex intrinsic special variables, $ZCONTROLC
959: @cindex intrinsic special variables, implementation-specific
960:
961: Returns the status of the Ctrl-C flag and resets it to @emph{false}.
962:
963: @node $ZDATE
964: @section $ZDATE
965: @cindex $ZDATE
966: @cindex intrinsic special variables, $ZDATE
967: @cindex intrinsic special variables, implementation-specific
968:
969: Returns the current date, in the preferred representation for the current system locale.
970:
971: @node $ZERROR
972: @section $ZERROR
973: @cindex $ZERROR
974: @cindex intrinsic special variables, $ZERROR
975: @cindex intrinsic special variables, implementation-specific
976:
977: Returns the last error message.
978:
979: @node $ZHOROLOG
980: @section $ZHOROLOG
981: @cindex $ZHOROLOG
982: @cindex intrinsic special variables, $ZHOROLOG
983: @cindex intrinsic special variables, implementation-specific
984:
985: Output @code{@ref{$HOROLOG}}-style time, with the addition of milliseconds.
986:
987: @node $ZINRPT
988: @section $ZINRPT
989: @cindex $ZINRPT
990: @cindex intrinsic special variables, $ZINRPT
991: @cindex intrinsic special variables, implementation-specific
992:
993: Gets or sets the interrupt enable/disable flag.
994:
995: @node $ZJOB
996: @section $ZJOB
997: @cindex $ZJOB
998: @cindex intrinsic special variables, $ZJOB
999: @cindex intrinsic special variables, implementation-specific
1000:
1001: Returns the @code{@ref{$JOB}} value of the parent process if the current process was started by a @code{@ref{JOB}} command. Otherwise, returns an empty string.
1002:
1003: @node $ZLOCAL
1004: @section $ZLOCAL
1005: @cindex $ZLOCAL
1006: @cindex intrinsic special variables, $ZLOCAL
1007: @cindex intrinsic special variables, implementation-specific
1008:
1009: Returns the last local variable referenced.
1010:
1011: @node $ZNAME
1012: @section $ZNAME
1013: @cindex $ZNAME
1014: @cindex intrinsic special variables, $ZNAME
1015: @cindex intrinsic special variables, implementation-specific
1016:
1017: Returns the name of the current routine.
1018:
1019: @node $ZPRECISION
1020: @section $ZPRECISION
1021: @cindex $ZPRECISION
1022: @cindex intrinsic special variables, $ZPRECISION
1023: @cindex intrinsic special variables, implementation-specific
1024:
1025: Gets or sets the number of digits of numeric precision used for fixed-point decimal arithmetic. If @code{^$JOB($JOB,"MATH")} is @code{IEEE754}, @code{$ZPRECISION} defaults to 16 digits, with a maximum of 16 digits. If @code{^$JOB($JOB,"MATH")} is @code{FIXED}, @code{$ZPRECISION} defaults to 100 digits, with a maximum of 20,000 digits.
1026:
1027: @xref{^$JOB}.
1028:
1029: @node $ZREFERENCE
1030: @section $ZREFERENCE
1031: @cindex $ZREFERENCE
1032: @cindex intrinsic special variables, $ZREFERENCE
1033: @cindex intrinsic special variables, implementation-specific
1034:
1035: Returns the last @emph{gvn} referenced.
1036:
1037: @node $ZSYSTEM
1038: @section $ZSYSTEM
1039: @cindex $ZSYSTEM
1040: @cindex intrinsic special variables, $ZSYSTEM
1041: @cindex intrinsic special variables, implementation-specific
1042:
1043: Represents the return value of the last external command run with @code{!}.
1044:
1045: @node $ZTIME
1046: @section $ZTIME
1047: @cindex $ZTIME
1048: @cindex intrinsic special variables, $ZTIME
1049: @cindex intrinsic special variables, implementation-specific
1050:
1051: Returns the system time in the preferred representation for the current system locale.
1052:
1053: @node $ZTRAP
1054: @section $ZTRAP
1055: @cindex $ZTRAP
1056: @cindex intrinsic special variables, $ZTRAP
1057: @cindex intrinsic special variables, implementation-specific
1058:
1059: 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.
1060:
1061: In FreeM-style error processing, @code{$ZTRAP} is specific to each program execution stack level.
1062:
1063: In DSM 2.0-style error processing, @code{$ZTRAP} is the same for all program execution stack levels.
1064:
1065: When FreeM encounters an error, if @code{$ZTRAP} is nonempty and @code{$ETRAP} is empty, FreeM will perform an implicit @code{@ref{GOTO}} to the entryref indicated in @code{$ZTRAP}.
1066:
1067: 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.
1068:
1069: @node $ZUT
1070: @section $ZUT
1071: @cindex $ZUT
1072: @cindex intrinsic special variables, $ZUT
1073: @cindex intrinsic special variables, implementation-specific
1074:
1075: Returns the number of microseconds elapsed since the UNIX epoch (Jan 1, 1970 0:00:00).
1076:
1077: @node $ZVERSION
1078: @section $ZVERSION
1079: @cindex $ZVERSION
1080: @cindex intrinsic special variables, $ZVERSION
1081: @cindex intrinsic special variables, implementation-specific
1082:
1083: Returns the version of FreeM in use, as well as the GNU host triplet for the current FreeM build.
1084:
1085: See @emph{https://wiki.osdev.org/Target_Triplet}.
1086:
1087: @node Intrinsic Functions
1088: @chapter Intrinsic Functions
1089:
1090: @menu
1091: * $ASCII():: Return ASCII code for character in string.
1092: * $CHAR():: Return character for one or more ASCII codes.
1093: * $DATA():: Retrieve definition and characteristics of array node.
1094: * $EXTRACT():: Return a substring of a string.
1095: * $FIND():: Find position of substring within string.
1096: * $FNUMBER():: Format a number according to formatting codes.
1097: * $GET():: Return value of glvn or a default if undefined.
1098: * $INSTANCEOF():: Determine if lvn is an instance of a class.
1099: * $JUSTIFY():: Right-justify a string based on specified length.
1100: * $LENGTH():: Return length or delimiter-based piece count of string.
1101: * $NAME():: Return canonical name from string representation of glvn.
1102: * $NEXT():: Return next numeric subscript following given glvn.
1103: * $ORDER():: Return next subscript at same level of specified glvn.
1104: * $PIECE():: Return one or more delimited pieces of a string.
1105: * $QLENGTH():: Return subscript count of glvn.
1106: * $QSUBSCRIPT():: Return a specified subscript from glvn.
1107: * $QUERY():: Return next subscript of specified glvn.
1108: * $RANDOM():: Return pseudorandom integer up to a maximum value.
1109: * $REVERSE():: Reverse a string.
1110: * $SELECT():: Return value from first true condition in list of expressions.
1111: * $STACK():: Return information about the program stack.
1112: * $TEXT():: Return line of code from a routine.
1113: * $TRANSLATE():: Substitute specified characters in a string.
1114: * $TYPE():: Return class of the specified lvn.
1115: * $VIEW():: Retrieve implementation-specific information.
1116: * $ZBOOLEAN():: Perform boolean operations on numeric arguments.
1117: * $ZCALL():: Unknown.
1118: * $ZCRC():: Generate checksum of a string argument.
1119: * $ZDATA():: Unknown.
1120: * $ZDATE():: Convert @code{@ref{$HOROLOG}} string into human-readable date.
1121: * $ZEDIT():: Unknown.
1122: * $ZHOROLOG():: Convert date/time values to @code{@ref{$HOROLOG}} format.
1123: * $ZKEY():: Unknown.
1124: * $ZLENGTH():: Unknown.
1125: * $ZLSD():: Compute Levenshtein distance between two arguments.
1126: * $ZM():: Unknown.
1127: * $ZNAME():: Unknown.
1.52 snw 1128: * $ZNEXT():: Return glvn of next numeric subscript following given glvn.
1.1 snw 1129: * $ZORDER():: Unknown.
1130: * $ZPIECE():: Unknown.
1131: * $ZPREVIOUS():: Unknown.
1132: * $ZREPLACE():: Replace all instances of a substring within a string.
1133: * $ZSYNTAX():: Perform syntax check on string argument.
1134: * $ZTIME():: Convert a @code{@ref{$HOROLOG}} string into human-readable time.
1135: @end menu
1136:
1137: @node $ASCII()
1138: @section $ASCII
1139: @cindex $ASCII
1140: @cindex intrinsic functions, $ASCII
1141:
1142: Returns the ASCII code (in decimal) for one character in a string.
1143:
1144: @example
1145: SET RESULT=$ASCII(@emph{<string>}[,@emph{<index>}])
1146: @end example
1147:
1148:
1149: If @emph{<index>} 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{<index>}.
1150:
1151: @node $CHAR()
1152: @section $CHAR
1153: @cindex $CHAR
1154: @cindex intrinsic functions, $CHAR
1155:
1156: Returns a string of characters corresponding to a list of ASCII codes.
1157:
1158: @example
1159: SET RESULT=$CHAR(@emph{<ascii-code>}[,@emph{<ascii-code>},...])
1160: @end example
1161:
1162: @node $DATA()
1163: @section $DATA
1164: @cindex $DATA
1165: @cindex intrinsic functions, $DATA
1166:
1167: Returns a numeric value 0, 1, 10, or 11, depending on whether a referenced node is defined, has data, or has children:
1168:
1169: @example
1170: SET RESULT=$DATA(@emph{<node>})
1171: @end example
1172:
1173: The return values are as follows:
1174:
1175: @example
1176: 0: @emph{<node>} is undefined
1177: 1: @emph{<node>} has data but no children
1178: 10: @emph{<node>} has children but no data
1179: 11: @emph{<node>} has children and data
1180: @end example
1181:
1182: @node $EXTRACT()
1183: @section $EXTRACT
1184: @cindex $EXTRACT
1185: @cindex intrinsic functions, $EXTRACT
1186:
1187: Extracts a substring of a string.
1188:
1189: The first argument is the source string.
1190:
1191: The optional second argument specifies the starting position of the substring to extract, and defaults to @code{1}.
1192:
1193: The optional third argument specifies the ending position of the substring to extract, and defaults to the value of the second argument, or @code{1}.
1194:
1195: This example will extract the string @emph{FreeM} into the local variable @code{M}.
1196:
1197: @example
1198: SET NAME="FreeM is the best!"
1199: SET M=$EXTRACT(NAME,1,5)
1200: @end example
1201:
1202: It is also possible to use @code{$EXTRACT} on the left-hand side of a @code{SET} assignment in order to modify a substring:
1203:
1204: @example
1.22 snw 1205: DEFAULT.USER> SET FOO="ABCDEFG"
1.1 snw 1206:
1207:
1.22 snw 1208: DEFAULT.USER> SET $EXTRACT(FOO,1,3)="XYZ"
1.1 snw 1209:
1210:
1.22 snw 1211: DEFAULT.USER> WRITE FOO
1.1 snw 1212:
1213: XYZDEFG
1214: @end example
1215:
1216: @node $FIND()
1217: @section $FIND
1218: @cindex $FIND
1219: @cindex intrinsic functions, $FIND
1220:
1221: Finds the character immediately following the first occurence of a substring within a string.
1222:
1223: The first argument is the source string.
1224:
1225: The second argument is the substring to be located.
1226:
1227: The optional third argument indicates the position within the source string at which to begin searching.
1228:
1229: @node $FNUMBER()
1230: @section $FNUMBER
1231: @cindex $FNUMBER
1232: @cindex intrinsic functions, $FNUMBER
1233:
1234: Formats a number according to a particular set of formatting codes.
1235:
1236: The first argument is the number to format.
1237:
1.22 snw 1238: The second argument is the series of formatting codes:
1239:
1240: @table @asis
1241: @item 'P' or 'p'
1242: Will display negative numbers within parentheses instead of showing a minus sign.
1243: @item , (comma)
1244: Will add commas as thousands separators.
1245: @item +
1246: Will include a plus sign for positive numbers. Not compatible with 'P' or 'p'.
1247: @item -
1248: Will remove the minus sign from negative numbers. Not compatible with 'p' or 'P'.
1249: @item 't' or 'T'
1250: Will place the sign after the number instead of before the number.
1.23 snw 1251: @end table
1.22 snw 1252:
1253: The optional third argument is a number indicating how many digits to which the fractional part of the number will be zero-padded.
1.1 snw 1254:
1255: @node $GET()
1256: @section $GET
1257: @cindex $GET
1258: @cindex intrinsic functions, $GET
1259:
1260: Returns the value of a local, global, or SSVN if the specified item is defined, or a default value otherwise.
1261:
1262: The first argument is the local, global, or SSVN to be examined.
1263:
1264: The optional second argument is the default value to be returned if the referenced item is undefined, and defaults to the empty string.
1265:
1266: @node $INSTANCEOF()
1267: @section $INSTANCEOF
1268: @cindex $INSTANCEOF
1269: @cindex intrinsic functions, $INSTANCEOF
1270: @cindex object functions, $INSTANCEOF
1271:
1272: Returns @code{1} if the specified @emph{lvn} is an instance of class @emph{class}, or @code{0} otherwise.
1273:
1274: The first argument is a string representing a valid FreeM local variable.
1275:
1276: The second argument is a string representing a valid FreeM class.
1277:
1278: @example
1.22 snw 1279: DEFAULT.USER> N STR=$$^%STRING
1.1 snw 1280:
1.22 snw 1281: DEFAULT.USER> W $INSTANCEOF("STR","^%STRING")
1.1 snw 1282: 1
1283: @end example
1284:
1285: @node $JUSTIFY()
1286: @section $JUSTIFY
1287: @cindex $JUSTIFY
1288: @cindex intrinsic functions, $JUSTIFY
1289:
1290: Right-justifies a string based on a specified fixed length.
1291:
1292: The first argument is the source string.
1293:
1294: The second argument is the character length of the output.
1295:
1296: The optional third argument controls the number of fractional digits to be included in the output, and defaults to the number of digits specified in the first argument.
1297:
1298: @node $LENGTH()
1299: @section $LENGTH
1300: @cindex $LENGTH
1301: @cindex intrinsic functions, $LENGTH
1302:
1303: Returns the length of a string, or the number of items in a list delimited by a specified character (as used by @code{@ref{$PIECE()}}).
1304:
1305: The first argument is the source string.
1306:
1307: The optional second argument is the list delimiter to be used. When this argument is omitted, the length of the string in characters is returned.
1308:
1309: @node $NAME()
1310: @section $NAME
1311: @cindex $NAME
1312: @cindex intrinsic functions, $NAME
1313:
1314: Returns the canonical name reference along with some or all of its subscripts.
1315:
1316: The first argument is the source name.
1317:
1318: The optional second argument indicates the maximum subscript count to be returned, and defaults to the subscript count of the source name.
1319:
1320: @node $NEXT()
1321: @section $NEXT
1322: @cindex $NEXT
1323: @cindex intrinsic functions, $NEXT
1324:
1.25 snw 1325: Deprecated. Use @code{$ORDER} instead.
1.52 snw 1326: Returns the next numeric subscript of the specified glvn.
1327:
1328: @emph{Syntax}
1329:
1330: @example
1331: $NEXT(@emph{glvn})
1332: @end example
1333:
1334: @emph{Example}
1335:
1336: Assume the following array:
1337:
1338: @example
1339: ^foo(1)=""
1340: ^foo(2)=""
1341: @end example
1342:
1343: And the following code:
1344:
1345: @example
1346: W $ZNEXT(^foo(1)) ; => 2
1347: @end example
1.25 snw 1348:
1.1 snw 1349: @node $ORDER()
1350: @section $ORDER
1351: @cindex $ORDER
1352: @cindex intrinsic functions, $ORDER
1353:
1.25 snw 1354: Returns the previous subscript or next subscript in a local, global, or a subset of structured system variables.
1355:
1356: The first argument is the subscripted local, global, or SSVN.
1357:
1358: The optional second argument can be @code{1} to retrieve the next subscript, or @code{-1} to return the previous.
1359:
1.1 snw 1360: @node $PIECE()
1361: @section $PIECE
1362: @cindex $PIECE
1363: @cindex intrinsic functions, $PIECE
1364:
1365: @emph{Syntax}
1366:
1367: @code{$PIECE(@emph{s},@emph{d}[,@emph{n}[,@emph{end}]])}
1368:
1369: Accesses the @code{n}th through @code{end} @code{d}-delimited pieces of string @code{s}.
1370:
1371: The first argument is the string to be evaluated.
1372:
1373: The second argument is the delimiter to be used.
1374:
1375: The optional third argument is the first @code{d}-delimited piece to access, and defaults to @code{1}.
1376:
1377: The optional fourth argument is the final @code{d}-delimited piece to access, and defaults to the value of the third argument (@code{n}).
1378:
1379: Can be used on the left-hand side of an expression in order to @code{@ref{SET}} a value into a @code{d}-delimited piece of @code{s}, as in:
1380:
1381: @example
1.28 snw 1382: ; ^snw="this^is^a^piece"
1383: SET $PIECE(^snw,"^",2)="isn't" ; => "this^isn't^a^piece"
1.1 snw 1384: @end example
1385:
1386: @node $QLENGTH()
1387: @section $QLENGTH
1388: @cindex $QLENGTH
1389: @cindex intrinsic functions, $QLENGTH
1390:
1391: @emph{Syntax}
1392:
1393: @example
1394: @code{$QLENGTH(@emph{expr V glvn})}
1395: @end example
1396:
1397: Returns the number of subscripts in @emph{glvn}.
1398:
1399: @emph{Example}
1400: @example
1401: @code{SET SUBCT=$QLENGTH("^GBL(1,2,3)") ; => 3}
1402: @end example
1403:
1404: @node $QSUBSCRIPT()
1405: @section $QSUBSCRIPT
1406: @cindex $QSUBSCRIPT
1407: @cindex intrinsic functions, $QSUBSCRIPT
1408:
1409: @emph{Syntax}
1410:
1411: @example
1412: @code{$QSUBSCRIPT(@emph{expr V glvn},@emph{expr V n})}
1413: @end example
1414:
1.28 snw 1415: In the RHS form, returns the @emph{n}th subscript of @emph{glvn}.
1.1 snw 1416:
1417: @emph{Example}
1418:
1419: @example
1420: @code{SET SUB=$QSUBSCRIPT("^GBL(1,2,3)",2) ; => 2}
1421: @end example
1422:
1.28 snw 1423: @emph{Syntax}
1424:
1425: @example
1426: @code{SET $QSUBSCRIPT(@emph{expr V glvn},@emph{expr V n})=@emph{expr} ; => ^GBL(1,4,3)}
1427: @end example
1428:
1429: In the LHS form, sets the @emph{n}th subscript of @emph{glvn} to @emph{expr}.
1430:
1.1 snw 1431: @node $QUERY()
1432: @section $QUERY
1433: @cindex $QUERY
1434: @cindex intrinsic functions, $QUERY
1435:
1436: Returns the next subscripted reference in a global.
1437:
1438: @emph{Syntax}
1439:
1440: @example
1441: @code{$QUERY(@emph{glvn})}
1442: @end example
1443:
1444: @emph{Example}
1445:
1446: We will assume the following data structure exists:
1447: @example
1.28 snw 1448: ^snw(1)=1
1449: ^snw(1,2)="foo"
1450: ^snw(2)=3
1451: ^snw(3)=""
1.1 snw 1452: @end example
1453:
1.28 snw 1454: The following code will retrieve the next subscripted name after @code{^snw(1)}:
1.1 snw 1455:
1456: @example
1.28 snw 1457: @code{SET NEXTNAM=$QUERY(^snw(1)) ; => ^snw(1,2)}
1.1 snw 1458: @end example
1459:
1460: @node $RANDOM()
1461: @section $RANDOM
1462: @cindex $RANDOM
1463: @cindex intrinsic functions, $RANDOM
1464:
1465: @emph{Syntax}
1466:
1467: @example
1468: $RANDOM(@emph{max})
1469: @end example
1470:
1471: Returns a pseudo-random integer in the range of @code{0..@emph{max} - 1}
1472:
1473: @node $REVERSE()
1474: @section $REVERSE
1475: @cindex $REVERSE
1476: @cindex intrinsic functions, $REVERSE
1477:
1478: @emph{Syntax}
1479:
1480: @example
1481: $REVERSE(@emph{s})
1482: @end example
1483:
1484: Returns the reverse of string @emph{s}.
1485:
1486: @emph{Example}
1487:
1488: @example
1489: SET FOO=$REVERSE("ABC") ; => CBA
1490: @end example
1491:
1492: @node $SELECT()
1493: @section $SELECT
1494: @cindex $SELECT
1495: @cindex intrinsic functions, $SELECT
1496:
1497: Returns a value corresponding to the first true condition in a list of conditional expressions. Each argument is an expression, followed by a colon, followed by an expression whose value will be returned if the first expression is true. If no expressions are true, error condition @code{M4} is raised.
1498:
1499: @emph{Example}
1500:
1501: @example
1502: SET FOO=$SELECT(1=2:"math is broken",1=1:"the world makes sense") ; => "the world makes sense"
1503: @end example
1504:
1505: @node $STACK()
1506: @section $STACK
1507: @cindex $STACK
1508: @cindex intrinsic functions, $STACK
1509:
1510: Returns information about the program execution stack. The @code{$STACK} intrinsic function has both a one-argument form and a two-argument form.
1511:
1512: @emph{Syntax (One-Argument)}
1513:
1514: @example
1515: $STACK(@emph{<num>})
1516: @end example
1517:
1518: If @emph{num} is @code{0}, returns the command with which this FreeM instance was invoked.
1519:
1520: If @emph{num} is @code{-1}, returns the current program execution stack level.
1521:
1522: 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:
1523:
1524: @table @asis
1525:
1526: @item @code{$$}
1527: If @code{$STACK(@emph{<num>})="$$"}, program execution stack level @code{num} was created as the result of an extrinsic function call
1528:
1529: @item @emph{<m-command>}
1530: If @code{$STACK(@emph{<num>})} returns a valid M command, the referenced program execution stack level was created as a result of the @emph{m-command} command.
1531:
1532: @end table
1533:
1534: @emph{Syntax (Two-Argument})
1535:
1536: @example
1537: $STACK(@emph{<num>},"[ECODE|MCODE|PLACE]")
1538: @end example
1539:
1540: Returns the error codes, M program code, or entryref applicable to the action that created program execution stack level @emph{num}.
1541:
1542: @node $TEXT()
1543: @section $TEXT
1544: @cindex $TEXT
1545: @cindex intrinsic functions, $TEXT
1546:
1547: Returns a line of code from a routine.
1548:
1549: @node $TRANSLATE()
1550: @section $TRANSLATE
1551: @cindex $TRANSLATE
1552: @cindex intrinsic functions, $TRANSLATE
1553:
1.25 snw 1554: Replaces characters in a string.
1555:
1556: The first argument is a string expression representing the text to be changed.
1557:
1558: The second argument is a list of characters to replace.
1559:
1560: The third argument is a list of characters to use as the replacements for the characters in the second argument.
1561:
1562: @emph{Example}
1563:
1564: @example
1565: DEFAULT.USER> W $TRANSLATE("twig","wt","rb")
1566: brig
1567: @end example
1568:
1.1 snw 1569: @node $TYPE()
1570: @section $TYPE
1571: @cindex $TYPE
1572: @cindex intrinsic functions, $TYPE
1573: @cindex object functions, $TYPE
1574:
1575: Returns a string giving the class of the object specified in the parameter.
1576:
1577: @xref{Object-Oriented Programming}
1578:
1579: @node $VIEW()
1580: @section $VIEW
1581: @cindex $VIEW
1582: @cindex intrinsic functions, $VIEW
1583:
1584: @node $ZBOOLEAN()
1585: @section $ZBOOLEAN
1586: @cindex $ZBOOLEAN
1587: @cindex intrinsic functions, $ZBOOLEAN
1588: @cindex intrinsic functions, implementation-specific
1589:
1590:
1591: Performs @emph{boolean-operation} on numeric arguments @emph{A} and @emph{B}.
1592:
1593: @emph{Syntax}
1594:
1595: @example
1596: SET RESULT=$ZBOOLEAN(@emph{A},@emph{B},@emph{boolean-operation})
1597: @end example
1598:
1599: @code{$ZBOOLEAN} Operations (@emph{boolean-operation} values)
1600:
1601: @table @code
1602: @item 0
1603: Always @emph{false}
1604: @item 1
1605: @code{A AND B}
1606: @item 2
1607: @code{A AND NOT B}
1608: @item 3
1609: @code{A}
1610: @item 4
1611: @code{NOT A AND B}
1612: @item 5
1613: @code{B}
1614: @item 6
1615: @code{A XOR B}
1616: @item 7
1617: @code{A OR B}
1618: @item 8
1619: @code{A NOR B}
1620: @item 9
1621: @code{A EQUALS B}
1622: @item 10
1623: @code{NOT B}
1624: @item 11
1625: @code{A OR NOT B}
1626: @item 12
1627: @code{NOT A}
1628: @item 13
1629: @code{NOT A OR B}
1630: @item 14
1631: @code{A NAND B}
1632: @item 15
1633: Always @emph{true}
1634: @end table
1635:
1636: @node $ZCALL()
1637: @section $ZCALL
1638: @cindex $ZCALL
1639: @cindex intrinsic functions, $ZCALL
1640: @cindex intrinsic functions, implementation-specific
1641:
1.26 snw 1642: Purpose unknown.
1643:
1.1 snw 1644: @node $ZCRC()
1645: @section $ZCRC
1646: @cindex $ZCRC
1647: @cindex intrinsic functions, $ZCRC
1648: @cindex intrinsic functions, implementation-specific
1649:
1650: Returns a checksum of @code{arg1}.
1651:
1652: @emph{Syntax}
1653:
1654: @code{$ZCRC(@emph{arg1})}
1655:
1656: @code{SET VAR=$ZCRC("MUMPS") ; => 86}
1657:
1658: @node $ZDATA()
1659: @section $ZDATA
1660: @cindex $ZDATA
1661: @cindex intrinsic functions, $ZDATA
1662: @cindex intrinsic functions, implementation-specific
1663:
1.26 snw 1664: Purpose unknown.
1665:
1.1 snw 1666: @node $ZDATE()
1667: @section $ZDATE
1668: @cindex $ZDATE
1669: @cindex intrinsic functions, $ZDATE
1670: @cindex intrinsic functions, implementation-specific
1671:
1672: Converts a @code{@ref{$HOROLOG}} string into a human-readable date.
1673:
1674: @emph{Syntax}
1675:
1676: @example
1677: SET VAR=$ZDATE($H[,@emph{<format-string>}])
1678: @end example
1679:
1680: The optional @emph{<format-string>} follows the same rules as the UNIX @code{strftime} function. If @emph{<format-string>} is omitted, the value of @code{^$SYSTEM("ZDATE_FORMAT")} is used (typically @code{%x}).
1681:
1682: @xref{^$SYSTEM}
1683:
1684: @node $ZEDIT()
1685: @section $ZEDIT
1686: @cindex $ZEDIT
1687: @cindex intrinsic functions, $ZEDIT
1688: @cindex intrinsic functions, implementation-specific
1689:
1.26 snw 1690: Purpose unknown.
1691:
1.1 snw 1692: @node $ZHOROLOG()
1693: @section $ZHOROLOG
1694: @cindex $ZHOROLOG
1695: @cindex intrinsic functions, $ZHOROLOG
1696: @cindex intrinsic functions, implementation-specific
1697:
1698: Converts date and/or time values producible by @code{@ref{$ZDATE()}} or @code{@ref{$ZTIME()}} to @code{@ref{$HOROLOG}} format.
1699:
1700: @emph{Syntax}
1701:
1702: @example
1703: $ZHOROLOG(@emph{<date-value>},@emph{<format-string>})
1704: @end example
1705:
1706: @emph{<date-value>} is a date or time string compatible with the formats from @code{@ref{$ZDATE()}} or @code{@ref{$ZTIME}}.
1707:
1708: @emph{<format-string>} is a format string of the same format as used by the @code{strptime(3)} UNIX function.
1709:
1710: @node $ZKEY()
1711: @section $ZKEY
1712: @cindex $ZKEY
1713: @cindex intrinsic functions, $ZKEY
1714: @cindex intrinsic functions, implementation-specific
1715:
1.26 snw 1716: Purpose unknown.
1717:
1.1 snw 1718: @node $ZLENGTH()
1719: @section $ZLENGTH
1720: @cindex $ZLENGTH
1721: @cindex intrinsic functions, $ZLENGTH
1722: @cindex intrinsic functions, implementation-specific
1723:
1.26 snw 1724: Purpose unknown.
1725:
1.1 snw 1726: @node $ZLSD()
1727: @section $ZLSD
1728: @cindex $ZLSD
1729: @cindex intrinsic functions, $ZLSD
1730: @cindex intrinsic functions, implementation-specific
1731:
1732: Returns the Levenshtein distance between two arguments. The Levenshtein distance represents the minimum number of edits needed to change the first argument into the second argument.
1733:
1734: @emph{Syntax}
1735:
1736: @code{SET VAR=$ZLSD(@emph{arg1},@emph{arg2})}
1737:
1738: @emph{Example}
1739:
1740: @code{SET VAR=$ZLSD("KITTENS","MITTENS") ; => 1}
1741:
1742: @node $ZM()
1743: @section $ZM
1744: @cindex $ZM
1745: @cindex intrinsic functions, $ZM
1746: @cindex intrinsic functions, implementation-specific
1747:
1.51 snw 1748: Purpose unknown.
1749:
1.1 snw 1750: @node $ZNAME()
1751: @section $ZNAME
1752: @cindex $ZNAME
1753: @cindex intrinsic functions, $ZNAME
1754: @cindex intrinsic functions, implementation-specific
1755:
1.26 snw 1756: Purpose unknown.
1757:
1.52 snw 1758: This function relies on the value of @code{$VIEW(71)} being @code{0} (this is not the default).
1759:
1.1 snw 1760: @node $ZNEXT()
1761: @section $ZNEXT
1762: @cindex $ZNEXT
1763: @cindex intrinsic functions, $ZNEXT
1764: @cindex intrinsic functions, implementation-specific
1765:
1.52 snw 1766: Returns a fully-formed variable reference of the next numeric subscript of the specified glvn.
1767:
1768: @emph{Syntax}
1769:
1770: @example
1771: $ZNEXT(@emph{glvn})
1772: @end example
1773:
1774: @emph{Example}
1775:
1776: Assume the following array:
1777:
1778: @example
1779: ^foo(1)=""
1780: ^foo(2)=""
1781: @end example
1782:
1783: And the following code:
1784:
1785: @example
1786: W $ZNEXT(^foo(1)) ; => ^foo(2)
1787: @end example
1788:
1789: This function relies on the value of @code{$VIEW(71)} being @code{1} (this is the default).
1.26 snw 1790:
1.1 snw 1791: @node $ZORDER()
1792: @section $ZORDER
1793: @cindex $ZORDER
1794: @cindex intrinsic functions, $ZORDER
1795: @cindex intrinsic functions, implementation-specific
1796:
1.26 snw 1797: Purpose unknown.
1798:
1.1 snw 1799: @node $ZPIECE()
1800: @section $ZPIECE
1801: @cindex $ZPIECE
1802: @cindex intrinsic functions, $ZPIECE
1803: @cindex intrinsic functions, implementation-specific
1804:
1.26 snw 1805: Purpose unknown.
1806:
1.1 snw 1807: @node $ZPREVIOUS()
1808: @section $ZPREVIOUS
1809: @cindex $ZPREVIOUS
1810: @cindex intrinsic functions, $ZPREVIOUS
1811: @cindex intrinsic functions, implementation-specific
1812:
1.26 snw 1813: Purpose unknown.
1814:
1.1 snw 1815: @node $ZREPLACE()
1816: @section $ZREPLACE
1817: @cindex $ZREPLACE
1818: @cindex intrinsic functions, $ZREPLACE
1819: @cindex intrinsic functions, implementation-specific
1820:
1821: Replaces all instances of @code{arg2} with @code{arg3} in string @code{arg1}.
1822:
1823: @emph{Syntax}
1824: @code{$ZREPLACE(@emph{arg1},@emph{arg2},@emph{arg3})}
1825:
1826: @emph{Example}
1827:
1828: @code{SET VAR=$ZREPLACE("CAT","C","B") ; => BAT}
1829:
1830: @node $ZSYNTAX()
1831: @section $ZSYNTAX
1832: @cindex $ZSYNTAX
1833: @cindex intrinsic functions, $ZSYNTAX
1834: @cindex intrinsic functions, implementation-specific
1835:
1836: @code{$ZSYNTAX} performs a very basic syntax check on @emph{expr V mcode}. Checks only for illegal commands, mismatched brackets, mismatched quotes, missing or surplus arguments, or surplus commas.
1837:
1838: @emph{Syntax}
1839: @example
1840: $ZSYNTAX(@emph{expr V mcode})
1841: @end example
1842:
1843: If no syntax error is found, returns the empty string.
1844:
1845: If a syntax error is found, returns a number indicating the position in @emph{expr V mcode} at which the error was found, followed by a comma, and the FreeM error code that was found.
1846:
1847: @node $ZTIME()
1848: @section $ZTIME
1849: @cindex $ZTIME
1850: @cindex intrinsic functions, $ZTIME
1851: @cindex intrinsic functions, implementation-specific
1852:
1853: Converts a @code{@ref{$HOROLOG}} string into a human-readable time.
1854:
1855: @emph{Syntax}
1856:
1857: @example
1858: SET VAR=$ZTIME($H[,@emph{<format-string>}])
1859: @end example
1860:
1861: The optional @emph{<format-string>} follows the same rules as the UNIX @code{strftime(3)} function. If @emph{<format-string>} is omitted, the value of @code{^$SYSTEM("ZTIME_FORMAT")} is used (typically @code{%X}).
1862:
1863: @node OBJECT Methods
1864: @chapter OBJECT Methods
1865:
1866: These methods are part of the @code{^%OBJECT} class, from which all FreeM objects ultimately inherit.
1867:
1868: Please note that classes may override @code{^%OBJECT} methods (or methods of any class) in order to provide results more fitting to the class's abstraction goals.
1869:
1870: @menu
1871: * $$TONUMBER:: Returns the canonical numeric representation of the object.
1872: * $$TYPE:: Returns the fully-qualified class name of the object.
1873: * $$VALUE:: Returns the value of the object.
1874: @end menu
1875:
1876: @node $$TONUMBER
1877: @section $$TONUMBER
1878:
1879: Returns (when applicable) a canonical numeric representation of the referenced object.
1880:
1881: @emph{Syntax}
1882:
1883: @example
1884: W $$MYOBJECT.TONUMBER(),!
1885: @end example
1886:
1887: If no canonical numeric representation of the object is possible, will return the empty string.
1888:
1889: @node $$TYPE
1890: @section $$TYPE
1891:
1892: Returns the fully-qualified class of the referenced object.
1893:
1894: @emph{Syntax}
1895:
1896: @example
1897: W $$MYOBJECT.TYPE()
1898: @end example
1899:
1900: Note that M variables that are created by non-object-oriented means will be objects of the @code{^%STRING} class.
1901:
1902: @node $$VALUE
1903: @section $$VALUE
1904:
1905: Returns the value of the referenced object.
1906:
1907: @emph{Syntax}
1908:
1909: @example
1910: W $$MYOBJECT.VALUE()
1911: @end example
1912:
1913: @node STRING Methods
1914: @chapter STRING Methods
1915:
1916: These are methods inherent to the @code{^%STRING} class, which is the default class for M variables created without specifying a class.
1917:
1918: @menu
1919: * $$ASCII:: Return the ASCII code of a character within the string.
1920: * $$DATA:: Return tree characteristics of the string.
1921: * $$DISTANCE:: Determine Levenstein distance between this string and another.
1922: * $$EXTRACT:: Return a substring of the string.
1923: * $$FIND:: Find the position of a substring within the string.
1924: * $$FNUMBER:: Format numbers.
1925: * $$JUSTIFY:: Pad the string to specific positions.
1926: * $$LENGTH:: Return the length of the string.
1927: * $$PIECECOUNT:: Return the count of pieces existing between instances of a delimiter.
1928: * $$PIECE:: Return a delimited subset of the string.
1929: * $$REPLACE:: Replace instances of a substring within the string.
1930: * $$REVERSE:: Reverse the order of characters in the string.
1931: * $$TOLOWER:: Return a lowercase version of the string.
1932: * $$TOUPPER:: Return an uppercase version of the string.
1933: * $$TRANSLATE:: Replace individual characters within the string.
1934: @end menu
1935:
1936: @node $$ASCII
1937: @section $$ASCII
1938:
1939: Returns the ASCII code of a character within the string. See @ref{$ASCII()}.
1940:
1941: @emph{Syntax}
1942:
1943: @example
1944: W $$MYOBJECT.ASCII(3)
1945: @end example
1946:
1947: The above example returns the ASCII code in position 3 of string object @code{MYOBJECT}.
1948:
1949: @node $$DATA
1950: @section $$DATA
1951:
1952: Returns the value of the @code{$DATA} intrinsic function as performed on the value of the object. See @ref{$DATA()}.
1953:
1954: @emph{Syntax}
1955:
1956: @example
1957: W $$MYOBJECT.DATA()
1958: @end example
1959:
1960: @node $$DISTANCE
1961: @section $$DISTANCE
1962:
1963: Returns the Levenstein distance between the string and another string. See @ref{$ZLSD()}.
1964:
1965: @emph{Syntax}
1966:
1967: @example
1968: W $$MYOBJECT.DISTANCE("someString")
1969: @end example
1970:
1971: @node $$EXTRACT
1972: @section $$EXTRACT
1973:
1974: Returns a substring of the string. See @ref{$EXTRACT()}.
1975:
1976: @emph{Syntax}
1977:
1978: @example
1979: $$<objectName>.EXTRACT(<start>,<end>)
1980: @end example
1981:
1982:
1983: @node $$FIND
1984: @section $$FIND
1985:
1.25 snw 1986: Finds the character immediately following the first occurence of a substring within a string.
1987:
1988: The first argument is the substring to be located.
1989:
1990: The second argument is the position within the string at which to begin searching.
1991:
1992: See @ref{$FIND()}.
1993:
1.1 snw 1994: @node $$FNUMBER
1995: @section $$FNUMBER
1996:
1.25 snw 1997: Formats a number according to a set of formatting codes.
1998:
1999: The argument is a series of formatting codes. See @ref{$FNUMBER()} for details.
2000:
1.1 snw 2001: @node $$JUSTIFY
2002: @section $$JUSTIFY
2003:
1.25 snw 2004: Right-justifies a string based on a specified fixed length.
2005:
2006: The first argument is the character length of the output.
2007:
2008: The second argument controls the number of fractional digits to be included in the output, and defaults to the number of digits specified in the first argument.
2009:
2010: See @ref{$JUSTIFY()} for details.
2011:
1.1 snw 2012: @node $$LENGTH
2013: @section $$LENGTH
2014:
1.25 snw 2015: Returns the length of the string.
2016:
1.1 snw 2017: @node $$PIECECOUNT
2018: @section $$PIECECOUNT
2019:
1.25 snw 2020: Returns the number of items in a list delimited by the character specified in the argument.
2021:
1.1 snw 2022: @node $$PIECE
2023: @section $$PIECE
2024:
1.25 snw 2025: @emph{Syntax}
2026:
2027: @code{$PIECE(@emph{d}[,@emph{n}[,@emph{end}]])}
2028:
2029: Accesses the @code{n}th through @code{end} @code{d}-delimited pieces of the string.
2030:
2031: The first argument is the delimiter to be used.
2032:
2033: The optional second argument is the first @code{d}-delimited piece to access, and defaults to @code{1}.
2034:
2035: The optional third argument is the final @code{d}-delimited piece to access, and defaults to the value of the third argument (@code{n}).
2036:
2037:
1.1 snw 2038: @node $$REPLACE
2039: @section $$REPLACE
2040:
1.25 snw 2041: @emph{Syntax}
2042: @code{myString.$$REPLACE(@emph{arg1},@emph{arg2})}
2043:
2044: Replaces all instances of @code{arg2} with @code{arg3} in @code{myString}.
2045:
1.1 snw 2046: @node $$REVERSE
2047: @section $$REVERSE
2048:
1.25 snw 2049: Returns the reverse of the string.
2050:
1.1 snw 2051: @node $$TOLOWER
2052: @section $$TOLOWER
2053:
1.25 snw 2054: Returns an all-lowercase version of the string.
2055:
1.1 snw 2056: @node $$TOUPPER
2057: @section $$TOUPPER
2058:
1.25 snw 2059: Returns an all-uppercase version of the string.
2060:
1.1 snw 2061: @node $$TRANSLATE
2062: @section $$TRANSLATE
2063:
1.25 snw 2064: Identical to @ref{$TRANSLATE()}, except that the arguments are shifted left by one, and the input string is implicit (the object).
2065:
1.1 snw 2066: @node Commands
2067: @chapter Commands
2068: @cindex commands
2069:
2070: @menu
2071: * @@:: Execute the following expression as M code.
2072: * !:: Run an external program or command.
2073: * !!:: Launch a subshell from FreeM direct mode.
2074: * ABLOCK:: Increment the block counter for one or more event classes.
2075: * ASTART:: Enable asynchronous event handling for one or more event classes.
2076: * ASTOP:: Disable asynchronous event handling for one or more event classes.
2077: * AUNBLOCK:: Decrement the block counter for one or more event classes.
2078: * BREAK:: Interrupt a running routine to allow interactive debugging.
2079: * CLOSE:: Close an input/output device.
2080: * DO:: Transfer program control to one or more subroutines or introduces a new execution level.
2081: * ELSE:: Execute the remainder of a line if @code{@ref{$TEST}} evaluates @emph{false}.
2082: * FOR:: Repeat execution of a line or block of code.
2083: * GOTO:: Unconditionally transfer program execution to a supplied @emph{entryref}.
2084: * HALT:: Terminate the current FreeM interpreter instance.
2085: * HANG:: Temporarily suspend the running program.
2086: * IF:: Execute the remainder of a line if a conditional expression evaluates @emph{true}.
2087: * JOB:: Execute an @emph{entryref} in a child process.
2088: * KILL:: Remove data from a local, global, or structured system variable.
2089: * KSUBSCRIPTS:: Kill only the descendant subscripts of a local, global, global, or structured system variable.
2090: * KVALUE:: Kill only the value of a local, global, or structured system variable.
2091: * LOCK:: Control advisory locking for concurrency control.
2092: * MERGE:: Merge contents of one local, global, or structured system variable into another.
2093: * NEW:: Introduce a new scope for a specified local variable or intrinsic special variable or instantiate an object.
2094: * OPEN:: Open a sequential or socket input/output device.
2095: * QUIT:: End execution of the current process level, optionally with return value.
2096: * READ:: Read input from an input/output device.
2097: * SET:: Set the value of a local variable, global, intrinsic special variable, or structured system variable.
2098: * TCOMMIT:: Commit a transaction.
2099: * THEN:: Preserve @code{@ref{$TEST}} until the end of the current line.
2100: * TROLLBACK:: Roll back all pending transactions.
2101: * TSTART:: Introduce a new transaction processing level.
2102: * USE:: Set the currently-active input/output device.
2103: * VIEW:: Modify FreeM internal parameters.
2104: * WRITE:: Write output to current input/output device.
2105: * XECUTE:: Interpret string as M code.
1.46 snw 2106: * ZASSERT:: Raise error when a conditional expression evaluates @emph{false}.
1.48 snw 2107: * ZBREAK:: Enable/disable ZBREAK mode.
1.42 snw 2108: * ZCONST:: Define a constant that cannot be altered after initial definition.
1.59 snw 2109: * ZEDIT:: Edit a routine using an external editor.
1.48 snw 2110: * ZGOTO:: @code{GOTO} with @code{BREAK} control.
1.49 snw 2111: * ZHALT:: Exit FreeM job with return value.
1.1 snw 2112: * ZINSERT:: Insert code into routine buffer.
1.49 snw 2113: * ZJOB:: Invoke job, ignoring any timeouts.
1.1 snw 2114: * ZLOAD:: Load routine into routine buffer.
1.42 snw 2115: * ZMAP:: Map a global name to a non-default namespace.
1.1 snw 2116: * ZNEW:: Unknown.
2117: * ZPRINT:: Print contents of routine buffer.
1.49 snw 2118: * ZQUIT:: Quit multiple stack levels at once.
1.1 snw 2119: * ZREMOVE:: Remove code from routine buffer.
2120: * ZSAVE:: Save routine buffer to disk.
1.42 snw 2121: * ZTHROW:: Programmatically raise an error condition.
1.50 snw 2122: * ZTRAP:: Raise a FreeM error.
1.42 snw 2123: * ZUNMAP:: Remove a mapping of a global to a non-default namespace.
2124: * ZWATCH:: Enable or disable watchpoints, or set or clear watchpoints on specified globals, locals, or structured system variables.
2125: * ZWITH:: Set prefix for future variable references.
1.1 snw 2126: * ZWRITE:: Write local variable, global, or structured system variable to @code{@ref{$IO}}.
2127: @end menu
2128:
2129: @node @@
2130: @section @@
2131: @cindex @@
2132: @cindex commands, @@
2133: @cindex commands, implementation-specific
2134: @cindex commands, non-standard
2135:
2136: Executes FreeM code @emph{expr V mcode}.
2137:
2138: @emph{Syntax}
2139:
2140: @example
2141: @@@emph{expr V mcode}
2142: @end example
2143:
2144: @emph{Example (Using Variable)}
2145:
2146: @example
1.22 snw 2147: DEFAULT.USER> SET FOO="WRITE ""HELLO WORLD"",!"
2148: DEFAULT.USER> @@FOO
1.1 snw 2149:
2150: HELLO WORLD
2151:
1.22 snw 2152: DEFAULT.USER>
1.1 snw 2153: @end example
2154:
2155: @emph{Example (Using String Literal)}
2156:
2157: @example
1.22 snw 2158: DEFAULT.USER> @@"WRITE ""HELLO WORLD"",!"
1.1 snw 2159:
2160: HELLO WORLD
2161:
1.22 snw 2162: DEFAULT.USER>
1.1 snw 2163: @end example
2164:
2165: @emph{Example (Using Indirection)}
2166:
2167: @example
1.22 snw 2168: DEFAULT.USER> SET FOO="BAR"
1.1 snw 2169:
1.22 snw 2170: DEFAULT.USER> SET BAR="WRITE ""HELLO WORLD"",!"
1.1 snw 2171:
1.22 snw 2172: DEFAULT.USER> @@@@FOO
1.1 snw 2173:
2174: HELLO WORLD
2175:
1.22 snw 2176: DEFAULT.USER>
1.1 snw 2177: @end example
2178:
2179:
2180: @node !
2181: @section !
2182: @cindex !
2183: @cindex commands, !
2184: @cindex commands, external
2185: @cindex commands, non-standard
2186: @emph{FreeM Extension}
2187:
2188: Invokes a shell to run @emph{<external-command>} 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}.
2189:
2190: If the @command{<} character is supplied immediately preceding @emph{<external-command>}, FreeM will append the contents of M local variable @code{%} to @emph{<external-command>} as standard input.
2191:
2192: If the @command{>} character is supplied immediately preceding @emph{<external-command>}, FreeM will take the standard output stream of @emph{<external-command>} and store it in M local variable @code{%}.
2193:
2194: @code{%} contains the number of lines in the input or output. @code{%(1)..%(@emph{n})} contains the data for lines 1-@emph{n}.
2195:
2196: @node !!
2197: @section !!
2198: @cindex !!
2199: @cindex commands, !!
2200: @cindex commands, external
2201: @cindex commands, non-standard
2202: @emph{FreeM Extension}
2203:
2204: Launches a subshell within the FreeM direct mode, allowing the user to run operating system commands.
2205:
2206: @example
1.22 snw 2207: DEFAULT.USER> !!
1.1 snw 2208:
2209: Type Ctrl-D to exit from the shell
2210: $ uname -a
2211: Linux hesperos 4.19.0-17-amd64 #1 SMP Debian 4.19.194-3 (2021-07-18) x86_64 GNU/Linux
2212: $ exit
2213:
1.22 snw 2214: DEFAULT.USER>
1.1 snw 2215: @end example
2216:
2217:
2218: @node ABLOCK
2219: @section ABLOCK
2220: @cindex ABLOCK
2221: @cindex commands, ABLOCK
2222:
2223: 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).
2224:
2225: 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.
2226:
2227: @emph{Syntax}
2228:
2229: @example
2230: ABLOCK@emph{:postcondition}
2231: @end example
2232:
2233: 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.
2234:
2235: @example
2236: ABLOCK@emph{:postcondition} @emph{evclass1}...,@emph{evclassN}
2237: @end example
2238:
2239: 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.
2240:
2241: @example
2242: ABLOCK@emph{:postcondition} (@emph{evclass1}...,@emph{evclassN}
2243: @end example
2244:
2245: 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.
2246:
2247:
2248: @node ASTART
2249: @section ASTART
2250: @cindex ASTART
2251: @cindex commands, ASTART
2252:
2253: Enables asynchronous event handling for one or more event classes.
2254:
2255: @emph{Syntax}
2256:
2257: @example
2258: ASTART@emph{:postcondition}
2259: @end example
2260:
2261: 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.
2262:
2263: @example
2264: ASTART@emph{:postcondition} @emph{evclass1}...,@emph{evclassN}
2265: @end example
2266:
2267: 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.
2268:
2269: @example
2270: ASTART@emph{:postcondition} (@emph{evclass1}...,@emph{evclassN})
2271: @end example
2272:
2273: 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.
2274:
2275: @node ASTOP
2276: @section ASTOP
2277: @cindex ASTOP
2278: @cindex commands, ASTOP
2279:
2280: Disables asynchronous event handling for one or more event classes.
2281:
2282: @emph{Syntax}
2283:
2284: @example
2285: ASTOP@emph{:postcondition}
2286: @end example
2287:
2288: 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.
2289:
2290: @example
2291: ASTOP@emph{:postcondition} @emph{evclass1}...,@emph{evclassN}
2292: @end example
2293:
2294: 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.
2295:
2296: @example
2297: ASTOP@emph{:postcondition} (@emph{evclass1}...,@emph{evclassN})
2298: @end example
2299:
2300: 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.
2301:
2302: @node AUNBLOCK
2303: @section AUNBLOCK
2304: @cindex AUNBLOCK
2305: @cindex commands, AUNBLOCK
2306:
2307: Decrements the event block counter for one or more event classes.
2308:
2309: @emph{Syntax}
2310:
2311: @example
2312: AUNBLOCK@emph{:postcondition}
2313: @end example
2314:
2315: 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.
2316:
2317: @example
2318: AUNBLOCK@emph{:postcondition} @emph{evclass1}...,@emph{evclassN}
2319: @end example
2320:
2321: 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.
2322:
2323: @example
2324: AUNBLOCK@emph{:postcondition} (@emph{evclass1}...,@emph{evclassN}
2325: @end example
2326:
2327: 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.
2328:
2329:
2330: @node BREAK
2331: @section BREAK
2332: @cindex BREAK
2333: @cindex commands, BREAK
2334:
2335: Interrupts running routine to allow interactive debugging.
2336:
2337: @emph{Syntax}
2338:
2339: @example
2340: @code{BREAK@emph{:postcondition}}
2341: @end example
2342:
2343: In its argumentless form, @code{BREAK} suspends execution of running code, provided the optional @emph{postcondition} is @emph{true} or omitted.
2344:
2345: @example
2346: @code{BREAK@emph{:postcondition} @emph{breakflag}}
2347: @end example
2348:
2349: @emph{FreeM Extension}
2350:
1.35 snw 2351: In its single-argument form, @code{BREAK} enters the interactive debugger or sets @emph{Ctrl-C} handling and error handling characteristics, provided the optional @emph{postcondition} is @emph{true} or omitted.
1.1 snw 2352: The following table enumerates the possible values of @emph{breakflag}
2353:
2354: @table @code
1.35 snw 2355: @item "DEBUG"
2356: Enters the interactive debugger
1.1 snw 2357: @item 0
2358: Disables @emph{Ctrl-C} handling
2359: @item -2
2360: Enables normal FreeM error handling
2361: @item 2
2362: Enables @emph{Digital Standard MUMPS} v2 error handling
2363: @item @emph{any integer value other than 0, 2, or -2}
2364: Enables @emph{Ctrl-C} handling
2365: @end table
2366:
2367: @node CLOSE
2368: @section CLOSE
2369: @cindex CLOSE
2370: @cindex commands, CLOSE
2371:
2372: Closes an input/output device.
2373:
2374: @emph{Syntax}
2375:
2376: @example
2377: @code{CLOSE@emph{:postcondition}}
2378: @end example
2379:
2380: 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.
2381:
2382: @example
2383: @code{CLOSE@emph{:postcondition} @emph{channel}}
2384: @end example
2385:
2386: 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.
2387:
2388: @node DO
2389: @section DO
2390: @cindex DO
2391: @cindex commands, DO
2392:
2393: In its inclusive form, transfers program control to one or more specified subroutines, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. Line levels of entryrefs specified in the argument list must be one, or error @code{M14} is raised.
2394:
2395: @emph{Syntax}
2396:
2397: @example
2398: DO[@emph{:postcondition}] @emph{entryref}[@emph{:postcondition}[,...]]
2399: @end example
2400:
1.35 snw 2401: @cartouche
2402: @quotation
2403: @emph{Non-Standard Behavior}
2404:
2405: FreeM allows @code{DO} @emph{entryref}s to follow the format of @code{+@emph{intexpr}}. In this case, the value of @emph{intexpr} will be interpreted as an offset from the first line of the current routine.
2406: @end quotation
2407: @end cartouche
2408:
1.1 snw 2409: In its argumentless form, transfers control to the following block of code where the line level is one greater than the level at which @code{DO} was encountered, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2410:
2411: @emph{Syntax}
2412:
2413: @example
2414: DO[@emph{:postcondition}]
2415: @end example
2416:
2417: @node ELSE
2418: @section ELSE
2419: @cindex ELSE
2420: @cindex commands, ELSE
2421:
2422: Executes the remainder of the line of code on which @code{ELSE} is encountered only if @code{$TEST} evaluates to @emph{false}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2423:
2424: @emph{Syntax}
2425:
2426: @example
2427: ELSE[@emph{:postcondition}]
2428: @end example
2429:
2430: @cartouche
2431: @quotation
2432: @emph{Non-Standard Behavior}
2433:
1.39 snw 2434: FreeM allows a @emph{postcondition} on @code{ELSE}. While explicitly forbidden in the @emph{Standard}, it was decided that FreeM should allow postconditions everywhere, both for the sake of foolish consistency (the likes of which Emerson warned against), and for the benefit of entrants to a hypothetical future obfuscated M contest, and those with a Machiavellian predisposition to wicked perversions and undue cleverness.
1.1 snw 2435:
1.35 snw 2436: Using postconditions on @code{ELSE} should be strictly avoided in production code, as they have no practical use, and may contribute to technical debt, hardening of the arteries, hobgoblins, a small mind, a surfeit of logic, climate change, @emph{Daily WTF} rants, or the meltdown of global financial markets.
1.1 snw 2437: @end quotation
2438: @end cartouche
2439:
2440: @node FOR
2441: @section FOR
2442: @cindex FOR
2443: @cindex commands, FOR
2444:
2445: In its argumentless form, repeatedly executes the remainder of the line on which @code{FOR} was encountered until a @code{QUIT}, @code{GOTO}, or end-of-line is encountered, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2446:
2447: @emph{Syntax}
2448:
2449: @example
2450: FOR[@emph{:postcondition}]
2451: @end example
2452:
2453: @cartouche
2454: @quotation
2455: @emph{Non-Standard Behavior}
2456:
2457: When @code{$DIALECT} is set to @code{FREEM}, FreeM allows a @emph{postcondition} on @code{FOR}. Much like postconditions on @code{ELSE} and @code{IF}, this is explicitly forbidden in the @emph{standard}. The expression contained in the @emph{postcondition} is evaluated on each iteration of the @code{FOR} loop, and if it does not evaluate @emph{true}, the loop will be immediately exited. The effect is roughly similar to @code{WHILE} constructs present in other languages, but absent from standard M.
2458:
2459: As with all non-standard features of FreeM, please exercise caution when using this feature, especially in code that is expected to run in other, less preternaturally-inclined M implementations.
2460: @end quotation
2461: @end cartouche
2462:
2463: In its sentinel form, repeatedly executes the remainder of the line and sets a sentinel variable on each iteration, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2464:
2465: On the first iteration of the loop, @emph{glvn} will be set to @emph{initalizer-expression}. On each subsequent iteration, @emph{glvn} will be incremented by @emph{increment-expression}, and the loop will terminate when @emph{glvn} meets or exceeds the value of @emph{max-expression}.
2466:
2467: @emph{Syntax}
2468:
2469: @example
2470: FOR[@emph{:postcondition}] @emph{glvn}=@emph{initializer-expression}:@emph{increment-expression}:@emph{max-expression}
2471: @end example
2472:
2473: @emph{Example}
2474:
2475: @example
1.22 snw 2476: DEFAULT.USER> FOR I=1:1:10 WRITE I,!
1.1 snw 2477:
2478: 1
2479: 2
2480: 3
2481: 4
2482: 5
2483: 6
2484: 7
2485: 8
2486: 9
2487: 10
2488:
1.22 snw 2489: DEFAULT.USER> FOR I=2:2:10 WRITE I,!
1.1 snw 2490:
2491: 2
2492: 4
2493: 6
2494: 8
2495: 10
2496: @end example
2497:
2498: In its explicit parameter form, a variable is set to each of a series of explicit values, once per iteration, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. The loop terminates when no more values are available.
2499:
2500: @emph{Syntax}
2501:
2502: @example
2503: FOR[@emph{:postcondition}] @emph{glvn}=@emph{expr1}[,..@emph{exprN}]
2504: @end example
2505:
2506: @emph{Example}
2507:
2508: @example
1.22 snw 2509: DEFAULT.USER> FOR I=60,"FOO",-3,"George",1450,$HOROLOG WRITE I,!
1.1 snw 2510:
2511: 60
2512: FOO
2513: -3
2514: George
2515: 1450
2516: 66106,52388
2517: @end example
2518:
2519: @node GOTO
2520: @section GOTO
2521: @cindex GOTO
2522: @cindex commands, GOTO
2523:
2524: Transfers program execution to another line of code, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. Attempting to @code{GOTO} a different line level or a different block when the line level of @code{GOTO} is greater than one will raise error @code{M45}.
2525:
2526: @emph{Syntax}
2527:
2528: @example
2529: GOTO[@emph{:postcondition}] @emph{entryref}
2530: @end example
2531:
1.35 snw 2532: @cartouche
2533: @quotation
2534: @emph{Non-Standard Behavior}
2535:
2536: FreeM allows @code{GOTO} @emph{entryref}s to follow the format of @code{+@emph{intexpr}}. In this case, the value of @emph{intexpr} will be interpreted as an offset from the first line of the current routine.
2537: @end quotation
2538: @end cartouche
2539:
2540:
1.1 snw 2541: @node HALT
2542: @section HALT
2543: @cindex HALT
2544: @cindex commands, HALT
2545:
2546: Halts program execution and frees resources allocated during execution, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2547:
2548: @emph{Syntax}
2549:
2550: @example
2551: HALT[@emph{:postcondition}]
2552: @end example
2553:
2554: @node HANG
2555: @section HANG
2556: @cindex HANG
2557: @cindex commands, HANG
2558:
2559: Temporarily suspends the program for @emph{expr} seconds, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. Values of @emph{expr} that are zero or less than zero are ignored.
2560:
2561: @emph{Syntax}
2562:
2563: @example
2564: HANG[@emph{:postcondition}] @emph{expr}
2565: @end example
2566:
2567: @cartouche
2568: @quotation
2569: @emph{Non-Standard Behavior}
2570:
2571: FreeM supports sub-second values for @emph{expr}.
2572: @end quotation
2573: @end cartouche
2574:
2575: @node IF
2576: @section IF
2577: @cindex IF
2578: @cindex commands, IF
2579:
2580: In its argumented form, allows the remainder of the line of code following @code{IF} to execute only if all @emph{tvexpr}s evaluate to @emph{true}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2581:
2582: @emph{Syntax}
2583: @example
2584: IF[@emph{:postcondition}] @emph{tvexpr}[,...@emph{tvexpr}]
2585: @end example
2586:
2587: In its argumentless form, allows the remainder of the line of code following @code{IF} to execute only if @code{$TEST} evaluates to @emph{1}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2588:
1.39 snw 2589:
1.1 snw 2590: @emph{Syntax}
2591: @example
1.39 snw 2592: IF[@emph{:postcondition}] @emph{command...}
1.1 snw 2593: @end example
2594:
1.39 snw 2595: @cartouche
2596: @quotation
2597: @emph{Style Recommendation}
2598:
2599: In the interest of readability and maintainability, we recommend avoiding the argumentless form of @code{IF} in new code. It is an obsolete relic of an era when routine sizes were severely limited, and can be difficult to spot, as the use of whitespace (@code{IF @emph{command}}) makes the intent of its use non-obvious at a glance. It is also far too easy to inadvertently delete the extra space, leading to program errors easily avoided otherwise.
2600:
2601: We recommend explicitly checking the value of @code{$TEST} instead, as in @code{IF $TEST @emph{command}} or @code{@emph{command}:$TEST ...}, as this makes the intent immediately clear both to M newcomers and seasoned experts, and sacrifices nothing of value, even on the oldest computer systems where FreeM can be used today.
2602: @end quotation
2603: @end cartouche
2604:
1.1 snw 2605: @node JOB
2606: @section JOB
2607: @cindex JOB
2608: @cindex commands, JOB
2609:
2610: Executes @emph{entryref} in a separate process, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2611:
2612: @emph{Syntax}
2613: @example
2614: JOB[@emph{:postcondition}] @emph{entryref}[:@emph{job-parameters}[:@emph{timeout}]]
2615: @end example
2616:
2617: If @emph{timeout} is supplied, FreeM will set @code{$TEST} to @emph{1} if the child process completes within @emph{timeout} seconds.
2618:
2619: @node KILL
2620: @section KILL
2621: @cindex KILL
2622: @cindex commands, KILL
2623:
2624: In its inclusive form, @code{KILL} deletes the specified @emph{glvn}s and their descendant subscripts, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2625:
2626: @emph{Syntax}
2627: @example
2628: KILL[@emph{:postcondition}] @emph{glvn}[,...@emph{glvn}]
2629: @end example
2630:
2631: In its exclusive form, @code{KILL} deletes all local variables @emph{except} for those specified by @emph{lvn}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2632:
2633: @emph{Syntax}
2634: @example
2635: KILL[@emph{:postcondition}] (@emph{lvn}[,...@emph{lvn}])
2636: @end example
2637:
2638: In its argumentless form, @code{KILL} deletes all local variables, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2639:
2640: @emph{Syntax}
2641: @example
2642: KILL[@emph{:postcondition}]
2643: @end example
2644:
2645: @node KSUBSCRIPTS
2646: @section KSUBSCRIPTS
2647: @cindex KSUBSCRIPTS
2648: @cindex commands, KSUBSCRIPTS
2649:
2650: Kills only the descendant subscripts (but not the data value) of a referenced global, local, or SSVN (where allowed).
2651:
2652: @emph{Syntax}
2653:
2654: @example
2655: KSUBSCRIPTS@emph{:postcondition} @emph{var1},...
2656: @end example
2657:
2658: In the above @emph{inclusive} form, @code{KVALUE} will kill the descendant subscripts at each local, global, or SSVN node specified in the list (provided that the optional @emph{postcondition} is @emph{true} or omitted), but will leave the data value intact.
2659:
2660: @cartouche
2661: @quotation
2662: @emph{Note}
1.62 snw 2663: The below @emph{argumentless} and @emph{exclusive} forms of @code{KSUBSCRIPTS} are not implemented in FreeM, as of version 0.65.1-rc1, but are planned for a future release.
1.1 snw 2664: @end quotation
2665: @end cartouche
2666:
2667: @example
2668: KSUBSCRIPTS@emph{:postcondition}
2669: @end example
2670:
2671: 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.
2672:
2673: @example
2674: KSUBSCRIPTS@emph{:postcondition} (@emph{var1},...)
2675: @end example
2676:
2677: 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.
2678:
2679:
2680: @node KVALUE
2681: @section KVALUE
2682: @cindex KVALUE
2683: @cindex commands, KVALUE
2684:
2685: Kills only the data value (but not descendant subscripts) of a referenced global, local, or SSVN (where allowed).
2686:
2687: @emph{Syntax}
2688:
2689: @example
2690: KVALUE@emph{:postcondition} @emph{var1},...
2691: @end example
2692:
2693: In the above @emph{inclusive} form, @code{KVALUE} will kill the data values at each local, global, or SSVN node specified in the list (provided that the optional @emph{postcondition} is @emph{true} or omitted), but will leave descendant subscripts intact.
2694:
2695: @cartouche
2696: @quotation
2697: @emph{Note}
1.62 snw 2698: The below @emph{argumentless} and @emph{exclusive} forms of @code{KVALUE} are not implemented in FreeM, as of version 0.65.1-rc1, but are planned for a future release.
1.1 snw 2699: @end quotation
2700: @end cartouche
2701:
2702: @example
2703: KVALUE@emph{:postcondition}
2704: @end example
2705:
2706: 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.
2707:
2708: @example
2709: KVALUE@emph{:postcondition} (@emph{var1},...)
2710: @end example
2711:
2712: 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.
2713:
2714: @node LOCK
2715: @section LOCK
2716: @cindex LOCK
2717: @cindex commands, LOCK
2718:
2719: Acquires or releases ownership of names.
2720:
2721: In its argumentless form, @code{LOCK} releases ownership of all names previously locked by the current process, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2722:
2723: @emph{Syntax}
2724: @example
2725: LOCK[@emph{:postcondition}]
2726: @end example
2727:
2728: In its incremental form, increments or decrements the lock counter for each specified @emph{name}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. Ownership of each @emph{name} is considered to be the current process as long as the lock counter for @emph{name} is greater than zero. If @emph{timeout} is specified, FreeM will wait no more than @emph{timeout} seconds in attempting to acquire ownership of @emph{name}.
2729:
2730: If @code{LOCK} succeeds within @emph{timeout}, @code{$TEST} is set to @emph{1}. Otherwise, @code{$TEST} is set to @emph{0}.
2731:
2732: @emph{Syntax}
2733: @example
2734: LOCK[@emph{:postcondition}] [+|-]@emph{name}[:@emph{timeout}][,...[+|-]@emph{name}[:@emph{timeout}]]
2735: @end example
2736:
2737: @emph{Example}
2738:
1.26 snw 2739: This example will increment the lock counter for @code{^SNW} and decrement the lock counter for @code{^MJR}.
1.1 snw 2740:
2741: @example
1.26 snw 2742: LOCK +^SNW,-^MJR
1.1 snw 2743: @end example
2744:
2745: In its non-incremental form, @code{LOCK} releases all @code{LOCK}s held by the current process, and then attempts to acquire a lock on each @emph{name}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. If @emph{timeout} is supplied, FreeM will attempt to lock @emph{name} for no more than @emph{timeout} seconds.
2746:
2747: If @code{LOCK} succeeds within @emph{timeout}, @code{$TEST} is set to @emph{1}. Otherwise, @code{$TEST} is set to @emph{0}.
2748:
2749: @emph{Syntax}
2750: @example
2751: LOCK[@emph{:postcondition}] @emph{name}[:@emph{timeout}][,...@emph{name}[:@emph{timeout}]]
2752: @end example
2753:
2754: @node MERGE
2755: @section MERGE
2756: @cindex MERGE
2757: @cindex commands, MERGE
2758:
2759: Merges the contents of one global, local, or SSVN subtree to another global, local, or SSVN.
2760:
2761: @emph{Syntax}
2762:
2763: @example
2764: @code{MERGE A=^$JOB}
2765: @end example
2766:
2767: The above example will merge the @code{^$JOB} SSVN 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.
2768:
2769: @node NEW
2770: @section NEW
2771: @cindex NEW
2772: @cindex commands, NEW
2773:
2774: In all forms of @code{NEW}, @emph{name} must be a local variable name or @code{NEW}-able structured or intrinsic system variable.
2775:
2776: In its inclusive form, @code{NEW} saves each specified @emph{name} on the process stack and removes it, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. When the current stack frame is exited, the previous values are restored.
2777:
2778: @emph{Syntax}
2779:
2780: @example
2781: NEW[@emph{:postcondition}] @emph{name}[,...@emph{name}]
2782: @end example
2783:
2784: In its exclusive form, @code{NEW} saves all local variables @emph{except} those named (each @emph{name}) and removes them, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. When the current stack frame is exited, the previous values are restored.
2785:
2786: @emph{Syntax}
2787: @example
2788: NEW[@emph{:postcondition}] (@emph{name}[,...@emph{name}])
2789: @end example
2790:
2791: In its argumentless form, @code{NEW} saves all local variables and removes them, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. When the current stack frame is exited, the previous values are restored.
2792:
2793: @emph{Syntax}
2794: @example
2795: NEW@emph{:postcondition} @emph{name}=@emph{expr}
2796: @end example
2797:
2798: In its initializing form, @code{NEW} stacks variable @emph{name} and sets its value to @emph{expr}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. When the current stack frame is exited, the previous value is restored.
2799:
1.26 snw 2800: @emph{Syntax}
2801: @example
2802: NEW@emph{:postcondition} @emph{name}=$%@emph{^CLASS}(@emph{initializer-list})
2803: @end example
2804:
2805: In its object-oriented form, @code{NEW} creates an instance of class @emph{^CLASS} in local variable @emph{name} and calls the constructor of @emph{^CLASS}, passing @emph{initializer-list} as its argument(s).
2806:
1.1 snw 2807: @node OPEN
2808: @section OPEN
2809: @cindex OPEN
2810: @cindex commands, OPEN
2811:
2812: Opens sequential or socket I/O devices and files and associates them with a numeric FreeM input/output channel.
2813:
2814: @emph{Syntax (Sequential Files)}
2815:
2816: @example
2817: @code{OPEN@emph{:postcondition} @emph{channel}:"@emph{filename}/@emph{access-mode}"}
2818: @end example
2819:
2820: 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.
2821: The below table lists the valid options for @emph{access-mode}:
2822:
2823: @table @code
2824: @item r
2825: Read-only access
2826: @item w
2827: Create a new file for write access
2828: @item a
2829: Write access; append to existing file
2830: @item r+
2831: Read/write access
2832: @end table
2833:
2834: @cartouche
2835: @quotation
2836: @emph{I/O Path}
2837:
2838: 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
2839: access files in other directories, you must first set the @emph{I/O Path} in @code{^$JOB($JOB,"IOPATH")}.
2840:
2841: The following example will set the I/O path to @code{/etc}:
2842:
2843: @example
2844: @code{SET ^$JOB($JOB,"IOPATH")="/etc"}
2845: @end example
2846:
2847: @end quotation
2848: @end cartouche
2849:
2850: 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}.
2851:
2852: @emph{Syntax (Network Sockets)}
2853:
2854: 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.
2855:
2856: @example
2857: OPEN@emph{:postcondition} @emph{socket-channel}:"@emph{hostname-or-address}:@emph{port}:@emph{address-family}:@emph{connection-type}"
2858: @end example
2859:
2860: @emph{Socket Parameters}
2861:
2862: @table @emph
2863:
2864: @item socket-channel
2865: The socket I/O channel to use. This must be in the range of 100-255.
2866:
2867: @item hostname-or-address
2868: 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.
2869:
2870: @item port
2871: The TCP or UDP port to which the socket will connect on the remote host.
2872:
2873: @item address-family
2874: The address family to use. Either @emph{IPV4} or @emph{IPV6}.
2875:
2876: @item connection-type
2877: Which connection type to use. Either @emph{TCP} or @emph{UDP}.
2878:
2879: @end table
2880:
2881: If you do not specify the address family and connection type, they will default to @emph{IPV4} and @emph{TCP}, respectively.
2882:
2883: @node QUIT
2884: @section QUIT
2885: @cindex QUIT
2886: @cindex commands, QUIT
2887:
2888: @code{QUIT} will end execution of the current process level, optionally returning @emph{expr}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2889:
2890: @code{QUIT} with @emph{expr} when an argument is not expected will raise error @code{M16}; @code{QUIT} without @emph{expr} when an argument is expected will raise error @code{M17}.
2891:
2892: Argumentless @code{QUIT} may also be used to exit a @code{FOR} loop occurring on the same line.
2893:
2894: @emph{Syntax}
2895: @example
2896: QUIT[@emph{:postcondition}] [@emph{expr}]
2897: @end example
2898:
2899: @node READ
2900: @section READ
2901: @cindex READ
2902: @cindex commands, READ
2903:
2904: The @code{READ} command takes input from I/O channel @code{$IO} and stores it into specified variables, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2905:
2906: @emph{Syntax}
2907: @example
2908: READ[@emph{:postcondition}] @emph{read-argument}[,...@emph{read-argument}]
2909: @end example
2910:
2911: Each @emph{read-argument} may be one of the following:
2912:
2913: @table @asis
2914:
2915: @item String Literal
2916: String literal @emph{read-argument}s will be output to @code{$IO} unmodified.
2917:
2918: @item Format Specifier
2919: One or more of the following:
2920:
2921: @table @asis
2922: @item @code{!} (newline)
2923: Advances the cursor down by one line and returns it to the first column.
2924:
2925: @item @code{#} (form-feed)
2926: Advances the screen down by @code{$ZROWS} and moves the cursor to the upper-left corner of the screen.
2927:
2928: @item @code{?@emph{n}} (position)
2929: Advances the cursor and @code{$X} forward to position @emph{n}.
2930:
2931: @end table
2932:
2933: @item Single-Character Read (@code{*@emph{variable-name}[@emph{:timeout}]})
2934: Reads one character into variable @emph{variable-name}. If the optional @emph{timeout} is specified, will wait @emph{timeout} seconds to retrieve one character. If a character is read within @emph{timeout} seconds, @code{$TEST} will be set to @emph{1}. If no character is read within @emph{timeout} seconds, @code{$TEST} will be set to @emph{0}.
2935:
2936: @item Variable-Length Character Read (@code{@emph{variable-name}[@emph{:timeout}]})
2937: Reads characters into @emph{variable-name} until the character or character pair in @code{^$DEVICE(@emph{io-channel},"OPTIONS","TERMINATOR")} is encountered. If the optional @emph{timeout} is specified, will wait @emph{timeout} seconds to retrieve characters. If characters are read within @emph{timeout} seconds, @code{$TEST} will be set to @emph{1}. If no character is read within @emph{timeout} seconds, @code{$TEST} will be set to @emph{0}.
2938:
2939: @item Fixed-Length Character Read (@code{@emph{variable-name}#@emph{count}[@emph{:timeout}]})
2940: Reads @emph{count} characters into @emph{variable-name}. If the optional @emph{timeout} is specified, will wait @emph{timeout} seconds to retrieve characters. If characters are read within @emph{timeout} seconds, @code{$TEST} will be set to @emph{1}. If no character is read within @emph{timeout} seconds, @code{$TEST} will be set to @emph{0}.
2941:
2942: @item Control Mnemonic (@code{/@emph{control-mnemonic}[@emph{(arg1[,...argN])}]})
2943: Outputs X3.64 control mnemonic @emph{control-mnemonic} to @code{$IO}. Please see the appendix on X3.64 Control Mnemonics for more information.
2944:
2945: @end table
2946:
2947: @node SET
2948: @section SET
2949: @cindex SET
2950: @cindex commands, SET
2951:
2952: The @code{SET} command places values into one or more variables, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2953:
2954: @emph{Syntax}
2955: @example
2956: SET[@emph{:postcondition}] @emph{set-argument}[=@emph{expression} | @emph{postfix-operator}][@emph{,...set-argument}[=@emph{expression} | @emph{postfix-operator}]]
2957: @end example
2958:
2959: Each @emph{set-argument} can be:
2960:
2961: @table @asis
2962: @item @emph{variable-name}
2963: A local variable, global variable, writable intrinsic special variable, or writable structured system variable.
2964:
2965: @item @emph{lhs-function}
2966: @code{$EXTRACT} or @code{$PIECE}.
2967: @end table
2968:
2969: If any grouping of @emph{set-argument}s is surrounded by parentheses, all @emph{set-argument}s in the parenthesized group will be set to the result of @emph{expression}.
2970:
2971: If @emph{postfix-operator} is used instead of @code{=@emph{expression}}, the results of applying @emph{postfix-operator} to the @emph{set-argument} will be stored in @emph{set-argument}. @emph{postfix-operator} may not be used following a parenthesized group of @emph{set-argument}s.
2972:
2973: @emph{Example (postfix-operator)}
2974:
2975: @example
2976: SET A++,B-- ; increments A, decrements B
2977: @end example
2978:
2979: @node TCOMMIT
2980: @section TCOMMIT
2981: @cindex TCOMMIT
2982: @cindex commands, TCOMMIT
2983:
2984: Commits all pending transactions to the data files, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
2985:
2986: @emph{Syntax}
2987: @example
2988: TCOMMIT[@emph{:postcondition}]
2989: @end example
2990:
2991: @node THEN
2992: @section THEN
2993: @cindex THEN
2994: @cindex commands, THEN
2995:
2996: Saves the value of @code{$TEST} until the end of the current line, restoring it at the end of the current line or when a @code{QUIT} is encountered. @code{THEN} should be used in all new code in conjunction with @code{IF}.
2997:
2998: @emph{Example}
2999: @example
3000: IF 1 THEN WRITE "HELLO!",!
3001: @end example
3002:
3003: @node TROLLBACK
3004: @section TROLLBACK
3005: @cindex TROLLBACK
3006: @cindex commands, TROLLBACK
3007:
3008: Rolls back all pending transactions for the current process, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
3009:
3010: @emph{Syntax}
3011:
3012: @example
3013: TROLLBACK[@emph{:postcondition}]
3014: @end example
3015:
3016: @node TSTART
3017: @section TSTART
3018: @cindex TSTART
3019: @cindex commands, TSTART
3020:
3021: Introduces a new transaction level, incrementing @code{$TLEVEL}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted. Any global data file operations encountered when @code{$TLEVEL} is greater than zero will not be committed to the global data files until @code{TCOMMIT} is encountered.
3022:
3023: If a transaction is restartable, variables in the @emph{variables-list} will be restored to their original values on a restart of the transaction.
3024:
3025: @emph{Syntax}
3026:
3027: @example
3028: TSTART[@emph{:postcondition}] @emph{<variables-list>}:@emph{<transaction-parameters>}
3029: @end example
3030:
3031: @emph{<variables-list>} can be:
3032:
3033: @table @asis
3034:
3035: @item @code{()}
3036: Do not save off any local variables. Makes the transaction non-restartable.
3037:
3038: @item @code{*}
3039: Save off all local variables. Makes the transaction restartable.
3040:
3041: @item @code{@emph{variableName}}
3042: Saves off only one local variable, @emph{variableName}. Makes the transaction restartable.
3043:
3044: @item @code{(@emph{variableName1},...,@emph{variableNameN})}
3045: Saves off all local variables listed. Makes the transaction restartable.
3046:
3047: @end table
3048:
3049: @emph{<transaction-parameters>} can be:
3050:
3051: @table @asis
3052:
3053: @item @code{S[ERIAL]}
3054: Forces ACID properties on the transaction. When @code{SERIAL} is not selected, transactions occur in batch mode, and no attempt is made to guarantee ACID properties.
3055:
3056: @item @code{T[RANSACTIONID]=@emph{transaction-id}}
3057: Sets the ID of the transaction to @emph{transaction-id}
3058:
3059: @end table
3060:
3061: If you are using more than one transaction parameter, surround all of them in parentheses and separate them with commas, e.g.:
3062:
3063: @example
3064: TSTART (FOO,BAR):(SERIAL,TRANSACTIONID="FOO")
3065: @end example
3066:
3067:
3068: @node USE
3069: @section USE
3070: @cindex USE
3071: @cindex commands, USE
3072:
3073: 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.
3074:
3075: @emph{Syntax (Terminal)}
3076:
3077: @example
3078: 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})]
3079: @end example
3080:
3081: For terminals, @emph{io-channel} must be 0.
3082:
3083: Semantic and functional description of each device parameter TBA.
3084:
3085: @emph{Syntax (Sequential Files)}
3086:
3087: @example
3088: USE@emph{:postcondition} @emph{io-channel}[:@emph{seek-position}:@emph{terminator}:@emph{nodelay})]
3089: @end example
3090:
3091: For sequential files, @emph{io-channel} must be in the range 1-99.
3092:
3093: Semantic and functional description of each device parameter TBA.
3094:
3095: @emph{Syntax (Network Sockets)}
3096:
3097: @example
3098: USE@emph{:postcondition} @emph{io-channel}
3099: @end example
3100:
3101: 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.
3102:
3103: @example
3104: USE@emph{:postcondition} @emph{io-channel}:/CONNECT
3105: @end example
3106:
3107: 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).
3108:
3109: For network sockets, @emph{io-channel} must be in the range 100-255.
3110:
3111: @node VIEW
3112: @section VIEW
3113: @cindex VIEW
3114: @cindex commands, VIEW
3115:
3116: Provides write access to various FreeM internal parameters, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
3117:
3118: @emph{Syntax}
3119: @example
3120: VIEW[@emph{:postcondition}] @emph{view-number}[:@emph{view-argument}[:@emph{view-argument}...]]
3121: @end example
3122:
3123: The @emph{view-number} argument can be one of the following:
3124:
3125: @table @asis
3126:
3127: @item @code{21} - Close All Globals
3128: Closes all global data files open in the current process. Takes no arguments.
3129:
3130: @emph{Syntax}
3131: @example
3132: VIEW 21
3133: @end example
3134:
3135: @item @code{52} - Set G0 Input Translation Table for @code{$IO}
3136:
3137: @emph{Syntax}
3138: @example
3139: VIEW 52:@emph{expr V trantab}
3140: @end example
3141:
3142: @item @code{53} - Set G0 Output Translation Table for @code{$IO}
3143:
3144: @emph{Syntax}
3145: @example
3146: VIEW 53:@emph{expr V trantab}
3147: @end example
3148:
3149: @item @code{54} - Set G1 Input Translation Table for @code{$IO}
3150:
3151: @emph{Syntax}
3152: @example
3153: VIEW 54:@emph{expr V trantab}
3154: @end example
3155:
3156: @item @code{55} - Set G1 Output Translation Table for @code{$IO}
3157:
3158: @emph{Syntax}
3159: @example
3160: VIEW 55:@emph{expr V trantab}
3161: @end example
3162:
3163: @item @code{62} - Set @code{$RANDOM} Seed Number
3164: Sets the seed number used by @code{$RANDOM} to @emph{numexpr}.
3165:
3166: @emph{Syntax}
3167: @example
3168: VIEW 62:@emph{numexpr}
3169: @end example
3170:
3171: @item @code{63} - Set @code{$RANDOM} Parameter A
3172: Sets the number used for @code{$RANDOM} Parameter A to @emph{numexpr}.
3173:
3174: @emph{Syntax}
3175: @example
3176: VIEW 63:@emph{numexpr}
3177: @end example
3178:
3179: @item @code{64} - Set @code{$RANDOM} Parameter B
3180: Sets the number used for @code{$RANDOM} Parameter B to @emph{numexpr}.
3181:
3182: @emph{Syntax}
3183: @example
3184: VIEW 64:@emph{numexpr}
3185: @end example
3186:
3187: @item @code{65} - Set @code{$RANDOM} Parameter C
3188: Sets the number used for @code{$RANDOM} Parameter C to @emph{numexpr}.
3189:
3190: @emph{Syntax}
3191: @example
3192: VIEW 65:@emph{numexpr}
3193: @end example
3194:
3195: @item @code{66} - Set or Clear @code{SIGTERM} Handling Flag
3196: Enables or disables handling of @code{SIGTERM} UNIX signals. If @emph{tvexpr} evaluates to 1 (@emph{true}), @code{SIGTERM} handling will be enabled. Otherwise, @code{SIGTERM} handling will be disabled.
3197:
3198: @emph{Syntax}
3199: @example
3200: VIEW 66:@emph{tvexpr}
3201: @end example
3202:
3203: @item @code{67} - Set or Clear @code{SIGHUP} Handling Flag
3204: Enables or disables handling of @code{SIGHUP} UNIX signals. If @emph{tvexpr} evaluates to 1 (@emph{true}), @code{SIGHUP} handling will be enabled. Otherwise, @code{SIGHUP} handling will be disabled.
3205:
3206: @emph{Syntax}
3207: @example
3208: VIEW 67:@emph{tvexpr}
3209: @end example
3210:
3211: @item @code{70} - Set @code{$ZSORT}/@code{$ZSYNTAX} Flag
3212: Selects whether @code{$ZS} resolves to @code{$ZSORT} or @code{$ZSYNTAX}.
3213:
3214: If @emph{tvexpr} evaluates to @emph{true}, selects @code{$ZSYNTAX}. Otherwise, selects @code{$ZSORT}.
3215:
3216: @emph{Syntax}
3217: @example
3218: VIEW 70:@emph{tvexpr}
3219: @end example
3220:
3221: @item @code{71} - Set @code{$ZNEXT}/@code{$ZNAME} Flag
3222: Selects whether @code{$ZN} resolves to @code{$ZNEXT} or @code{$ZNAME}.
3223:
3224: If @emph{tvexpr} evaluates to @emph{true}, selects @code{$ZNAME}. Otherwise, selects @code{$ZNEXT}.
3225:
3226: @emph{Syntax}
3227: @example
3228: VIEW 71:@emph{tvexpr}
3229: @end example
3230:
3231: @item @code{72} - Set @code{$ZPREVIOUS}/@code{$ZPIECE} Flag
3232: Selects whether @code{$ZP} resolves to @code{$ZPREVIOUS} or @code{$ZPIECE}.
3233:
3234: If @emph{tvexpr} evaluates to @emph{true}, selects @code{$ZPIECE}. Otherwise, selects @code{$ZPREVIOUS}.
3235:
3236: @emph{Syntax}
3237: @example
3238: VIEW 72:@emph{tvexpr}
3239: @end example
3240:
3241: @item @code{73} - Set @code{$ZDATA}/@code{$ZDATE} Flag
3242: Selects whether @code{$ZD} resolves to @code{$ZDATA} or @code{$ZDATE}.
3243:
3244: If @emph{tvexpr} evaluates to @emph{true}, selects @code{$ZDATE}. Otherwise, selects @code{$ZDATA}.
3245:
3246: @emph{Syntax}
3247: @example
3248: VIEW 73:@emph{tvexpr}
3249: @end example
3250:
3251: @item @code{79} - Set Old @code{ZJOB} vs. New @code{ZJOB} Flag
3252: If @emph{tvexpr} evaluates to @emph{true}, sets the @code{ZJOB} mode to new, otherwise, sets it to old.
3253:
3254: @emph{Syntax}
3255: @example
3256: VIEW 79:@emph{tvexpr}
3257: @end example
3258:
3259: @item @code{80} - Set or Clear 8-Bit Flag
3260: If @emph{tvexpr} evaluates to @emph{true}, sets FreeM to 8-bit mode. Otherwise, sets FreeM to 7-bit mode.
3261:
3262: @emph{Syntax}
3263: @example
3264: VIEW 80:@emph{tvexpr}
3265: @end example
3266:
3267: @item @code{81} - Set or Clear PF1 Flag
3268: If @emph{tvexpr} evaluates to @emph{true}, sets the @code{PF1} flag. We do not yet know what this does.
3269:
3270: @emph{Syntax}
3271: @example
3272: VIEW 81:@emph{tvexpr}
3273: @end example
3274:
3275: @item @code{83} - Set or Clear Text in @code{$ZERROR} Flag
3276: If @emph{tvexpr} evaluates to @emph{true}, descriptive error messages will be included in @code{$ZERROR}. Otherwise, only the short error code (i.e. @emph{ZILLFUN}) will be included in @code{$ZERROR}.
3277:
3278: @emph{Syntax}
3279: @example
3280: VIEW 83:@emph{tvexpr}
3281: @end example
3282:
3283: @item @code{92} - Set Type Mismatch Error Flag on @code{EUR2DEM}
3284: If @emph{tvexpr} evaluates to @emph{true}, a type mismatch error will be thrown in @code{EUR2DEM} currency conversions in certain situations that we do not yet understand.
3285:
3286: @emph{Syntax}
3287: @example
3288: VIEW 92:@emph{tvexpr}
3289: @end example
3290:
3291: @item @code{93} - Define @code{ZKEY} Production Rule
3292: We do not know what this does.
3293:
3294: @item @code{96} - Set Global Prefix
3295: Forces global data filenames to be prefixed with the result of @emph{expr}.
3296:
3297: @emph{Syntax}
3298: @example
3299: VIEW 96:@emph{expr V string}
3300: @end example
3301:
3302: @item @code{97} - Set Global Postfix
3303: Forces global data filenames to be postfixed with the result of @emph{expr}.
3304:
3305: @emph{Syntax}
3306: @example
3307: VIEW 97:@emph{expr V string}
3308: @end example
3309:
3310: @item @code{98} - Set Routine Extension
3311: Sets the default extension for M routine filenames to the result of @emph{expr}.
3312:
3313: @emph{Syntax}
3314: @example
3315: VIEW 98:@emph{expr V string}
3316: @end example
3317:
3318: @item @code{101} - Set @code{ierr}
3319: Sets the FreeM internal @code{ierr} value to @emph{intexpr}. Used by some FreeM polyfills (commands or functions implemented in M code).
3320:
3321: @emph{Syntax}
3322: @example
3323: VIEW 101:@emph{intexpr}
3324: @end example
3325:
3326: @item @code{102} - Set @code{ierr} (Deferred)
3327: Sets the FreeM internal @code{ierr} value to @emph{intexpr}, but only after the current process stack level is exited. Used by FreeM polyfills to throw an error that will appear to come from the user's own code rather than the polyfill implementation M code.
3328:
3329: @emph{Syntax}
3330: @example
3331: VIEW 102:@emph{intexpr}
3332: @end example
3333:
3334: @item @code{103} - Signal @code{MERGE} to @code{^$WINDOW} Complete
3335: Signals FreeM's MWAPI implementation that a @code{MERGE} to @code{^$WINDOW} or descendant subscripts thereof has completed.
3336:
3337: @emph{Syntax}
3338: @example
3339: VIEW 103[@emph{:subscript}]
3340: @end example
3341:
3342: @item @code{110} - Set Local @code{$ORDER}/@code{$QUERY} Data Value
3343: Sets the local variable @code{$ORDER}/@code{$QUERY} data value to the result of @emph{expr}. We're not entirely sure what this is.
3344:
3345: @emph{Syntax}
3346: @example
3347: VIEW 110:@emph{expr}
3348: @end example
3349:
3350: @item @code{111} - Set Global @code{$ORDER}/@code{$QUERY} Data Value
3351: Sets the global variable @code{$ORDER}/@code{$QUERY} data value to the result of @emph{expr}. We're not entirely sure what this is.
3352:
3353: @emph{Syntax}
3354: @example
3355: VIEW 111:@emph{expr}
3356: @end example
3357:
3358: @item @code{113} - Set @code{termio} Information
3359: We don't know what this does.
3360:
3361: @item @code{133} - Remember @code{ZLOAD} Directory on @code{ZSAVE}
3362: We don't know what this does, but it takes a @emph{tvexpr}.
3363:
3364: @emph{Syntax}
3365: @example
3366: VIEW 133:@emph{tvexpr}
3367: @end example
3368:
3369: @end table
3370:
3371:
3372:
3373: @node WRITE
3374: @section WRITE
3375: @cindex WRITE
3376: @cindex commands, WRITE
3377:
3378: @node XECUTE
3379: @section XECUTE
3380: @cindex XECUTE
3381: @cindex commands, XECUTE
3382:
1.46 snw 3383: @node ZASSERT
3384: @section ZASSERT
3385: @cindex ZASSERT
3386: @cindex commands, ZASSERT
3387: @cindex commands, debugging
3388: @cindex commands, implementation-specific
3389: @cindex commands, non-standard
3390: @emph{FreeM Extension}
3391:
3392: 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}), and that the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
3393:
3394: The @code{ZASSERT} error is catchable whether using standard-style, FreeM-style, or DSM 2.0-style error processing.
3395:
3396: @emph{Syntax}
3397:
3398: @example
3399: ZASSERT@emph{:postcondition} @emph{<tvexpr>}
3400: @end example
3401:
3402: @emph{Example}
3403:
3404: @example
3405: DEFAULT.USER> SET DEBUG=1
3406:
3407:
3408: DEFAULT.USER> ZASSERT:DEBUG 1=1
3409:
3410:
3411: DEFAULT.USER> ZASSERT:DEBUG 1=0
3412:
3413:
3414: >> Error ZASSERT: programmer assertion failed in SYSTEM::^%SYSINIT [$STACK = 0]
3415: >> ZASSERT:DEBUG 1=0
3416: ^
3417: @end example
3418:
1.1 snw 3419: @node ZBREAK
3420: @section ZBREAK
3421: @cindex ZBREAK
3422: @cindex commands, ZBREAK
3423: @cindex commands, debugging
3424: @cindex commands, implementation-specific
3425: @cindex commands, non-standard
3426: @emph{FreeM Extension}
3427:
1.48 snw 3428: Sets or clears the @code{ZBREAK} flag@footnote{NOTE: FreeM team needs to investigate how @code{zbreakon} and @code{zbflag} affect program execution.}, based on the result of evaluating @emph{tvexpr}.
3429:
3430: @emph{Syntax}
3431:
3432: @example
3433: ZBREAK @emph{tvexpr}
3434: @end example
3435:
1.42 snw 3436: @node ZCONST
3437: @section ZCONST
3438: @cindex ZCONST
3439: @cindex commands, ZCONST
3440: @cindex commands, non-standard
3441: @emph{FreeM Extension}
3442:
3443: Defines a local @emph{constant}, or variable that cannot be altered after its initial definition, provided the optional @emph{postcondition} is @emph{true} or omitted.
3444:
3445: Constants must only be locals, and globals are not supported.
3446:
3447: @emph{Syntax}
3448:
3449: @example
3450: @code{ZCONST@emph{:postcondition} @emph{mref1}=@emph{initial-value1},...,@emph{mrefN}=@emph{initial-valueN}}
3451: @end example
3452:
1.59 snw 3453: @node ZEDIT
3454: @section ZEDIT
3455: @cindex ZEDIT
3456: @cindex commands, ZEDIT
3457: @cindex commands, non-standard
3458: @emph{FreeM Extension}
3459:
3460: Edits a routine using an external editor. Uses environment variable @code{$EDITOR} if defined; otherwise, uses @code{vi}.
3461:
3462: @emph{Syntax}
3463:
3464: @example
3465: ZEDIT@emph{[:postcondition]}
3466: @end example
3467:
3468: In its argumentless form, edits the currently-active routine, provided the optional @emph{postcondition} is @emph{true} or omitted.
3469:
3470: @emph{Syntax}
3471:
3472: @example
3473: ZEDIT@emph{[:postcondition]} @emph{<routine-name>}
3474: @end example
3475:
3476: In its single-argument form, edits @emph{<routine-name>}, provided the optional @emph{postcondition} is @emph{true} or omitted.
3477:
1.63 ! snw 3478: If the specified routine does not exist, it will be created.
! 3479:
1.59 snw 3480: Routine names must not be quoted, and must not included a leading caret (@code{^}).
3481:
3482: @emph{Errors}
3483:
1.63 ! snw 3484: @code{ZEDIT} will raise @code{ZNOPGM} in its argumentless form if there is no routine currently loaded.
1.59 snw 3485:
1.48 snw 3486: @node ZGOTO
3487: @section ZGOTO
3488: @cindex ZGOTO
3489: @cindex commands, ZGOTO
1.1 snw 3490: @cindex commands, implementation-specific
3491: @cindex commands, non-standard
3492: @emph{FreeM Extension}
3493:
1.59 snw 3494: In its single-argument form, enables @code{BREAK} mode and branches unconditionally to @emph{entryref}.
1.48 snw 3495:
3496: @emph{Syntax}
3497:
3498: @example
3499: ZGOTO @emph{entryref}
3500: @end example
3501:
1.59 snw 3502: In its argumentless form, resumes execution after a @code{BREAK}.
1.48 snw 3503:
3504: @emph{Syntax}
3505:
3506: @example
3507: ZGOTO
3508: @end example
3509:
1.1 snw 3510: @node ZHALT
3511: @section ZHALT
3512: @cindex ZHALT
3513: @cindex commands, ZHALT
3514: @cindex commands, implementation-specific
3515: @cindex commands, non-standard
3516: @emph{FreeM Extension}
3517:
1.48 snw 3518: In its single-argumented form, @code{ZHALT} command is used to exit the FreeM process with a specific return value @emph{intexpr}.
3519:
3520: @emph{Syntax}
3521:
3522: @example
3523: ZHALT @emph{intexpr}
3524: @end example
3525:
3526: In its argumentless form, @code{ZHALT} is synonymous with @code{HALT}.
3527:
3528: @emph{Syntax}
3529:
3530: @example
3531: ZHALT
3532: @end example
3533:
1.1 snw 3534: @node ZINSERT
3535: @section ZINSERT
3536: @cindex ZINSERT
3537: @cindex commands, ZINSERT
3538: @cindex commands, implementation-specific
3539: @cindex commands, non-standard
3540: @emph{FreeM Extension}
3541:
1.61 snw 3542: Inserts a line of M code into the currently-active routine buffer, provided the optional @emph{postcondition} is @emph{true} or omitted.
3543:
3544: @emph{Syntax}
3545:
3546: @example
3547: ZINSERT@emph{:postcondition} @emph{expr V mcode}[:@emph{label}]
3548: @end example
3549:
3550: Above, @emph{expr V mcode} is an expression returning a string giving M code. If @emph{label} is omitted, the code will be inserted at the insertion point, which is typically the end of the routine. Otherwise, the code will be inserted at the line immediately following @emph{label}.
3551:
1.1 snw 3552: @node ZJOB
3553: @section ZJOB
3554: @cindex ZJOB
3555: @cindex commands, ZJOB
3556: @cindex commands, implementation-specific
3557: @cindex commands, non-standard
3558: @emph{FreeM Extension}
3559:
3560: When @code{ZJOB} is used, the semantics are identical to @code{JOB}, with the exception that the @emph{timeout} is forced to be @code{0}, regardless of what the user specifies.
3561:
3562: For more information, see @code{JOB}.
3563:
3564: @node ZLOAD
3565: @section ZLOAD
3566: @cindex ZLOAD
3567: @cindex commands, ZLOAD
3568: @cindex commands, implementation-specific
3569: @cindex commands, non-standard
3570: @emph{FreeM Extension}
3571:
3572: Loads routine @emph{<routine-name>} into FreeM's routine buffer, provided the optional @emph{postcondition} is @emph{true} or omitted.
3573:
3574: @emph{Syntax}
3575:
3576: @example
3577: ZLOAD@emph{:postcondition} @emph{<routine-name>}
3578: @end example
3579:
1.42 snw 3580:
3581: @node ZMAP
3582: @section ZMAP
3583: @cindex ZMAP
3584: @cindex commands, ZMAP
3585: @cindex commands, implementation-specific
3586: @cindex commands, non-standard
3587:
3588: Maps global name @code{gvn} to be mapped to the non-default namespace @emph{expr V namespace}, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
3589:
3590: @emph{Syntax}
3591:
3592: @example
3593: ZMAP[@emph{:postcondition}] GLOBAL @emph{gvn}=@emph{expr V namespace}
3594: @end example
3595:
1.1 snw 3596: @node ZNEW
3597: @section ZNEW
3598: @cindex ZNEW
3599: @cindex commands, ZNEW
3600: @cindex commands, implementation-specific
3601: @cindex commands, non-standard
3602: @emph{FreeM Extension}
3603:
3604: @node ZPRINT
3605: @section ZPRINT
3606: @cindex ZPRINT
3607: @cindex commands, ZPRINT
3608: @cindex commands, implementation-specific
3609: @cindex commands, non-standard
3610: @emph{FreeM Extension}
3611:
1.60 snw 3612: In argumentless form, prints the contents of the current routine buffer, provided the optional @emph{postcondition} is @emph{true} or omitted.
1.1 snw 3613:
3614: @emph{Syntax}
3615:
3616: @example
3617: ZPRINT@emph{:postcondition}
3618: @end example
3619:
1.60 snw 3620: In argumented form, prints a subset of the current routine buffer, provided the optional @emph{postcondition} is @emph{true} or omitted.
3621:
3622: @emph{Syntax}
3623:
3624: @example
3625: ZPRINT@emph{:postcondition} @emph{start}[:@emph{end}]
3626: @end example
3627:
3628: In the above syntax, @emph{start} and @emph{end} can be a tag in the current routine, or @code{*} to indicate the routine buffer insertion point (typically the end of the routine).
3629:
1.1 snw 3630: @node ZQUIT
3631: @section ZQUIT
3632: @cindex ZQUIT
3633: @cindex commands, ZQUIT
3634: @cindex commands, implementation-specific
3635: @cindex commands, non-standard
3636: @emph{FreeM Extension}
3637:
3638: In its single-argument form, quits from @emph{levels} levels of the stack, provided the optional @emph{postcondition} is @emph{true} or omitted.
3639:
3640: In its argumentless form, quits from @code{$STACK} levels of the stack, provided the optional @emph{postcondition} is @emph{true} or omitted.
3641:
3642: @emph{Syntax}
3643:
3644: @example
3645: @code{ZQUIT@emph{:postcondition} [@emph{levels}]}
3646: @end example
3647:
3648: @node ZREMOVE
3649: @section ZREMOVE
3650: @cindex ZREMOVE
3651: @cindex commands, ZREMOVE
3652: @cindex commands, implementation-specific
3653: @cindex commands, non-standard
3654: @emph{FreeM Extension}
3655:
1.61 snw 3656: In argumentless form, removes all M code from the current routine buffer, provided the optional @emph{postcondition} is @emph{true} or omitted.
3657:
3658: @emph{Syntax}
3659:
3660: @example
3661: ZREMOVE@emph{:postcondition}
3662: @end example
3663:
3664: In argumented form, removes a subset of the current routine buffer, provided the optional @emph{postcondition} is @emph{true} or omitted.
3665:
3666: @emph{Syntax}
3667:
3668: @example
3669: ZREMOVE@emph{:postcondition} @emph{start}[:@emph{end}]
3670: @end example
3671:
3672: In the above syntax, @emph{start} and @emph{end} can be a tag in the current routine, or @code{*} to indicate the routine buffer insertion point (typically the end of the routine).
3673:
1.1 snw 3674: @node ZSAVE
3675: @section ZSAVE
3676: @cindex ZSAVE
3677: @cindex commands, ZSAVE
3678: @cindex commands, implementation-specific
3679: @cindex commands, non-standard
3680: @emph{FreeM Extension}
3681:
1.42 snw 3682:
3683: @node ZTHROW
3684: @section ZTHROW
3685: @cindex ZTHROW
3686: @cindex commands, ZTHROW
3687: @cindex commands, non-standard
3688: @emph{FreeM Extension}
3689:
3690: Raises an error condition as long as the optional @emph{postcondition} is @emph{true} or omitted.
3691:
3692: @emph{Syntax}
3693:
3694: @example
3695: @code{ZTHROW@emph{:postcondition} @emph{expr V error-code}}
3696: @end example
3697:
3698: @emph{Example}
3699:
3700: @example
3701: @code{ZTHROW "M102"}
3702: @end example
3703:
1.1 snw 3704: @node ZTRAP
3705: @section ZTRAP
3706: @cindex ZTRAP
3707: @cindex commands, ZTRAP
3708: @cindex commands, debugging
3709: @cindex commands, implementation-specific
3710: @cindex commands, non-standard
3711: @emph{FreeM Extension}
3712:
1.50 snw 3713: Synonymous with @ref{ZTHROW}.
3714:
1.42 snw 3715: @node ZUNMAP
3716: @section ZUNMAP
3717: @cindex ZUNMAP
3718: @cindex commands, ZUNMAP
3719: @cindex commands, implementation-specific
3720: @cindex commands, non-standard
3721:
3722: Removes any mapping connecting @emph{gvn} to a non-default namespace, provided the optional @emph{postcondition} evaluates to @emph{true} or is omitted.
3723:
3724: @emph{Syntax}
3725:
3726: @example
3727: ZUNMAP GLOBAL @emph{gvn}
3728: @end example
3729:
3730: @node ZWATCH
3731: @section ZWATCH
3732: @cindex ZWATCH
3733: @cindex commands, ZWATCH
3734: @cindex commands, debugging
3735: @cindex commands, implementation-specific
3736: @cindex commands, non-standard
3737: @emph{FreeM Extension}
3738:
3739: Sets a watchpoint on a global, local, or SSVN node.
3740:
3741: @emph{Syntax}
3742:
3743:
3744: In its @emph{argumentless} form, @code{ZWATCH} toggles watchpoints on and off, provided the optional @emph{postcondition} is @emph{true} or omitted.
3745:
3746: @example
3747: ZWATCH[@emph{:postcondition}]
3748: @end example
3749:
3750: In its @emph{inclusive} form, @code{ZWATCH} adds, removes, or examines watchpoints, provided the optional @emph{postcondition} is @emph{true} or omitted.
3751:
3752: A @code{+} adds a new watchpoint to the following variable.
3753:
3754: A @code{-} removes an existing watchpoint for the following variable.
3755:
3756: A @code{?} examines the status of a watchpoint for the following variable.
3757:
3758: @example
3759: ZWATCH[@emph{:postcondition}] [+|-|?]@emph{var1}...,[+|-|?]@emph{varN}
3760: @end example
3761:
3762:
3763: The following example demonstrates turning watchpoint processing on and adding a watchpoint for global variable @code{^snw(1)}. It then changes the value of @code{^snw(1)}.
3764:
3765: @example
3766: DEFAULT.USER> ZWATCH
3767:
3768: Watchpoints enabled.
3769:
3770: DEFAULT.USER> ZWATCH +^SNW(1)
3771:
3772: Added '^SNW("1")' to the watchlist.
3773:
3774: DEFAULT.USER> SET ^SNW(1)="new value"
3775:
3776: >> WATCHPOINT: ^SNW("1") => 'new value' (changed 1 times)
3777:
3778: @end example
3779:
3780: The following example will remove that watchpoint:
3781:
3782: @example
3783: DEFAULT.USER> ZWATCH -^SNW(1)
3784:
3785: Removed '^SNW("1")' from the watchlist.
3786:
3787: DEFAULT.USER> ZWATCH ?^SNW(1)
3788:
3789: '^SNW("1")' is not being watched.
3790: @end example
3791:
3792: @node ZWITH
3793: @section ZWITH
3794: @cindex ZWITH
3795: @cindex commands, ZWITH
3796: @cindex commands, non-standard
3797: @emph{FreeM Extension}
3798:
3799: NOTE: This command may be deprecated and removed in future FreeM releases.
3800:
3801: Sets a prefix to be applied to all subsequent local variable or constant references.
3802:
3803: @emph{Syntax}
3804:
3805: @example
3806: @code{ZWITH@emph{:postcondition} @emph{var-prefix}}
3807: @end example
3808:
3809: In the above single-argument form, sets the @code{$WITH} prefix to @emph{var-prefix}, provided that the optional @emph{postcondition} is either @emph{true} or omitted.
3810:
3811: The @emph{var-prefix} argument may be a string literal or any valid FreeM expression.
3812:
3813: @example
3814: @code{ZWITH@emph{:postcondition}}
3815: @end example
3816:
3817: In the above argumentless form, clears the @code{$WITH} prefix, provided the optional @emph{postcondition} is either @emph{true} or omitted. Equivalent to @code{ZWITH ""}.
3818:
3819:
3820:
3821:
3822:
3823:
3824:
3825:
1.1 snw 3826: @node ZWRITE
3827: @section ZWRITE
3828: @cindex ZWRITE
3829: @cindex commands, ZWRITE
3830: @cindex commands, implementation-specific
3831: @cindex commands, non-standard
3832: @emph{FreeM Extension}
3833:
3834: Writes the names and values of M variables to @code{$IO}.
3835:
3836: @emph{Syntax}
3837:
3838: @example
3839: ZWRITE@emph{:postcondition}
3840: @end example
3841:
3842: 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.
3843:
3844: @example
3845: ZWRITE@emph{:postcondition} @emph{ArrayName},@dots{}
3846: @end example
3847:
3848: 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.
3849:
3850: @example
3851: ZWRITE@emph{:postcondition} (@emph{ArrayName},@dots{})
3852: @end example
3853:
3854: 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.
3855:
3856:
3857: @node Structured System Variables
3858: @chapter Structured System Variables
3859: @cindex variables, structured system
3860: @cindex structured system variables
3861: @cindex SSVNs
3862:
3863: @menu
3864: * ^$CHARACTER:: Character set information.
3865: * ^$DEVICE:: Device information.
3866: * ^$DISPLAY:: Information about graphic display.
3867: * ^$EVENT:: Information supplied about a synchronous or asynchronous event.
3868: * ^$GLOBAL:: Information about M globals.
3869: * ^$JOB:: Information about and control of FreeM jobs.
3870: * ^$LOCK:: Information about the FreeM lock table.
3871: * ^$OBJECT:: Information about FreeM objects.
3872: * ^$ROUTINE:: Information about FreeM routines.
3873: * ^$SYSTEM:: Information about the running system.
3874: * ^$WINDOW:: Configuration of MWAPI windows.
3875: * ^$ZPROCESS:: Information about and control of system processes.
3876: * ^$ZRPI:: Information about and control of Raspberry Pi GPIO pins.
3877: @end menu
3878:
3879: SSVN subscripts are each described in the following format:
3880:
3881: @table @asis
3882: @item @code{@emph{<ssvn-subscript-name>}} +/-R +/-U +/-D
3883: @end table
3884:
3885: 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.
3886:
3887: @node ^$CHARACTER
3888: @section ^$CHARACTER
3889: @cindex ^$CHARACTER
3890: @cindex structured system variables, ^$CHARACTER
3891:
3892: Exposes character set information. As FreeM currently only supports the @code{M} character set, the first subscript of @code{^$CHARACTER} must always be @code{"M"}.
3893:
3894: The following values for the second subscript are supported:
3895:
3896: @table @asis
3897:
3898: @item @code{IDENT} +R -U -D
3899: Returns the empty string.
3900:
3901: @item @code{COLLATE} +R -U -D
3902: Returns the empty string.
3903:
3904: @item @code{INPUT} +R -U -D
3905: Returns the empty string if the third subscript is @code{M}, otherwise, raises error @code{M38}.
3906:
3907: @item @code{OUTPUT} +R -U -D
3908: Returns the empty string if the third subscript is @code{M}, otherwise, raises error @code{M38}.
3909:
3910: @end table
3911:
3912: @node ^$DEVICE
3913: @section ^$DEVICE
3914: @cindex ^$DEVICE
3915: @cindex structured system variables, ^$DEVICE
3916:
3917: FreeM implements several important pieces of functionality in the @code{^$DEVICE} SSVN.
3918:
3919: The first subscript of @code{^$DEVICE} represents the I/O channel of an @code{OPEN}ed device.
3920:
3921: The following values for the second subscript are supported:
3922:
3923: @table @asis
3924:
3925: @item @code{$DEVICE}
3926: Returns the value of @code{$DEVICE} for the specified I/O channel.
3927:
3928: @item @code{$X} +R -U -D
3929: Returns the horizontal cursor position of a terminal device. Only valid if the I/O channel is @code{0}.
3930:
3931: @item @code{$Y} +R -U -D
3932: Returns the vertical cursor position of a terminal device. Only valid if the I/O channel is @code{0}.
3933:
3934: @item @code{ROWS} +R -U -D
3935: Returns the number of character rows on the terminal device. Only valid if the I/O channel is @code{0}.
3936:
3937: @item @code{COLUMNS} +R -U -D
3938: Returns the number of character columns on the terminal device. Only valid if the I/O channel is @code{0}.
3939:
3940: @item @code{CHARACTER} +R -U -D
3941: Returns the character set of the specified I/O channel; always @code{M} in the current implementation.
3942:
3943: @item @code{INPUT_BUFFER} +R +U -D
3944: Returns or sets the contents of the input buffer for the specified I/O channel. Data populated in this node will remain in the buffer until subsequent @code{READ} command(s) remove it. This can be used to perform input buffer stuffing, i.e., to fill out an interactive form programmatically.
3945:
3946: @item @code{NAME} +R -U -D
3947: Returns the operating system's name for the file, device, or socket attached to the specified I/O channel.
3948:
3949: @item @code{FD} +R -U -D
3950: Returns the UNIX file descriptor of the specified I/O channel.
3951:
3952: @item @code{MODE} +R -U -D
3953: Returns one of @code{READ}, @code{WRITE}, @code{READWRITE}, or @code{APPEND}, depending on the mode in which the specified I/O channel was opened.
3954:
3955: @item @code{EOF} +R -U -D
3956: 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.
3957:
3958: @item @code{LENGTH} +R -U -D
3959: 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.
3960:
3961: @item @code{NAMESPACE} +R -U -D
3962: Returns the current @emph{mnemonic-space} in use for the referenced I/O channel. Always @code{X364} for terminals and blank for sequential files.
3963:
3964: @item @code{TYPE} +R -U -D
3965: Returns either @code{1,FILE}, @code{2,SOCKET}, or @code{4,TERMINAL}, depending on the device type associated with the specified I/O channel.
3966:
3967: @item @code{OPTIONS} -R -U -D
3968: The following subscripts reside beneath @code{^$DEVICE(<io-channel>,"OPTIONS")}, and this subscript may not be accessed without one of the following third-level subscripts being specified:
3969:
3970: @table @asis
3971:
3972: @item @code{DSW} +R +U -D
3973: Sets or returns the current @emph{Device Status Word} controlling terminal characteristics. Only valid for I/O channel 0.
3974:
3975: @item @code{TERMINATOR} +R +U -D
3976: 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).
3977:
3978: @item @code{TERMID} +R -U -D
3979: Returns the type of terminal connected to channel 0. Only valid for I/O channel 0.
3980:
3981: @item @code{ECHO} +R +U -D
3982: 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.
3983:
3984: @item @code{DELMODE} +R +U -D
3985: 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.
3986:
3987: @item @code{ESCAPE} +R +U -D
3988: 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.
3989:
3990: @item @code{CONVUPPER} +R +U -D
3991: 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.
3992:
3993: @item @code{DELEMPTY} +R +U -D
3994: 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.
3995:
3996: @item @code{NOCTRLS} +R +U -D
3997: TBD. Only valid for I/O channel 0. Corresponds to bit 20 of the Device Status Word.
3998:
3999: @item @code{CTRLOPROC} +R +U -D
4000: 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.
4001:
4002: @item @code{NOTYPEAHEAD} +R +U -D
4003: 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.
4004: @end table
4005: @end table
4006:
4007: @emph{Example}
4008:
4009: 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.
4010:
4011: @example
4012: SET ^$JOB($JOB,"IOPATH")="/etc" ; set I/O path to /etc
4013: OPEN 1:"freem.conf/r" ; open freem.conf for reading
4014: ;
4015: ; read until we run out of lines
4016: ;
4017: FOR USE 1 READ LINE USE 0 QUIT:^$DEVICE(1,"EOF") D
4018: . WRITE LINE,!
4019: ;
4020: CLOSE 1
4021: QUIT
4022: @end example
4023:
4024: @node ^$DISPLAY
4025: @section ^$DISPLAY
4026: @cindex ^$DISPLAY
4027: @cindex structured system variables, ^$DISPLAY
4028:
4029: Provides information about the specified graphical display. The first subscript corresponds to a display number, which is an integer value, often corresponding to the current value of the @code{$PDISPLAY} ISV.
4030:
4031: The following second-level subscripts and specified descendant subscripts are supported:
4032:
4033: @table @asis
4034:
4035: @item @code{CLIPBOARD} +R +U +D
4036: Retrieves, sets, or erases the contents of the system clipboard.
4037:
4038: @item @code{PLATFORM} +R -U -D
4039: Retrieves the name and version of the underlying window system platform.
4040:
4041: @item @code{SIZE} +R -U -D
4042: Retrieves the display resolution of the specified graphical display. For instance, a 1080p display would have a @code{SIZE} value of @code{1920,1080}.
4043:
4044: @item @code{SPECTRUM} +R -U -D
4045: Retrieves the color depth (number of colors supported) of the specified graphical display.
4046:
4047: @item @code{COLORTYPE} +R -U -D
4048: Always returns @code{COLOR}, as monochrome and grayscale displays are not yet supported in FreeM.
4049:
4050: @item @code{UNITS} +R -U -D
4051: Returns the measurement unit of the specified display, i.e., @code{PIXEL}.
4052:
4053: @item @code{TYPEFACE} +R -U -D
4054: The third-level subscripts beneath this subscript represent a list of font families available on this display. The fourth level subscript is a list of sizes supported for the specified typeface, or @code{0} for vector typefaces, such as TrueType, OpenType, and Adobe Type 1 fonts.
4055:
4056: @end table
4057:
4058: @node ^$EVENT
4059: @section ^$EVENT
4060: @cindex ^$EVENT
4061: @cindex structured system variables, ^$EVENT
4062:
4063: The @code{^$EVENT} SSVN is not yet implemented.
4064:
4065: @node ^$GLOBAL
4066: @section ^$GLOBAL
4067: @cindex ^$GLOBAL
4068: @cindex structured system variables, ^$GLOBAL
4069:
4070: The @code{^$GLOBAL} structured system variable provides information about M globals. The first-level subscript is a global name, sans the leading caret symbol.
4071:
4072: The following second-level subscripts are supported:
4073:
4074: @table @asis
4075:
4076: @item @code{BYTES} +R -U -D
4077: Returns the number of bytes this global occupies in fixed storage.
4078:
4079: @item @code{BLOCKS} +R -U -D
4080: Returns the number of blocks contained in this global.
4081:
4082: @item @code{BLOCKSIZE} +R -U -D
4083: Returns the size of data blocks for this global. Currently, FreeM only supports 1024-byte blocks.
4084:
4085: @item @code{FILE} +R -U -D
4086: Returns the full filesystem path to the data file where this global resides in fixed storage.
4087:
4088: @item @code{NAMESPACE} +R +U +D
4089: Returns or sets the name of the FreeM namespace to which this global belongs. @code{SET}ting this node creates a mapping for the specified global name to a non-default namespace. @code{KILL}ing this node restores the mapping configuration for the specified global to the default.
4090:
4091: @end table
4092:
4093: @node ^$JOB
4094: @section ^$JOB
4095: @cindex ^$JOB
4096: @cindex structured system variables, ^$JOB
4097:
4098: FreeM fully implements @code{^$JOB} per ANSI X11.1-1995, as well as several extensions proposed in the M Millennium Draft Standard.
4099:
4100: The first subscript of @code{^$JOB} represents the @code{$JOB} of the process.
4101:
4102: 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.
4103:
4104: The following subscripts are supported:
4105:
4106: @table @asis
4107:
4108: @item @code{GVNDEFAULT} +R +U +D
4109: Contains a default expression to be evaluated if a global variable access attempt results in an @code{M7} error.
4110:
4111: Equivalent to wrapping all global accesses in @code{$GET(@emph{global-name},@emph{string-expr})}.
4112:
4113: @item @code{LVNDEFAULT} +R +U +D
4114: Contains a default expression to be evaluated if a local variable access attempt results in an @code{M6} error.
4115:
4116: Equivalent to wrapping all local accesses in @code{$GET(@emph{global-name},@emph{string-expr})}.
4117:
4118: @item @code{LVNQOVAL} +R +U +D
4119: Contains the data value (if any) at the subscripted local variable reference from the most recent @code{$ORDER} or @code{$QUERY} operation.
4120:
4121: This node is useful for code that uses @code{$ORDER} or @code{$QUERY} heavily in loops that retrieve successive data values, as it will prevent an additional symbol table scan that would result from retrieving the data value in the usual way, thus improving application performance. However, this optimization comes at the cost of compatibility with other M implementations.
4122:
4123: @item @code{GVNQOVAL} +R +U +D
4124: Contains the data value (if any) at the subscripted global variable reference from the most recent @code{$ORDER} or @code{$QUERY} operation.
4125:
4126: This node is useful for code that uses @code{$ORDER} or @code{$QUERY} heavily in loops that retrieve successive data values, as it will prevent an additional data file scan that would result from retrieving the data value in the usual way, thus improving application performance. However, this optimization comes at the cost of compatibility with other M implementations.
4127:
4128: @item @code{ZCOMMANDS} +R +U -D
4129: Contains a space-delimited list of @code{Z}-commands to be treated as intrinsic. Any @code{Z}-command not appearing in this list will be treated as a user-defined command.
4130:
4131: For instance, if command @code{ZFOO} does @emph{not} appear in this list, FreeM will attempt to run @code{^%ZFOO} as a subroutine when the @code{ZFOO} command is encountered in program code.
4132:
4133: If you remove a command from this list, you may provide your own private M implementation of the command in the manner described above.
4134:
4135: If an argument is passed to a @code{Z}-command you implement in M, it is made available to your M code in a variable whose name is specified in @code{^$JOB($JOB,"ZCOMMAND_ARGUMENT_NAME")}, which defaults to @code{%}.
4136:
4137: @item @code{PIPE_GLVN} +R +U -D
4138: Contains an M local or global variable to be used as standard input or standard output for the external shell commands run by @code{!<} and @code{!>}.
4139:
4140: @item @code{ZCOMMAND_ARGUMENT_NAME} +R +U -D
4141: Returns or sets the variable name in which arguments to user-defined @code{Z}-commands are passed. Defaults to @code{%}.
4142:
4143: @item @code{ZFUNCTIONS} +R +U -D
4144: Contains a space-delimited list of @code{Z} functions to be treated as intrinsic. Any @code{Z} function not appearing in this list will be treated as a user-defined extrinsic function.
4145:
4146: For instance, if function @code{$ZFOO} does @emph{not} appear in this list, FreeM will attempt to return the value of @code{$$^%ZFOO} called as an extrinsic function.
4147:
4148: If you remove a function from this list, you may provide your own private M implementation of the function in the manner described above.
4149:
4150: @item @code{ZSVS} +R +U -D
4151: Contains a space-delimited list of @code{Z} special variables to be treated as intrinsic. Any @code{Z} special variable not appearing in this list will be treated as a user-defined extrinsic function taking no arguments.
4152:
4153: For instance, if the special variable @code{$ZFOO} does @emph{not} appear in this list, FreeM will attempt to return the value of @code{$$^%ZFOO} called as an extrinsic function.
4154:
4155: If you remove a built-in special variable from this list, you may provide your own private M implementation of the special variable in the manner described above.
4156:
4157: @item @code{BREAK_HANDLER} +R +U -D
4158: Contains M code to be executed when the @code{BREAK} command is run.
4159:
4160: @item @code{ROUTINE_BUFFER_SIZE} +R +U -D
4161: Returns or sets the number of bytes allocated to each routine buffer. If @code{ROUTINE_BUFFER_AUTO_ADJUST} is set to @code{0}, this determines the maximum size of routines that FreeM will execute.
4162:
4163: @item @code{ROUTINE_BUFFER_COUNT} +R +U -D
4164: Returns or sets the number of routine buffers that FreeM will store in memory concurrently. Raising this value will increase memory usage, but will also increase performance if your applications call many different routines repeatedly.
4165:
4166: @item @code{ROUTINE_BUFFER_AUTO_ADJUST} +R +U -D
4167: Determines whether or not the size of routine buffers will be automatically adjusted at runtime. If set to @code{0}, routine buffers will be fixed to the byte size specified in @code{ROUTINE_BUFFER_SIZE} and may be manually resized using @code{ROUTINE_BUFFER_SIZE}. If set to @code{1}, routine buffers will grow automatically as necessary.
4168:
4169: @item @code{SYMBOL_TABLE_SIZE} +R +U -D
4170: Returns or sets the number of bytes allocated to each of the two FreeM symbol tables. If @code{SYMBOL_TABLE_AUTO_ADJUST} is @code{1}, this value is treated as a default, initial size. If @code{SYMBOL_TABLE_AUTO_ADJUST} is @code{0}, this value controls the fixed size of the two symbol tables.
4171:
4172: @item @code{SYMBOL_TABLE_AUTO_ADJUST} +R +U -D
4173: Determines whether or not the size of the two FreeM symbol tables will be automatically adjusted at runtime. If set to @code{0}, the symbol table will be fixed to the byte size specified in @code{SYMBOL_TABLE_SIZE} and may be manually resized by modifying @code{SYMBOL_TABLE_SIZE}. If set to @code{1}, the two symbol tables will grow automatically as necessary.
4174:
4175:
4176: @item @code{USER_DEFINED_ISV_TABLE_SIZE} +R +U -D
4177: Returns or sets the number of bytes allocated to the FreeM user-defined intrinsic special variable table. If @code{USER_DEFINED_ISV_TABLE_AUTO_ADJUST} is @code{1}, this value is treated as a default, initial size. If @code{USER_DEFINED_ISV_TABLE_AUTO_ADJUST} is @code{0}, this value controls the fixed byte size of the user-defined intrinsic special variable table.
4178:
4179: @item @code{USER_DEFINED_ISV_TABLE_AUTO_ADJUST} +R +U -D
4180: Determines whether or not the size of the FreeM user-defined intrinsic special variable table will be automatically adjusted at runtime. If set to @code{0}, the user-defined ISV table will be fixed to the byte size specified in @code{USER_DEFINED_ISV_TABLE_SIZE} and may be manually resized by modifying @code{USER_DEFINED_ISV_TABLE_SIZE}. If set to @code{1}, the user-defined ISV table will grow automatically as necessary.
4181:
4182: @item @code{GVN_UNIQUE_CHARS} +R +U -D
4183: Returns or sets the number of characters of a global name that make it unique, from 1 to 255.
4184:
4185: @item @code{GVN_CASE_SENSITIVE} +R +U -D
4186: Returns or sets the case sensitivity of global names. If set to @code{0}, global names are case-insensitive. If set to @code{1}, global names are case-sensitive.
4187:
4188: @item @code{GVN_NAME_SUB_LENGTH} +R +U -D
4189: Returns or sets the maximum number of characters of a global name plus all of its subscripts, from 1-255.
4190:
4191: @item @code{GVN_SUB_LENGTH} +R +U -D
4192: Returns or sets the maximum number of characters of a single global subscript, from 1-255.
4193:
4194: @item @code{SINGLE_USER} +R +U -D
1.27 snw 4195: If set to @code{1}, FreeM will skip all file locking operations on globals. If set to @code{0}, FreeM will enforce file locking on both.
1.1 snw 4196:
1.27 snw 4197: Setting @code{SINGLE_USER} to @code{1} will improve FreeM performance, but you must @emph{ONLY} use this on systems where you are absolutely sure that only one FreeM process will run at any given time, as running multiple instances of FreeM concurrently when any of them are set to @code{SINGLE_USER} mode @emph{will} cause global data corruption.
1.1 snw 4198:
4199: @item @code{CHARACTER} +R -U -D
4200: Returns the character set of the job.
4201:
4202: @item @code{CWD} +R +U -D
4203: Returns or sets the current working directory of the job.
4204:
4205: @item @code{OPEN} +R -U -D
4206: The @code{^$JOB($JOB,"OPEN",<channel>} subscripts list the open I/O channels in the specified job.
4207:
4208: @item @code{BERKELEYDB,FLUSH_THRESHOLD} +R +U -D
4209: Returns or sets the number of write operations that will be cached in the BerkeleyDB global handler prior to flushing BerkeleyDB's cache to disk.
4210:
4211: @item @code{EVENT} +R +U +D
4212: 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.
4213:
4214: @item @code{GLOBAL} +R -U -D
4215: Returns the global environment of the job.
4216:
4217: @item @code{IOPATH} +R +U -D
4218: Returns or sets the @emph{I/O path} to be used by the @code{OPEN} command.
4219:
4220: @item @code{PRIORITY} +R +U -D
4221: Returns or sets the @emph{nice} value of the FreeM job.
4222:
4223: @item @code{REVSTR} +R +U -D
4224: When set to 1, allows @code{$EXTRACT} to accept negative values.
4225:
4226: @item @code{ROUTINE} +R -U -D
4227: Returns the name of the routine currently being executed by the job.
4228:
4229: @item @code{SYMTAB} +R +U -D
4230: Returns or sets the current local variable symbol table in use.
4231:
4232: FreeM supports two unique and independent symbol tables, allowing FreeM programs to maintain two independent sets of identically- or differently-named local variables per process.
4233:
4234: The default symbol table is @code{0}, and the alternate symbol table is @code{1}, corresponding to the valid values for @code{^$JOB($JOB,"SYMTAB")}.
4235:
4236: Setting this subscript to values other than @code{0} or @code{1} will result in a @code{ZINVEXPR} error.
4237:
4238: @item @code{$PDISPLAY} +R -U -D
4239: Returns the value of @code{$PDISPLAY} for the job.
4240:
4241: @item @code{$PRINCIPAL} +R -U -D
4242: Returns the value of @code{$PRINCIPAL} for the job.
4243:
4244: @item @code{$TLEVEL} +R -U -D
4245: Returns the current transaction level (value of @code{$TLEVEL} for the job.
4246:
4247: @item @code{$IO} +R -U -D
4248: Returns the current value of @code{$IO} for the job.
4249:
4250: @item @code{USER} +R -U -D
4251: Returns the UID of the user owning the job.
4252:
4253: @item @code{GROUP} +R -U -D
4254: Returns the GID of the group owning the job.
4255:
4256: @item @code{NAMESPACE} +R +U -D
4257: Returns or sets the name of the job's currently-active namespace.
4258:
4259: @item @code{MATH} +R +U -D
4260: 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 support up to 16 digits of numeric precision.
4261:
4262: @code{IEEE754} mode will make mathematical calculations significantly faster, especially when accelerated by a floating-point processor, at the expense of precision and accuracy.
4263:
4264: @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.
4265:
4266: Attempting to @code{SET} this node to values other than @code{FIXED} or @code{IEEE754} will set @code{$ECODE} to @code{M29}.
4267:
4268: @end table
4269:
4270: @node ^$LOCK
4271: @section ^$LOCK
4272: @cindex ^$LOCK
4273: @cindex structured system variables, ^$LOCK
4274:
4275: The first-level subscript of @code{^$LOCK} is a lock name. The value at each node is the PID which owns the lock, a comma, and the lock counter for the locked resource.
4276:
4277: Attempting to @code{SET} or @code{KILL} any node in @code{^$LOCK} will raise error @code{M29}.
4278:
4279: @node ^$OBJECT
4280: @section ^$OBJECT
4281: @cindex ^$OBJECT
4282: @cindex structured system variables, ^$OBJECT
4283:
4284: @node ^$ROUTINE
4285: @section ^$ROUTINE
4286: @cindex ^$ROUTINE
4287: @cindex structured system variables, ^$ROUTINE
4288:
4289: The @code{^$ROUTINE} SSVN exposes a list of routines available in the current FreeM namespace, as well as additional attributes further describing each routine.
4290:
4291: The first-level subscript is the name of a FreeM routine minus the leading caret symbol.
4292:
4293: The following second-level subscripts are supported:
4294:
4295: @table @asis
4296:
4297: @item @code{CHARACTER} +R -U -D
4298: Returns the character set of the routine.
4299:
4300: @item @code{NAMESPACE} +R -U -D
4301: Returns the name of the FreeM namespace in which the routine resides.
4302:
4303: @item @code{PATH} +R -U -D
4304: Returns the full filesystem path to the routine in fixed storage.
4305:
4306: @end table
4307:
4308: @node ^$SYSTEM
4309: @section ^$SYSTEM
4310: @cindex ^$SYSTEM
4311: @cindex structured system variables, ^$SYSTEM
4312:
4313: The @code{^$SYSTEM} SSVN exposes system-level implementation details.
4314:
4315: The following first-level subscripts are supported:
4316:
4317: @table @asis
4318:
4319: @item @code{DEFPSIZE} +R -U -D
4320: Returns the default size in bytes of the symbol table and routine buffer memory partition.
4321:
4322: @item @code{DEFUDFSVSIZ} +R -U -D
4323: Returns the default size in bytes of the user-defined intrinsic special variable table.
4324:
4325: @item @code{DEFNSIZE} +R -U -D
4326: Returns the default size of the @code{NEW} stack, in number of entries.
4327:
4328: @item @code{MAXNO_OF_RBUF} +R -U -D
4329: Returns the maximum number of routine buffers.
4330:
4331: @item @code{DEFNO_OF_RBUF} +R -U -D
4332: Returns the default number of routine buffers.
4333:
4334: @item @code{DEFPSIZE0} +R -U -D
4335: Returns the default size in bytes of each routine buffer.
4336:
4337: @item @code{NO_GLOBLS} +R -U -D
4338: Returns the maximum number of globals that can be concurrently opened.
4339:
4340: @item @code{NO_OF_GBUF} +R -U -D
4341: Returns the number of global buffers.
4342:
4343: @item @code{NESTLEVLS} +R -U -D
4344: Returns the depth of the @code{DO}, @code{FOR}, @code{XECUTE} stack.
4345:
4346: @item @code{PARDEPTH} +R -U -D
4347: Returns the maximum depth of the parser's parameter stack.
4348:
4349: @item @code{PATDEPTH} +R -U -D
4350: Returns the maximum number of @emph{patatom}s in each pattern.
4351:
4352: @item @code{TRLIM} +R -U -D
4353: Returns the trace limit of the @code{BUILTIN} global handler.
4354:
4355: @item @code{ARGS_IN_ESC} +R -U -D
4356: Returns the maximum number of arguments in a terminal escape sequence.
4357:
4358: @item @code{ZTLEN} +R -U -D
4359: Returns the maximum length of @code{$ZTRAP}.
4360:
4361: @item @code{FUNLEN} +R -U -D
4362: Returns the maximum length of the @code{$ZF} (function key) variable.
4363:
4364: @item @code{NAME_LENGTH} +R -U -D
4365: Returns the maximum length of variable names in the current FreeM build. Compatible with the same SSVN node in @emph{Reference Standard M}
4366:
4367: @item @code{STRING_MAX} +R -U -D
4368: Returns the maximum length of character strings in the current FreeM build. Compatible with the same SSVN node in @emph{Reference Standard M}
4369:
4370: @item @code{$NEXTOK} +R -U -D
4371: Returns a value indicating whether or not the @code{$NEXT} intrinsic function is allowed. In FreeM, @code{$NEXT} is always enabled, and this SSVN is provided solely for compatibility with @emph{Reference Standard M}. Thus, this SSVN node always returns @code{1}.
4372:
4373: @item @code{EOK} +R -U -D
4374: Returns a value indicating whether or not @code{E} notation for exponents is allowed. In FreeM, this feature is always enabled, and this SSVN is provided solely for compatibility with @emph{Reference Standard M}. Thus, this SSVN node always returns @code{1}.
4375:
4376: @item @code{OFFOK} +R -U -D
4377: Returns a value indicating whether or not offsets are allowed in @code{DO} and @code{GOTO}. In FreeM, this feature is always enabled, and this SSVN is provided solely for compatibility with @emph{Reference Standard M}. Thus, this SSVN node always returns @code{1}.
4378:
4379: @item @code{BIG_ENDIAN} +R -U -D
4380: Returns a 1 if FreeM is running on a big-endian platform, or a 0 otherwise. Compatible with the same SSVN node in @emph{Reference Standard M}.
4381:
4382: @item @code{NAMESPACE} +R -U -D
4383: The descendant subscripts of this node list each namespace in the current FreeM environment.
4384:
4385: @item @code{MAPPINGS,GLOBAL} +R -U -D
4386: Descendant subscripts of this node represent global name mappings set in @code{^$GLOBAL(@emph{gvn},"NAMESPACE")}
4387:
4388: @end table
4389:
4390: @node ^$WINDOW
4391: @section ^$WINDOW
4392: @cindex ^$WINDOW
4393: @cindex structured system variables, ^$WINDOW
4394:
4395: The @code{^$WINDOW} SSVN has no nodes yet defined. However, completing a @code{MERGE} to this SSVN will cause MWAPI-ish things to happen, and further work is proceeding on MWAPI implementation.
4396:
4397: @node ^$ZPROCESS
4398: @section ^$ZPROCESS
4399: @cindex ^$ZPROCESS
4400: @cindex structured system variables, ^$ZPROCESS
4401:
4402: 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.
4403:
4404: The first subscript always represents the @emph{process ID} of the external process being acted upon.
4405:
4406: The following values for the second subscript are supported:
4407:
4408:
4409: @table @asis
4410:
4411: @item @code{EXISTS} +R -U -D
4412: Returns 1 if the referenced process exists; 0 otherwise.
4413:
4414: @item @code{ATTRIBUTE} +R -U -D
4415: Exposes the @code{/proc} files as descendant subscripts, i.e., @code{WRITE ^$ZPROCESS(2900,"ATTRIBUTE","cmdline"),!} would print the initial command line used to invoke process ID 2900. Note that the third subscript (the immediate descendant of the @code{ATTRIBUTE} subscript) is case sensitive.
4416:
4417: @item @code{SIGNAL} -R +U -D
4418: 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}.
4419:
4420: The constants @code{%SYS.SIGNAL.HUP}, @code{%SYS.SIGNAL.INT}, @code{%SYS.SIGNAL.KILL}, and @code{%SYS.SIGNAL.TERM} are provided for convenient use of this SSVN subscript.
4421:
4422: @end table
4423:
4424: @node ^$ZRPI
4425: @section ^$ZRPI
4426: @cindex ^$ZRPI
4427: @cindex structured system variables, ^$ZRPI
4428:
4429: The @code{^$ZRPI} structured system variable provides easy access to general-purpose input/output (GPIO) pins on Raspberry Pi single-board computers.
4430:
4431: To initialize the GPIO subsystem, @code{SET ^$ZRPI("INITIALIZE")=1}.
4432:
4433: Individual pins are accessed through @code{^$ZRPI("GPIO",<pin>,...)}, where @code{<pin>} represents the desired pin number. Descendant subscripts of @code{^$ZRPI("GPIO",<pin>)} are as follows:
4434:
4435: @table @asis
4436:
4437: @item @code{MODE} +R +U -D
4438: Represents the operating mode of the selected pin. One of @code{INPUT}, @code{OUTPUT}, @code{PWM_OUTPUT}, or @code{GPIO_CLOCK}.
4439:
4440: @item @code{DIGITAL} +R +U -D
4441: Reads or writes the selected pin digitally. The value is limited to @code{1} or @code{0}.
4442:
4443: @item @code{ANALOG} +R +U -D
4444: Reads or writes the selected pin in an analog fashion. The value represents analog voltage.
4445:
4446: @end table
4447:
4448: @node Operators
4449: @chapter Operators
4450:
4451: @menu
4452: * Unary +:: Force a value to positive.
4453: * Unary -:: Force a value to negative.
4454: * +:: Add.
4455: * +=:: Add and assign.
4456: * ++:: Postfix increment.
4457: * -:: Subtract.
4458: * -=:: Subtract and assign.
4459: * --:: Postfix decrement.
4460: * *:: Multiply.
4461: * *=:: Multiply and assign.
4462: * /:: Divide.
4463: * /=:: Divide and assign.
4464: * \:: Integer divide.
4465: * \=:: Integer divide and assign.
4466: * #:: Modulo.
4467: * #=:: Modulo and assign.
4468: * **:: Exponentiate.
4469: * **=:: Exponentiate and assign.
4470: * <:: Less than.
4471: * <=:: Less than or equal to.
4472: * >:: Greater than.
4473: * >=:: Greater than or equal to.
4474: * _:: Concatenate.
4475: * _=:: Concatenate and assign.
4476: * =:: Equals.
4477: * [:: Contains.
4478: * ]:: Follows.
4479: * ]]:: Sorts after.
4480: * ?:: Pattern match.
4481: * &:: Logical AND.
4482: * ! (Operator):: Logical OR.
4483: * ':: Logical NOT.
4484: * @@ (Operator):: Indirect
4485: @end menu
4486:
4487: @node Unary +
4488: @section Unary +
4489: @cindex operators, unary +
4490:
4491: Forces a number to positive, whether positive or negative. Also forces numeric coercion of strings.
4492:
4493: @node Unary -
4494: @section Unary -
4495: @cindex operators, unary -
4496:
1.28 snw 4497: Forces a number to negative, whether positive or negative. Also forces numeric coercion of strings.
4498:
1.1 snw 4499: @node +
4500: @section + (Add)
4501: @cindex operators, +
4502:
1.28 snw 4503: @emph{Syntax}
4504:
4505: @example
4506: S X=1+2 ; => 3
4507: @end example
4508:
4509: Adds numbers together.
4510:
1.1 snw 4511: @node +=
4512: @section += (Add/Assign)
4513: @cindex operators, +=
4514:
1.28 snw 4515: @emph{Syntax}
4516:
4517: @example
4518: S X=5
4519: S X+=3 ; => 8
4520: @end example
4521:
4522: Increments the variable on the LHS by the value on the RHS.
4523:
1.1 snw 4524: @node ++
4525: @section ++ (Postfix Increment)
4526: @cindex operators, ++
4527:
1.28 snw 4528: Increments a variable by 1.
4529:
1.1 snw 4530: @node -
4531: @section - (Subtract)
4532: @cindex operators, -
4533:
1.28 snw 4534: Subtracts one number from another.
4535:
1.1 snw 4536: @node -=
4537: @section -= (Subtract/Assign)
4538: @cindex operators, -=
4539:
1.28 snw 4540: @emph{Syntax}
4541:
4542: @example
4543: S X=5
4544: S X-=3 ; => 2
4545: @end example
4546:
4547: Decrements the variable on the LHS by the value on the RHS.
4548:
1.1 snw 4549: @node --
4550: @section -- (Postfix Decrement)
4551: @cindex operators, --
4552:
1.28 snw 4553: Decrements the variable by one.
4554:
1.1 snw 4555: @node *
4556: @section * (Multiply)
4557: @cindex operators, *
4558:
1.28 snw 4559: Multiplies one number by another.
4560:
1.1 snw 4561: @node *=
4562: @section *= (Multiply/Assign)
4563: @cindex operators, *=
4564:
1.28 snw 4565:
4566:
1.1 snw 4567: @node /
4568: @section / (Divide)
4569: @cindex operators, /
4570:
4571: @node /=
4572: @section /= (Divide/Assign)
4573: @cindex operators, /=
4574:
4575: @node \
4576: @section \ (Integer Divide)
4577: @cindex operators, \
4578:
4579: @node \=
4580: @section \= (Integer Divide/Assign)
4581: @cindex operators, \=
4582:
4583: @node #
4584: @section # (Modulo)
4585: @cindex operators, #
4586:
4587: @node #=
4588: @section #= (Modulo/Assign)
4589: @cindex operators, #=
4590:
4591: @node **
4592: @section ** (Exponentiate)
4593: @cindex operators, **
4594:
4595: @node **=
4596: @section **= (Exponentiate/Assign)
4597: @cindex operators, **=
4598:
4599: @node <
4600: @section < (Less Than)
4601: @cindex operators, <
4602:
4603: @node <=
4604: @section <= (Less Than or Equal To)
4605: @cindex operators, <=
4606:
4607: @node >
4608: @section > (Greater Than)
4609: @cindex operators, >
4610:
4611: @node >=
4612: @section >= (Greater Than or Equal To)
4613: @cindex operators, >=
4614:
4615: @node _
4616: @section _ (Concatenate)
4617: @cindex operators, _
4618:
4619: @node _=
4620: @section _= (Concatenate/Assign)
4621: @cindex operators, _=
4622:
4623: @node =
4624: @section = (Equals)
4625: @cindex operators, =
4626:
4627: @node [
4628: @section [ (Contains)
4629: @cindex operators, [
4630:
4631: @node ]
4632: @section ] (Follows)
4633: @cindex operators, ]
4634:
4635: @node ]]
4636: @section ]] (Sorts After)
4637: @cindex operators, ]]
4638:
4639: @node ?
4640: @section ? (Pattern Match)
4641: @cindex operators, ?
4642:
4643: @node &
4644: @section & (Logical AND)
4645: @cindex operators, &
4646:
4647: @node ! (Operator)
4648: @section ! (Logical OR)
4649: @cindex operators, !
4650:
4651: @node '
4652: @section ' (Logical NOT)
4653: @cindex operators, '
4654:
4655: @node @@ (Operator)
4656: @section @@ (Indirect)
4657: @cindex operators, @@
4658:
4659: @node Routines
4660: @chapter Routines
4661: @cindex routines
4662:
4663: A @emph{routine} is a file containing M source code to be processed by FreeM.
4664:
4665: Routines exist within a @emph{namespace} (such as @code{SYSTEM} or @code{USER}), which in turn exist within an @emph{environment} (such as @code{DEFAULT}).
4666:
4667: @menu
4668: * Routine Naming:: Requirements and conventions for routine names.
4669: @end menu
4670:
4671:
4672: @node Routine Naming
4673: @section Routine Naming
4674: The routine's filename follows the format @code{NAME.m}, where @code{NAME} is the name of the routine, and @code{.m} is the filename extension.
4675:
4676: Routine naming rules are as follows:
4677:
4678: @itemize @bullet
4679: @item Routine names must begin with an upper- or lower-case letter, or a @code{%} sign
4680: @item Within the routine name, you may have upper-case or lower-case letters or digits
4681: @item The entire routine name must not be longer than 255 characters
4682: @end itemize
4683:
4684: Routines whose names begin with @code{%} must be located in the @code{SYSTEM} namespace. Other routines may be located in any namespace.
4685:
4686: @node Types
4687: @chapter Types
4688: @cindex types
4689: @cindex data types
4690:
4691: FreeM supports all @emph{libdatatype} types defined in the former MDC's @emph{Millennium Draft Standard}, with the exception of @code{MATRIX}, and with extensions supporting object-oriented programming. A notable enhancement in FreeM is that the library data types can be used in the @emph{formallist} of any extrinsic function or subroutine; not only in @emph{libraryelement}s.
4692:
4693: @menu
4694: * BOOLEAN:: Truth values.
4695: * COMPLEX:: Numbers with real and imaginary parts.
4696: * INTEGER:: Numbers with no decimal part.
4697: * REAL:: Numbers with a decimal part.
4698: * STRING:: Arbitrary strings of characters.
4699: * Custom Types (Classes):: User-defined, object-oriented types.
4700: @end menu
4701:
4702: @node BOOLEAN
4703: @section BOOLEAN
4704: @cindex data types, BOOLEAN
4705: @cindex types, BOOLEAN
4706:
4707: The @code{BOOLEAN} type represents any M value that can be interpreted as a truth-value.
4708:
4709: @node COMPLEX
4710: @section COMPLEX
4711: @cindex data types, COMPLEX
4712: @cindex types, COMPLEX
4713:
4714: The @code{COMPLEX} type is a complex number represented as a string in the format @code{@emph{<real-part>}%@emph{<imaginary-part>}}, where @emph{real-part} and @emph{imaginary-part} are both @code{REAL} numbers. See @ref{REAL} for more information.
4715:
4716: FreeM will attempt to interpret any @code{COMPLEX} value according to the usual rules for M canonical numbers, i.e., the string @code{sabc123.345%fbd3.1} would be interpreted as a complex number with the real part being @code{123.345} and the imaginary part being @code{3.1}.
4717:
4718: @node INTEGER
4719: @section INTEGER
4720: @cindex data types, INTEGER
4721: @cindex types, INTEGER
4722:
4723: An @code{INTEGER} is an interpretation of numeric data with any fractional part removed.
4724:
4725: @node REAL
4726: @section REAL
4727: @cindex data types, REAL
4728: @cindex types, REAL
4729:
1.29 snw 4730: A @code{REAL} is a numeric interpretation of data including a fractional part.
4731:
1.1 snw 4732: @node STRING
4733: @section STRING
4734: @cindex data types, STRING
4735: @cindex types, STRING
4736:
1.36 snw 4737: The @code{STRING} is the fundamental FreeM data type. Other types are inferred from the context of their usage.
4738:
4739: @subsection String Rules
4740:
4741: The following rules apply to all FreeM strings:
4742:
4743: @itemize
4744: @item Must not exceed 255 characters
4745: @item Must not contain @code{$C(0)}, @code{$C(201)}, or @code{$C(202)}
4746: @end itemize
4747:
4748: @subsection String Quoting Rules
4749: Strings in FreeM must be surrounded in double quotes:
4750:
4751: @example
4752: SET MYSTRING="This is a string literal"
4753: @end example
4754:
4755: If you want to include double quotes inside of a string, simply double them:
4756:
4757: @example
4758: SET MYSTRING="This is a ""string literal"" with embedded double quotes"
4759: @end example
4760:
1.29 snw 4761:
1.1 snw 4762: @node Custom Types (Classes)
4763: @section Custom Types (Classes)
4764: @cindex data types, custom
4765: @cindex types, custom
4766: @cindex classes
4767:
1.44 snw 4768: See @ref{Object-Oriented Programming}.
1.1 snw 4769:
4770: @node Globals
4771: @chapter Globals
4772: @cindex globals
4773: @cindex variables, global
4774: @cindex data
4775:
1.33 snw 4776: @menu
4777: * Globals Overview:: Basics of FreeM persistent storage.
4778: * Creating Globals:: How to create globals.
4779: * Removing Globals:: How to remove globals.
4780: * Global Storage:: How globals are stored.
4781: @end menu
4782:
4783: @node Globals Overview
4784: @section Globals Overview
4785:
1.31 snw 4786: FreeM supports typical M globals, which are often described as persistent, hierachical sparse arrays. Globals make it relatively simple to include persistent data in an application without requiring the developer to use an external database management system, and offer syntax and semantics so similar to M local variables and structured system variables that moving from one to the other is seamless.
4787:
4788: Each global comprises three elements:
4789:
4790: @itemize @bullet
4791: @item
4792: An alphabetic name beginning with a caret (@code{^}) or a caret and a percent sign (@code{^%})
4793: @item
4794: Optionally, one or more comma-delimited subscripts, enclosed in parentheses
4795: @item
4796: A value of up to 255 characters in length
4797: @end itemize
4798:
1.36 snw 4799: A leading percent sign in the global name will force the named global into the @code{SYSTEM} namespace of the current FreeM environment.
1.31 snw 4800:
4801: @node Creating Globals
4802: @section Creating Globals
4803: @cindex globals, creating
4804:
4805: To create a global, you can use the @code{SET} command:
4806:
4807: @example
4808: SET ^MYGLOBAL("foo","bar")="this is the data value"
4809: @end example
4810:
4811: @node Removing Globals
4812: @section Removing Globals
4813: @cindex globals, removing
4814:
4815: To remove an entire global, you can use the @code{KILL} command with the unsubscripted name of the global:
4816:
4817: @example
4818: KILL ^MYGLOBAL
4819: @end example
4820:
4821: If you only want to remove part of a global, i.e., beginning at a certain subscript level, use the @code{KILL} command with a subscripted name:
4822:
4823: @example
4824: KILL ^MYGLOBAL("foo")
4825: @end example
4826:
4827: This will remove only the @code{"foo"} subscript and all of its children.
4828:
4829: If you only want to remove the data value at a specific subscript level, leaving the subscript itself intact, use @code{KVALUE}:
4830:
4831: @example
4832: KVALUE ^MYGLOBAL("foo")
4833: @end example
4834:
4835: @node Global Storage
4836: @section Global Storage
4837: @cindex globals, storage
4838:
4839: FreeM globals are stored in @code{$PREFIX/var/freem/@emph{<environment-name>}/@emph{<namespace-name>}/globals} in a binary format.
4840:
4841: Global files have a header of the following format:
4842:
4843: @verbatim
4844: typedef struct global_header {
4845:
4846: char magic[5]; /* FRMGL */
4847: int format_version;
4848: char host_triplet[40];
4849: char host_id[256];
4850:
4851: unsigned long block_size;
4852: unsigned long last_transaction_id;
4853:
4854: long created;
4855: long last_backup;
4856:
4857: } global_header;
4858: @end verbatim
4859:
1.1 snw 4860: @node Concurrency Control
4861: @chapter Concurrency Control
4862: @cindex concurrency control
4863: @cindex locking
4864: @cindex transaction processing
4865:
1.33 snw 4866: @menu
4867: * Concurrency Control Overview:: Basics of concurrency control.
4868: * Advisory Locks:: Coordinating access voluntarily.
4869: * Transaction Processing:: Ensuring logical consistency.
4870: @end menu
4871:
4872: @node Concurrency Control Overview
4873: @section Concurrency Control Overview
4874:
1.34 snw 4875: Multitasking, multi-user FreeM applications must concern themselves with conscientious management of concurrent access to globals in order to maintain logical consistency and prevent concurrent reads and writes from conflicting with each other.
1.31 snw 4876:
1.34 snw 4877: In FreeM, there are two mechanisms provided for managing concurrent global access: @emph{advisory locks}, and @emph{transaction processing}.
4878:
4879: Advisory locks allow applications to voluntarily coordinate concurrent access to globals with the @code{LOCK} command, and require each application to check the @code{LOCK} status prior to accessing a global.
4880:
4881: Transaction processing allows applications to delineate sets of global operations (sets, kills, etc.) as being part of a transaction, in which no operations are performed against the globals contained within the transaction until the transaction is committed. In addition, processes other than the one running the transaction will be forced to wait to access globals for either the duration of the commit phase (@emph{batch mode}), or for the entire duration of the transaction (@emph{serial mode}).
1.31 snw 4882:
1.33 snw 4883: @node Advisory Locks
4884: @section Advisory Locks
4885:
1.31 snw 4886: @node Transaction Processing
4887: @section Transaction Processing
4888: @cindex transaction processing
4889:
1.39 snw 4890: FreeM implements a significant subset of the transaction processing features from @emph{ANSI X11.1-1995}. This allows a series of global operations to be conducted all at once, either in batch mode (where concurrent operation is not interrupted until the last possible moment), or in serial mode (where writes are guaranteed to be atomic, consistent, isolated, and durable).
1.31 snw 4891:
4892: @subsection Theory of Operation
4893:
4894: FreeM uses a pessimistic concurrency control mechanism for @code{SERIAL} transactions, meaning that any @code{TSTART} command that includes the @code{SERIAL} transaction parameter will cause the process to acquire the transaction processing mutex, which prevents any process but the one holding the mutex from performing any data access (read or write) until either @code{TCOMMIT} or @code{TROLLBACK} is called, either committing or rolling back the transaction, respectively.
4895:
4896: Any transaction in between its @code{TSTART} and @code{TCOMMIT}/@code{TROLLBACK} is said to be @emph{in-flight}. During the in-flight stage, pending global operations are held only in memory and after-image journals.
4897:
4898: FreeM maintains a list of all globals affected during a transaction in-flight. When a @code{TCOMMIT} is reached, FreeM will generate a @emph{checkpoint} of each global data file to be changed by the transaction. These checkpoints allow all FreeM globals to be restored to their pre-transaction state if a @code{TCOMMIT} should fail part of the way through its operation.
4899:
4900: Checkpoints can have one of two modes:
4901:
4902: @table @asis
4903:
4904: @item @code{CP_REMOVE}
4905: Used for globals that did not exist prior to the beginning of this transaction. Simply marks the entire global data file for deletion in case of @code{TCOMMIT} failure.
4906:
4907: @item @code{CP_RESTORE}
4908: Used for globals that @emph{did} exist prior to the beginning of this transaction. In this case, the entire global data file is copied to a new file with a @code{.chk} extension. In cases of @code{TCOMMIT} failure, @code{CP_RESTORE} checkpoint files will be restored over the partially-modified live data file.
4909:
4910: @end table
4911:
4912: The below example shows a few global operations and checkpoints for a transaction in-flight using the @code{trantab} direct-mode command:
4913:
4914: @verbatim
4915: TL1:DEFAULT.USER> trantab
4916: $TLEVEL 1*
4917: Operations for Transaction ID: 6ea14aad-b8f1-47f9-9f52-4f513f892bc0 [RESTARTABLE SERIAL]
4918:
4919: OP. NO. ACTION KEY/DATA
4920: ------- ------ --------
4921: 1 SET ^FOO=3
4922: 2 KILL ^FOO
4923: 3 SET ^snw=10
4924: 4 SET ^BRANDNEW=6
4925:
4926: Global checkpoints:
4927:
4928: GLOBAL MODE FILES
4929: ------ ---- -----
4930: ^BRANDNEW CP_REMOVE IN: /usr/local/var/freem/USER/globals/^BRANDNEW
4931: ^snw CP_RESTORE IN: /usr/local/var/freem/USER/globals/^snw
4932: OUT: /usr/local/var/freem/USER/globals/^snw.23390.1.chk
4933: ^FOO CP_RESTORE IN: /usr/local/var/freem/USER/globals/^FOO
4934: OUT: /usr/local/var/freem/USER/globals/^FOO.23390.1.chk
4935: @end verbatim
4936:
4937: In the above example, @code{IN} files are the live data file that will be overwritten or removed, and @code{OUT} files are the checkpoints themselves. Note that @code{OUT} files are only used for @code{CP_RESTORE} checkpoints.
4938:
4939: @subsection Using Transaction Processing
4940:
4941: To use transactions in FreeM, you need to be familiar with three commands:
4942:
4943: @itemize @bullet
4944: @item
4945: @code{TSTART}
4946: @item
4947: @code{TCOMMIT}
4948: @item
4949: @code{TROLLBACK}
4950: @end itemize
4951:
4952: With transaction processing, global variable operations occurring between @code{TSTART} and @code{TCOMMIT} commands will be contained within the transaction.
4953:
4954: The atomicity, consistency, isolation, and durability facets of FreeM transaction hinge on the transaction mode.
4955:
4956: @subsubsection BATCH Transactions
4957: @code{BATCH} transactions offer higher performance, and allow other applications aside from the one doing the transaction to continue normal operations until the transaction is committed with @code{TCOMMIT}. In batch mode, other processes are only locked out of normal operation during the commit phase of the transaction.
4958:
4959: The effect of this is that the operations within the batch transaction will not be interleaved with global writes from other applications, but the entire lifetime of the transaction is not guaranteed to be serialized with respect to the transaction processing activities of other running applications in the environment.
4960:
4961: @subsubsection SERIAL Transactions
4962: @code{SERIAL} transactions offer full ACID compliance at the expense of multiprocessing performance. In serial mode, a @code{TSTART} blocks all activity from all other FreeM processes in the environment, and this blocking effect is not released until the transaction is committed with @code{TCOMMIT} or rolled back with @code{TROLLBACK} (or due to abnormal conditions in the environment that preclude the successful completion of the transaction).
4963:
1.1 snw 4964: @node Local Variables
4965: @chapter Local Variables
4966: @cindex variables, local
4967: @cindex local variables
4968:
1.41 snw 4969: @menu
4970: * Local Variables Overview:: The basics of locals.
4971: * Creating Local Variables:: Creating locals with SET.
4972: * Removing Local Variables:: Removing locals with KILL.
4973: @end menu
4974:
4975: @node Local Variables Overview
1.38 snw 4976: @section Local Variables Overview
4977:
4978: FreeM @emph{local variables} have the same data structure as global variables, but are scoped to a single FreeM process, and stored in memory.
4979:
4980: Each local comprises three elements:
4981:
4982: @itemize @bullet
4983: @item
4984: An alphabetic name beginning with a letter or a percent sign (@code{%})
4985: @item
4986: Optionally, one or more comma-delimited subscripts, enclosed in parentheses
4987: @item
4988: A value of up to 255 characters in length
4989: @end itemize
4990:
4991: @node Creating Local Variables
4992: @section Creating Local Variables
4993: @cindex local variables, creating
4994:
4995: To create a local variable, use the @code{SET} command:
4996:
4997: @example
4998: SET MYLOCAL("foo","bar")="this is the data value"
4999: @end example
5000:
5001: @node Removing Local Variables
5002: @section Removing Local Variables
5003: @cindex local variables, removing
5004:
5005: To remove an entire local variable, you can use the @code{KILL} command with the unsubscripted name of the variable:
5006:
5007: @example
5008: KILL MYLOCAL
5009: @end example
5010:
5011: If you only want to remove part of a local variable, i.e., beginning at a certain subscript level, use the @code{KILL} command with a subscripted name:
5012:
5013: @example
5014: KILL MYLOCAL("foo")
5015: @end example
5016:
5017: This will remove only the @code{"foo"} subscript and all of its children.
5018:
5019: If you only want to remove the data value at a specific subscript level, leaving the subscript itself intact, use @code{KVALUE}:
5020:
5021: @example
5022: KVALUE MYLOCAL("foo")
5023: @end example
5024:
1.1 snw 5025: @node Scoping
5026: @chapter Scoping
5027: @cindex scoping
5028:
1.38 snw 5029: By default, FreeM local variables and their values are scoped to the entire process, meaning that any function or subroutine can access and modify their values. This can lead to pernicious bugs.
5030:
5031: M provides the @code{NEW} command to work around these issues. When @code{NEW} is called with a local variable as its argument, FreeM will scope the variable to the process stack frame in which the @code{NEW} command occured. When exiting the stack frame (i.e. with the @code{QUIT} command), FreeM will restore the variable to its value prior to being @code{NEW}ed.
5032:
1.39 snw 5033: @emph{Example}
5034:
5035: @example
5036: MYRTN ;
5037: S J=1 ; set local variable J to 1
5038: W J,! ; this will output "1"
5039: D X ; execute subroutine X
5040: W J,! ; this will output "1", as the value of J was restored
5041: Q
5042: ;;
5043: X ;
5044: N J ; stack J
5045: S J=6 ; set its value to 6
5046: W J,! ; this will output "6"
5047: Q ; quit from the subroutine, destroying its stack frame
5048: ;;
5049: @end example
5050:
5051: @section Scoping Considerations for $TEST
5052:
5053: In M, the truth value of comparisons, logic operations, and certain forms of @code{LOCK} is stored in the @code{$TEST} intrinsic special variable, which follows the same rules as any M local variable.
5054:
5055: This is probably the most significant design flaw of the language, as the side effects of logic on @code{$TEST} lead to incredibly difficult bugs. However, M allows @code{$TEST} to be @code{NEW}ed, and FreeM provides the @code{THEN} command@footnote{From MDC Type A extension X11/1998-31} to help in the case of conditionals. @code{THEN} stacks @code{$TEST} to the end of the line.
5056:
5057: When writing new M code in FreeM, we strongly suggest using @code{THEN} as follows:
5058:
5059: @example
5060: MYRTN ;
5061: IF MYVAR=1 THEN DO SUBRT
5062: @end example
5063:
5064: This is instead of the traditional form:
5065:
5066: @example
5067: MYRTN ;
5068: IF MYVAR=1 DO SUBR
5069: @end example
5070:
5071: @cartouche
5072: @quotation
1.40 snw 5073: @emph{Style Recommendation}
1.39 snw 5074:
5075: Note that @code{THEN} is not in any currently published version of the @emph{Standard}, but is part of MDC Type A extension X11/1998-31. However, we recommend using @code{THEN} instead of favoring portability, as there is no defensible reason for this incredibly simple feature @emph{not} to be ubiquitous.
5076:
5077: If you use other M implementations, you should bug the implementers to implement @code{THEN}, as it at least partially mitigates an inexcusable flaw in the design of M.
5078: @end quotation
5079: @end cartouche
5080:
1.1 snw 5081: @node Decision Constructs
5082: @chapter Decision Constructs
5083: @cindex decision constructs
5084: @cindex IF
5085: @cindex ELSE
5086: @cindex THEN
5087: @cindex postconditionals
5088:
5089: @node Branch Constructs
5090: @chapter Branch Constructs
5091: @cindex branch constructs
5092: @cindex DO
5093: @cindex GOTO
5094: @cindex JOB
5095:
5096: @node Loop Constructs
5097: @chapter Loop Constructs
5098: @cindex loop constructs
5099: @cindex FOR
5100:
5101: @node Modular Programming
5102: @chapter Modular Programming
5103: @cindex modular programming
5104: @cindex functions, extrinsic
5105: @cindex subroutines
5106:
1.2 snw 5107: @menu
5108: * Subroutines:: Making sections of code reusable.
5109: * Extrinsic Functions:: Reusable code that returns a value.
5110: @end menu
5111:
1.1 snw 5112: @node Subroutines
5113: @section Subroutines
5114:
5115: @node Extrinsic Functions
5116: @section Extrinsic Functions
5117:
5118: @node Object-Oriented Programming
5119: @chapter Object-Oriented Programming
5120: @cindex object-oriented programming
5121: @cindex programming, object-oriented
5122:
1.45 snw 5123: @menu
5124: * Classes:: The organizing concept of object-oriented programming.
5125: * Inheritance:: Making one class derive from another.
5126: * Methods:: Attach code to classes.
5127: * Public and Private Variables:: Determining accessibility.
5128: * Instantiating Objects:: Creating instances of classes.
5129: @end menu
1.2 snw 5130:
1.45 snw 5131: @node Classes
1.1 snw 5132: @section Classes
1.33 snw 5133: @subsection Class Overview
5134:
1.29 snw 5135: A @emph{class} is the primary organizing concept of FreeM support for object-oriented programming, and in FreeM, is simply an M routine with a few special properties:
5136:
5137: @example
5138: MYCLASS(THIS,INIT):OBJECT ; Constructor for MYCLASS, inherits OBJECT
5139: ; two private variables
5140: S THIS("NUMERATOR"):PRIVATE=$P(INIT,"/",1)
5141: S THIS("DENOMINATOR"):PRIVATE=$P(INIT,"/",2)
5142: Q
5143: ;
5144: DESTROY(THIS) ; This is the destructor
5145: Q
5146: @end example
5147:
5148: The above example demonstrates general class syntax.
5149:
5150: @subsection Constructors
5151:
5152: A @emph{constructor} is an M entry point that is called when a new instance of a class is created.
5153:
5154: A constructor must be the first entry point in a class routine, its tag must match the class/routine name, and it must take two arguments, @code{THIS} and @code{INIT}.
5155:
5156: @code{THIS} represents the instance of the object being accessed, and @code{INIT} represents an initializer that can be used to assign an initial value to the object when instantiating the class.
5157:
5158: A constructor looks like this:
5159:
5160: @example
5161: %FRACTION(THIS,INIT):OBJECT ;
5162: S THIS("NUMERATOR"):PRIVATE=$P(INIT,"/",1)
5163: S THIS("DENOMINATOR"):PRIVATE=$P(INIT,"/",2)
5164: Q
5165: @end example
5166:
5167: @emph{Syntax}
5168: @example
5169: @emph{<class-name>}(THIS,INIT)[:@emph{<superclass>}]
5170: @end example
5171:
5172: In the above example, @emph{<superclass>} represents the name of a class from which this class should inherit. In this case, the @code{FRACTION} class inherits from the @code{OBJECT} class. Note that this is not strictly necessary in this case, as all classes in FreeM automatically inherit from @code{OBJECT}.
5173:
5174: @subsection Destructors
5175: A @code{destructor} is called when you @code{KILL} an instance variable. Its tag must be @code{DESTROY}, and it must take one argument (@code{THIS}).
5176:
5177: The destructor should be used to clean up any resources used by class methods.
5178:
5179: A destructor looks like this:
5180:
5181: @example
5182: DESTROY(THIS) ;
5183: ; free any resources that should be freed at the end of the object's lifetime
5184: Q
5185: @end example
1.2 snw 5186:
1.45 snw 5187: @node Inheritance
1.29 snw 5188: @section Inheritance
5189:
5190: Every class you create will automatically inherit the methods and functionality of the @code{OBJECT} class, supplied with FreeM.
5191:
5192: When attempting to call a method, FreeM will first search the class routine for a matching entry point, and then follow the inheritance chain upwards until a matching entry point is found. If the final class in the chain does not have a matching entry point, FreeM will try to find a matching entry point in the @code{OBJECT} class.
5193:
5194: Inheritance is achieved by specifying the name of the superclass in the constructor:
5195:
5196: @example
5197: CLASS(THIS,INIT):SUPERCLASS
5198: @end example
5199:
5200: @subsection Runtime Polymorphism
5201:
5202: You can achieve runtime polymorphism by subclassing, and defining methods in the subclass that match the names of existing methods in the superclass. Following FreeM inheritance rules, the overridden method in the subclass will be called, and the method in the superclass will not.
5203:
5204: Note that the overridden method in the subclass can take a different set or number of arguments than the @emph{formallist} of the superclass method would specify.
1.1 snw 5205:
1.45 snw 5206: @node Methods
1.29 snw 5207: @section Methods
5208: Class methods are defined as tags with @emph{formallist}s in a class routine, and per the typical FreeM object pattern, must take at least one argument, being @code{THIS} (representing a reference to the object instance being accessed).
1.1 snw 5209:
1.29 snw 5210: The following class (@code{MYCLASS}) has a constructor, a destructor, and a method called @code{MYMETHOD}:
5211:
5212: @example
5213: %MYCLASS(THIS,INIT) ;
5214: Q THIS
5215: DESTROY(THIS) ;
5216: Q
5217: MYMETHOD(THIS) ;
5218: Q "VALUE"
5219: @end example
5220:
1.31 snw 5221: The dot operator is used to invoke class methods:
5222:
5223: @example
5224: DEFAULT.USER> N MYOBJ=$#^%MYCLASS("")
5225: DEFAULT.USER> W MYOBJ.MYMETHOD()
5226: VALUE
5227: @end example
5228:
1.45 snw 5229: @node Public and Private Variables
1.29 snw 5230: @section Public and Private Variables
5231:
1.30 snw 5232: FreeM supports private fields with the @code{:PRIVATE} specifier in the @code{SET} command, enforcing classical object-oriented data encapsulation. The @code{:PUBLIC} specifier is provided for completeness, and is the default.
1.29 snw 5233:
5234: The below constructor for a @code{FRACTION} class defines two private fields:
5235:
5236: @example
5237: %FRACTION(THIS,INIT):OBJECT ;
5238: S THIS("NUMERATOR"):PRIVATE=$P(INIT,"/",1)
5239: S THIS("DENOMINATOR"):PRIVATE=$P(INIT,"/",2)
5240: Q
5241: @end example
5242:
5243: Either of the following commands will create a public field:
5244:
5245: @example
5246: S THIS("VARNAM")="Initial Value"
5247: S THIS("VARNAM"):PUBLIC="Initial Value"
5248: @end example
1.1 snw 5249:
1.29 snw 5250: Attempting to access private fields from outside of the class will raise error condition @code{ZOBJFLDACCV}.
1.1 snw 5251:
1.45 snw 5252: @node Instantiating Objects
1.31 snw 5253: @section Instantiating Objects
5254:
5255: To instantiate an object (i.e., create an object from a certain class), you will use the @code{NEW} command as follows:
5256:
5257: @example
5258: NEW MYSTR=$#^%STRING("myString")
5259: @end example
5260:
5261: This will create a local variable called MYSTR of type STRING, and initialize it with the value myString.
5262:
1.45 snw 5263: @subsection Determining Object Class
1.31 snw 5264:
5265: To determine the class of any FreeM local variable, you will use the @code{$$TYPE()} method:
5266:
5267: @example
5268: USER> W MYSTR.$$TYPE()
5269: ^%STRING
5270: @end example
5271:
5272: The @code{$$TYPE()} method is a member of the @code{OBJECT} class.
5273:
1.1 snw 5274: @node Libraries
5275: @chapter Libraries
5276: @cindex libraries
5277:
5278: @node Sequential I/O
5279: @chapter Sequential I/O
5280:
5281: @node Network I/O
5282: @chapter Network I/O
5283: @cindex networks, input and output
5284:
5285: 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.
5286:
5287: @section Opening and Connecting a Client Socket
5288: @cindex networks, opening and connecting client sockets
5289:
5290: To open a client socket and connect to it, you will need to call the @code{OPEN} command and the @code{USE} command:
5291:
5292: @example
5293: ;
5294: ; Set socket read terminator to LF
5295: ;
5296: SET ^$DEVICE(100,"OPTIONS","TERMINATOR")=$C(10)
5297: ;
5298: ; Open an IPv4 TCP socket to mail.mydomain.com on port 25 (SMTP)
5299: ; and connect to it
5300: ;
5301: OPEN 100:"mail.mydomain.com:25:IPV4:TCP"
5302: USE 100:/CONNECT
5303: ;
5304: ; Read a line of input from the remote host and write it to the terminal
5305: ;
5306: NEW LINE
5307: READ LINE
5308: USE 0
5309: WRITE LINE,!
5310: ;
5311: ; CLOSE the socket and disconnect
5312: ;
5313: CLOSE 100
5314: QUIT
5315: @end example
5316:
5317: @node Extended Global References
5318: @chapter Extended Global References
5319: @cindex global references, extended
5320: @cindex extended global references
5321:
5322: @section Standard Extended Global References
5323: @cindex extended global references, standard
5324:
5325: FreeM supports extended global references, allowing the user to access globals in namespaces other than the current default namespace and the @code{SYSTEM} namespace, without switching to the other namespace.
5326:
5327: For example, if you are in the @code{USER} namespace, the following code will print the value of @code{^VA(200,0)} in the @code{VISTA} namespace:
5328:
5329: @example
5330: WRITE ^|"VISTA"|VA(200,0),!
5331: @end example
5332:
5333: You may also use an expression that resolves to a string containing a valid namespace name:
5334:
5335: @example
5336: SET NS="VISTA"
5337: WRITE ^|NS|VA(200,0),!
5338: @end example
5339:
5340: @node Global Aliasing
5341: @chapter Global Aliasing
5342: @cindex aliasing, global
5343: @cindex globals, aliasing
5344:
5345: FreeM provides the ability to set alternative names for M global variables.
5346:
5347: To create an alias of @code{^FOO} named @code{^BAR}, use the following command:
5348:
5349: @example
5350: SET ^$JOB($JOB,"ALIASES","^BAR")="^FOO"
5351: @end example
5352:
5353: If such an alias is set, any reference to global variable @code{^BAR} will affect @code{^FOO} instead of @code{^BAR} until @code{^$JOB($JOB,"ALIASES","^BAR")} is @code{KILL}ed. If @code{^BAR} existed prior to the definition of this alias, its data will be unavailable to and unaffected by application code.
5354:
5355: @node Global Mappings
5356: @chapter Global Mappings
5357: @cindex mappings, global
5358: @cindex globals, mapping
5359:
5360: FreeM supports creating persistent mappings through which arbitrary global names may be mapped to specific namespaces. This allows non-@code{%} globals to be stored in the @code{SYSTEM} namespace, or @code{%} globals to be stored in non-@code{SYSTEM} namespaces.
5361:
5362: To map the @code{^FOO} global to the @code{SYSTEM} namespace, any of the following will work:
5363:
5364: @example
5365: MAP GLOBAL ^FOO="SYSTEM"
5366: SET ^$GLOBAL("FOO","NAMESPACE")="SYSTEM"
5367: SET ^$SYSTEM("MAPPINGS","GLOBAL","^FOO")="SYSTEM"
5368: @end example
5369:
5370: There is no functional difference in any of the three approaches; the method you choose is a matter of personal preference.
5371:
5372: To remove the above mapping, any of the following examples will also work:
5373:
5374: @example
5375: UNMAP GLOBAL ^FOO
5376: KILL ^$GLOBAL("FOO","NAMESPACE")
5377: KILL ^$SYSTEM("MAPPINGS","GLOBAL","^FOO")
5378: @end example
5379:
5380:
5381:
5382: @node Asynchronous Event Handling
5383: @chapter Asynchronous Event Handling
5384: @cindex event handling, asynchronous
5385:
5386: Asynchronous event handling in FreeM follows the specifications of the unpublished MDC @emph{Millennium Draft Standard}.
5387:
5388: @section Setting Up Async Event Handlers
5389:
5390: Asynchronous event handlers are configured through the @code{^$JOB} structured system variable for job-specific events, and the @code{^$SYSTEM} structured system variable for system-wide events. In order to become proficient in writing asynchronous event handling code, you need to be aware of several important concepts:
5391:
5392: @table @emph
5393:
5394: @item Event Classes
5395: @emph{Event classes} denote particular categories of events. These include @code{COMM}, @code{HALT}, @code{IPC}, @code{INTERRUPT}, @code{POWER}, @code{TIMER}, @code{TRIGGER}, and @code{USER} event classes. At present, only @code{INTERRUPT} and @code{TRIGGER} event classes are supported.
5396:
5397: @item Event Identifiers
5398: @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}).
5399:
5400: @item Event Handlers
5401: @emph{Event handlers} are M routines or subroutines that can be registered to run when an event of a certain event class occurs.
5402:
5403: @item Event Registration
5404: @emph{Event registration} is the process of modifying the @code{^$JOB} or @code{^$SYSTEM} SSVN to associate a particular event class and event identifier with an event handler routine or subroutine.
5405:
5406: @item Event Blocking and Unblocking
5407: @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.
5408:
5409: @end table
5410:
5411: The following sections of this chapter will take you step-by-step through setting up an event handler for @code{SIGWINCH} signal handling.
5412:
5413: @section Registering an Asynchronous Event Handler
5414: @cindex event handlers, registration
5415:
5416: To register a job-specific event handler that will only execute in the current FreeM process, use the following syntax:
5417:
5418: @example
5419: SET ^$JOB($JOB,"EVENT",@emph{event-class},@emph{event-identifier})=@emph{entryref}
5420: @end example
5421:
5422: To register a system-wide event handler that will execute in every FreeM process, use the following syntax:
5423:
5424: @example
5425: SET ^$SYSTEM("EVENT",@emph{event-class},@emph{event-identifier})=@emph{entryref}
5426: @end example
5427:
5428: For example, use the following to register @code{^RESIZE} as an asynchronous event handler for @code{SIGWINCH} events:
5429:
5430: @example
5431: SET ^$JOB($JOB,"EVENT","INTERRUPT","SIGWINCH")="^RESIZE"
5432: @end example
5433:
5434: 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}.
5435:
5436: @section Enabling Asynchronous Event Handling
5437: @cindex event handlers, enabling
5438:
5439: 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:
5440:
5441: @example
5442: ASTART "INTERRUPT"
5443: @end example
5444:
5445: 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.
5446:
5447: Once this is done, any event handlers registered for the @code{INTERRUPT} event class in @code{^$JOB} will be executed asynchronously as appropriate.
5448:
5449: Please note that @code{ASTART "TRIGGER"} is run implicitly at FreeM startup, to ensure consistency in applications depending on business logic contained in system-wide global triggers. To disable this behavior, add @code{ASTOP "TRIGGER"} to the @code{LOCAL.STARTUP} routine in the @code{USER} namespace. If @code{LOCAL.STARTUP} does not yet exist in your environment, you may create it by typing @code{fmadm edit routine USER LOCAL.STARTUP} from your UNIX command-line shell.
5450:
5451: @section Disabling Asynchronous Event Handling
5452: @cindex event handlers, disabling
5453:
5454: 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:
5455:
5456: @example
5457: ASTOP "INTERRUPT"
5458: @end example
5459:
5460: 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.
5461:
5462: You may also disable asynchronous event handling for a specific event identifier by @code{KILL}ing the appropriate node in the @code{^$JOB} SSVN, which unregisters the event handler altogether. The following example will unregister the event handler for the @code{SIGWINCH} event identifier:
5463:
5464: @example
5465: KILL ^$JOB($JOB,"EVENT","INTERRUPT","SIGWINCH")
5466: @end example
5467:
5468: @section Temporarily Blocking Asynchronous Event Handling
5469: @cindex event handlers, blocking
5470:
5471: 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.
5472:
5473: The following example blocks asynchronous event handling for the @code{INTERRUPT} event class:
5474:
5475: @example
5476: ABLOCK "INTERRUPT"
5477: @end example
5478:
5479: 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.
5480:
5481: Modifying M globals within event handlers is allowed but strongly discouraged, as doing so can lead to logical corruption of the data. 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.
5482:
5483: @node Global Triggers
5484: @chapter Global Triggers
5485: @cindex global triggers
5486: @cindex triggers
5487:
5488: Global triggers use the FreeM asynchronous event handling subsystem to allow a FreeM process to execute arbitrary M code when a particular action occurs on a particular global.
5489:
5490: To set up a global trigger, you must set up an event handler for event class @code{TRIGGER}. The event identifier must be in the format of @code{"<action>:<gvn>"}, where @emph{<gvn>} is a global variable name, and @emph{<action>} is one of the following:
5491:
5492: @table @asis
5493:
5494: @item @code{DATA}
5495: Trigger will fire when the @code{$DATA} intrinsic function is called on @emph{<gvn>}.
5496:
5497: @item @code{GET}
5498: Trigger will fire when @emph{<gvn>} is read from.
5499:
5500: @item @code{INCREMENT}
5501: Trigger will fire when intrinsic function @code{$INCREMENT} is called on @emph{<gvn>}.
5502:
5503: @item @code{KILL}
5504: Trigger will fire when @emph{<gvn>} is @code{KILL}ed.
5505:
5506: @item @code{NEXT}
5507: Trigger will fire when intrinsic function @code{$NEXT} is called on @emph{<gvn>}.
5508:
5509: @item @code{ORDER}
5510: Trigger will fire when intrinsic function @code{$ORDER} is called on @emph{<gvn>}.
5511:
5512: @item @code{QUERY}
5513: Trigger will fire when intrinsic function @code{$QUERY} is called on @emph{<gvn>}.
5514:
5515: @item @code{SET}
5516: Trigger will fire when @code{SET @emph{<gvn>}=@emph{value}} occurs.
5517:
5518: @item @code{ZDATA}
5519: Trigger will fire when intrinsic function @code{ZDATA} is called on @emph{<gvn>}.
5520:
5521: @end table
5522:
5523: When a @code{TRIGGER} event occurs, the @code{"GLOBAL"} node of the @code{^$EVENT} structured system variable will be populated with the global reference that invoked the trigger event.
5524:
5525: If a @code{SET} or @code{KILL} trigger was the source of the @code{TRIGGER} event, the @code{OLD_VALUE} node of @code{^$EVENT} will be populated with original value of @code{^$EVENT("GLOBAL")} prior to the change, and @code{NEW_VALUE} will be populated with the new value. This allows triggers to contain logic to undo global changes. This functionality can also be used to provide auditing of specific global changes.
5526:
5527: The following example shows a trigger implemented for @code{SET} operations on the @code{^DD} global.
5528:
5529: @example
5530: TRIGGER ;
5531: ;
5532: ; Set up a SET trigger on ^DD
5533: ;
5534: SET ^$JOB($JOB,"EVENT","TRIGGER","SET:^DD")="ONSET^TRIGGER"
5535: ;
5536: ; Enable the TRIGGER event class
5537: ;
5538: ASTART "TRIGGER"
5539: ;
5540: ; Try setting a node in ^DD
5541: ;
5542: SET ^DD(1)="Test"
5543: ;
5544: ; Quit
5545: ;
5546: QUIT
5547: ;
5548: ;
5549: ONSET ;
5550: WRITE "The "_^$EVENT("GLOBAL")_" global node was SET.",!
5551: QUIT
5552: @end example
5553:
5554: You can also set up a trigger that applies to all FreeM processes by setting descendant subscripts of @code{^$SYSTEM("EVENT","TRIGGER",...)} instead of using @code{^$JOB($JOB,"EVENT","TRIGGER",...)}.
5555:
5556: @node Synchronous Event Handling
5557: @chapter Synchronous Event Handling
5558:
5559: @node GUI Programming with MWAPI
5560: @chapter GUI Programming with MWAPI
5561:
5562: @node User-Defined Z Commands
5563: @chapter User-Defined Z Commands
5564:
5565: @node User-Defined Z Functions
5566: @chapter User-Defined Z Functions
5567:
5568: @cindex z functions, user-defined
5569:
5570: @node User-Defined SSVNs
5571: @chapter User-Defined SSVNs
5572:
5573: @cindex structured system variables, user-defined
5574: @cindex structured system variables
5575:
5576: @node Language Dialects
5577: @chapter Language Dialects
5578:
5579: @cindex language dialects
5580: @cindex dialects, language
5581:
5582:
5583: @node System Library Routines
5584: @chapter System Library Routines
5585: @cindex system library routines
5586:
5587: @section ^%ZCOLUMNS
5588: @cindex ^%ZCOLUMNS
5589: @cindex system library routines, ^%ZCOLUMNS
5590:
5591: This routine is the implementation of the @code{$ZCOLUMNS} intrinsic special variable.
5592:
1.28 snw 5593: @section %SYSINIT
5594: @cindex %SYSINIT
5595: @cindex system library routines, %SYSINIT
1.1 snw 5596:
5597: This routine is the default startup routine for FreeM running in direct mode.
5598:
5599: Running @code{DO INFO} from direct mode will use this routine to display information about the current FreeM status and namespace configuration.
5600:
5601: @section ^%ZHELP
5602: @cindex ^%ZHELP
5603: @cindex system library routines, ^%ZHELP
5604:
5605: 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}.
5606:
5607: @section ^%ZROWS
5608: @cindex ^%ZROWS
5609: @cindex system library routines, ^%ZROWS
5610:
5611: This routine is the implementation of the @code{$ZROWS} intrinsic special variable.
5612:
5613: @node Interrupt Handling
5614: @chapter Interrupt Handling
5615: @cindex interrupt handling
5616:
1.22 snw 5617: When FreeM receives the @code{SIGINT} signal, either by pressing @code{Ctrl-C} during program execution, or by external signal from the operating system, the FreeM environment daemon, or another external process, one of two things can happen, depending on the state of the @code{$ZI} special variable:
1.1 snw 5618:
5619: @table @asis
5620: @item @code{$ZI} evaluates @emph{true}
5621: In this case, the @code{ZINRPT} error is raised, and normal error handling procedures apply. If neither @code{$ZTRAP} nor @code{$ETRAP} are set, FreeM prints an error diagnostic on the home device and will exit the FreeM process in application mode (i.e., the @code{freem} executable was started with the @code{--routine} or @code{-r} flag), or return to the direct mode prompt otherwise.
5622:
5623: This is the default behavior of FreeM.
5624: @item @code{$ZI} evaluates @emph{false}
5625: In this case, no error is raised, but the @code{$ZCONTROLC} flag is set. In this mode of operation, it is up to program code to check for @code{$ZCONTROLC} and take appropriate action.
5626:
5627: Checking the value of @code{$ZCONTROLC} will reset it to @emph{false}.
5628: @end table
5629:
5630: In either case, if asynchronous event handling is enabled for the @code{INTERRUPT} event class (i.e., @code{ASTART "INTERRUPT"} or @code{ASTART} have been invoked by the current process), an asynchronous event of event class @code{INTERRUPT} and event identifier @code{SIGINT} will be enqueued.
5631:
5632: @node Error Processing
5633: @chapter Error Processing
5634: @cindex error processing
5635:
5636: FreeM exposes three means of processing M program execution errors:
5637:
5638: @table @emph
5639:
5640: @item FreeM-style error processing
5641: 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.
5642:
5643: @item DSM 2.0-style error processing
5644: 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.
5645:
5646: @item Standard error processing
5647: 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.
5648:
5649: 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.
5650:
5651: @end table
5652:
5653: 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.
5654:
5655: @node FreeM Error Codes
5656: @chapter FreeM Error Codes
5657: @cindex Error Codes
5658:
5659: @table @asis
5660:
5661: @item @code{ZINRPT} - @emph{interrupt}
5662: Raised when an interrupt signal is received.
5663:
5664: @item @code{ZBKERR} - @emph{BREAK point}
5665: Raised when a @code{BREAK} point is reached.
5666:
5667: @item @code{ZNOSTAND} - @emph{non standard syntax}
5668: Raised when features incompatible with the current value of @code{$DIALECT} are used.
5669:
5670: @item @code{ZUNDEF} - @emph{variable not found}
5671: Raised when an undefined local or global variable is accessed. This error code has been deprecated in favor of standard error codes @code{M6} and @code{M7}.
5672:
5673: @item @code{ZLBLUNDEF} - @emph{label not found}
5674: Raised when a referenced label is not found.
5675:
5676: @item @code{ZMISSOPD} - @emph{missing operand}
5677: Raised when an operand is missing from an expression.
5678:
5679: @item @code{ZMISSOP} - @emph{missing operator}
5680: Raised when an operator is missing from an expression.
5681:
5682: @item @code{ZILLOP} - @emph{unrecognized operator}
5683: Raised when an unrecognized operator is encountered in an expression.
5684:
5685: @item @code{ZQUOTER} - @emph{unmatched quotes}
5686: Raised when unbalanced quotes are encountered.
5687:
5688: @item @code{ZCOMMAER} - @emph{comma expected}
5689: Raised when a comma is expected in program syntax but is not found.
5690:
5691: @item @code{ZASSIGNER} - @emph{equals '=' expected}
5692: Raised when an equals sign is expected in program syntax but is not found.
5693:
5694: @item @code{ZARGER} - @emph{argument not permitted}
5695: Raised when an argument is encountered in a syntactic position where arguments are not permitted.
5696:
5697: @item @code{ZSPACER} - @emph{blank ' ' expected}
5698: Raised when a space character is expected in program syntax but is not found.
5699:
5700: @item @code{ZBRAER} - @emph{unmatched parentheses}
5701: Raised when unbalanced parentheses are detected in program syntax.
5702:
5703: @item @code{ZLVLERR} - @emph{level error}
5704: Raised when a level error occurs.
5705:
5706: @item @code{ZDIVER} - @emph{divide by zero}
5707: Raised when program code attempts to divide by zero. Deprecated in favor of standard error code @code{M9}.
5708:
5709: @item @code{ZILLFUN} - @emph{function not found}
5710: Raised when program code attempts to call intrinsic or extrinsic functions that are not defined.
5711:
5712: @item @code{ZFUNARG} - @emph{wrong number of function arguments}
5713: Raised when an intrinsic or extrinsic function is called with the wrong number of arguments.
5714:
5715: @item @code{ZZTERR} - @emph{ZTRAP error}
5716: Raised when a @code{$ZTRAP} error occurs.
5717:
5718: @item @code{ZNEXTERR} - @emph{$NEXT/$ORDER error}
5719: Raised when an error occurs in @code{$NEXT} or @code{$ORDER}.
5720:
5721: @item @code{ZSELER} - @emph{$SELECT error}
5722: Raised when an error occurs in @code{$SELECT}
5723:
5724: @item @code{ZCMMND} - @emph{illegal command}
5725: Raised when program code attempts to execute an illegal command.
5726:
5727: @item @code{ZARGLIST} - @emph{argument list incorrect}
5728: Raised when the argument list supplied to an M language element does not match that language element's syntactic requirements.
5729:
5730: @item @code{ZINVEXPR} - @emph{invalid expression}
5731: Raised when an invalid expression is encountered.
5732:
5733: @item @code{ZINVREF} - @emph{invalid reference}
5734: Raised when an invalid variable reference is encountered.
5735:
5736: @item @code{ZMXSTR} - @emph{string too long}
5737: Raised when a string is encountered that exceeds @code{^$SYSTEM("STRING_MAX")}.
5738:
5739: @item @code{ZTOOPARA} - @emph{too many parameters}
5740: Raised when too many parameters are passed to a function or subroutine.
5741:
5742: @item @code{ZNOPEN} - @emph{unit not open}
5743: Raised when attempting to access an I/O channel that has not been opened.
5744:
5745: @item @code{ZNODEVICE} - @emph{unit does not exist}
5746: Raised when attempting to access a device that does not exist.
5747:
5748: @item @code{ZPROTECT} - @emph{file protection violation}
5749: Raised when attempting to access a file or device to which you do not have permission.
5750:
5751: @item @code{ZGLOBER} - @emph{global not permitted}
5752: Raised when attempting to use a global in a syntactic element where global variables are not permitted.
5753:
5754: @item @code{ZFILERR} - @emph{file not found}
5755: Raised when attempting to access a file that does not exist.
5756:
5757: @item @code{ZPGMOV} - @emph{program overflow}
5758: Raised when a program overflows the limits of a routine buffer.
5759:
5760: @item @code{ZSTKOV} - @emph{stack overflow}
5761: Raised when @code{DO}, @code{FOR}, or @code{XECUTE} nesting levels exceed the value in @code{^$SYSTEM("NESTLEVLS")}.
5762:
5763: @item @code{ZSTORE} - @emph{symbol table overflow}
5764: Raised when program code attempts to store too much data in the local symbol table. Should not occur unless symbol table auto-adjust is disabled.
5765:
5766: @item @code{ZNOREAD} - @emph{file won't read}
5767: Raised when program code attempts to read from an unreadable file.
5768:
5769: @item @code{ZNOWRITE} - @emph{file won't write}
5770: Raised when program code attempts to write to an unwritable file.
5771:
5772: @item @code{ZNOPGM} - @emph{routine not found}
5773: Raised when an attempt is made to load or execute a routine that does not exist in the current namespace.
5774:
5775: @item @code{ZNAKED} - @emph{illegal naked reference}
5776: Raised when an attempt is made to use an illegal naked reference.
5777:
5778: @item @code{ZSBSCR} - @emph{illegal subscript}
5779: Raised when an illegal subscript access is attempted.
5780:
5781: @item @code{ZISYNTX} - @emph{insert syntax}
5782: Raised when illegal insert syntax is used.
5783:
5784: @item @code{ZDBDGD} - @emph{global data degradation}
5785: Raised when corruption is detected in global data files.
5786:
5787: @item @code{ZKILLER} - @emph{job kill signal}
5788: Raised on a job kill signal.
5789:
5790: @item @code{ZHUPER} - @emph{hangup signal}
5791: Raised on a job hangup signal.
5792:
5793: @item @code{ZMXNUM} - @emph{numeric overflow}
5794: Raised when an assignment or expression result exceeds @code{$ZPRECISION}.
5795:
5796: @item @code{ZNOVAL} - @emph{function returns no value}
5797: Raised when a function does not return a value. Extrinsic functions must @code{QUIT} with a value.
5798:
5799: @item @code{ZTYPEMISMATCH} - @emph{type mismatch}
5800: Raised when a type mismatch occurs.
5801:
5802: @item @code{ZMEMOV} - @emph{out of memory}
5803: Raised when FreeM runs out of heap memory.
5804:
5805: @item @code{ZNAMERES} - @emph{error in name resolution}
5806: Raised when an attempted name resolution fails.
5807:
5808: @item @code{ZSCKCREAT} - @emph{error creating socket}
5809: Raised when an error occurs creating a socket for network I/O.
5810:
5811: @item @code{ZSCKIFAM} - @emph{invalid address family (must be IPV4 or IPV6)}
5812: Raised when the address family specified in an @code{OPEN} command for a socket I/O channel is not IPV4 or IPV6.
5813:
5814: @item @code{ZSCKITYP} - @emph{invalid connection type (must be TCP or UDP)}
5815: Raised when the connection type specified in an @code{OPEN} command for a socket I/O channel is not @code{TCP} or @code{UDP}.
5816:
5817: @item @code{ZSCKIPRT} - @emph{invalid port number}
5818: Raised when the port number specified in an @code{OPEN} command for a socket I/O channel is invalid. Valid TCP and UDP ports are in the range of 1-65535.
5819:
5820: @item @code{ZSCKCERR} - @emph{connection error}
5821: Raised when an error occurs on a @code{USE <channel>:/CONNECT} command.
5822:
5823: @item @code{ZSCKAERR} - @emph{USE action invalid for connection type (possibly CONNECT on UDP socket?)}
5824: Raised when an attempt is made to @code{USE <channel>:/CONNECT} on a UDP socket I/O channel. The UDP protocol is connectionless.
5825:
5826: @item @code{ZSCKACON} - @emph{attempted to CONNECT an already-connected socket}
5827: Raised when an attempt is made to @code{USE <channel>:/CONNECT} on a TCP socket I/O channel that is already connected.
5828:
5829: @item @code{ZSCKNCON} - @emph{attempted to READ from a disconnected TCP socket}
5830: Raised when an attempt is made to @code{READ} a TCP socket that has not yet been connected.
5831:
5832: @item @code{ZSCKEOPT} - @emph{error setting socket options}
5833: Raised when an error is encountered while setting socket options.
5834:
5835: @item @code{ZSCKERCV} - @emph{error in READ from socket}
5836: Raised when an error occurs in a socket I/O channel @code{READ}.
5837:
5838: @item @code{ZSCKESND} - @emph{error in WRITE to socket}
5839: Raised when an error occurs while attempting to @code{WRITE} to a socket I/O channel.
5840:
5841: @item @code{ZNORPI} - @emph{^$ZRPI only supported on Raspberry Pi hardware}
5842: Raised when an attempt is made to use the @code{^$ZRPI} structured system variable on a platform other than the Raspberry Pi single-board computer.
5843:
5844: @item @code{ZCREDEF} - @emph{cannot redefine CONST}
5845: Raised when attempts are made to redefine a @code{CONST} after its initial definition.
5846:
5847: @item @code{ZCMODIFY} - @emph{cannot modify CONST}
5848: Raised when attempts are made to change the value of a @code{CONST}.
5849:
5850: @item @code{ZFILEXWR} - @emph{cannot open existing file for WRITE}
5851: Raised when an attempt is made to open an existing file in write (but not append) mode.
5852:
5853: @item @code{INEWMULT} - @emph{initializing NEW with multiple setarguments not supported}
5854: Raised when you attempt to use multiple setarguments with initializing @code{NEW}, e.g. @code{NEW X=2,Y=3}.
5855:
5856: @item @code{ZECODEINV} - @emph{invalid value for $ECODE}
5857: Raised when attempts are made to set @code{$ECODE} to an invalid error code value. Obsolete and replaced by standard error code @code{M101}.
5858:
5859: @item @code{ZASSERT} - @emph{programmer assertion failed}
1.46 snw 5860: Raised when an @code{ZASSERT} expression's result is not true.
1.1 snw 5861:
5862: @item @code{ZUSERERR} - @emph{user-defined error}
5863: Raised when program code calls @code{THROW} with an error code argument for which the first character is @code{U}, or when @code{$ECODE} is set to an error code for which the first character is @code{U}.
5864:
5865: Custom error messages for @code{ZUSERERR} may be set in @code{^$JOB($JOB,"USER_ERRORS",<user_error_code>)}, where @code{<user_error_code>} represents the custom error code.
5866:
5867: For example:
5868:
5869: @example
1.22 snw 5870: DEFAULT.USER> S ^$JOB($JOB,"USER_ERRORS","UBLACKHOLE")="black hole encountered"
1.1 snw 5871:
5872:
1.22 snw 5873: DEFAULT.USER> THROW UBLACKHOLE
1.1 snw 5874:
5875:
5876: >> Error UBLACKHOLE: black hole encountered in SYSTEM::^%SYSINIT [$STACK = 0]
5877: >> THROW UBLACKHOLE
5878: ^
5879: @end example
5880:
5881: @item @code{ZSYNTERR} - @emph{syntax error}
5882: Raised when a syntax error without a more specific error code is encountered.
5883:
5884: @item @code{ZCTRLB} - @emph{break}
5885: Pseudo-error used by the FreeM debugger. Not visibly raised in normal program operation.
5886:
5887: @item @code{ZASYNC} - @emph{asynchronous interruption}
5888: Pseudo-error used by the FreeM asynchronous events subsystem. Not visibly raised in normal program operation.
5889:
5890: @item @code{M1} - @emph{naked indicator undefined}
5891: Raised when an attempt is made to use a naked reference before the naked indicator is set.
5892:
5893: @item @code{M2} - @emph{invalid combination with $FNUMBER code atom}
5894:
5895:
5896: @item @code{M3} - @emph{$RANDOM seed less than 1}
5897:
5898:
5899: @item @code{M4} - @emph{no true condition in $SELECT}
5900:
5901:
5902: @item @code{M5} - @emph{line reference less than zero}
5903:
5904:
5905: @item @code{M6} - @emph{undefined local variable}
5906:
5907:
5908: @item @code{M7} - @emph{undefined global variable}
5909:
5910:
5911: @item @code{M8} - @emph{undefined intrinsic special variable}
5912:
5913:
5914: @item @code{M9} - @emph{divide by zero}
5915:
5916:
5917: @item @code{M10} - @emph{invalid pattern match range}
5918:
5919:
5920: @item @code{M11} - @emph{no parameters passed}
5921:
5922:
5923: @item @code{M12} - @emph{invalid line reference (negative offset)}
5924:
5925:
5926: @item @code{M13} - @emph{invalid line reference (line not found)}
5927:
5928:
5929: @item @code{M14} - @emph{line level not 1}
5930:
5931:
5932: @item @code{M15} - @emph{undefined index variable}
5933:
5934:
5935: @item @code{M16} - @emph{argumented QUIT not allowed}
5936:
5937:
5938: @item @code{M17} - @emph{argumented QUIT required}
5939:
5940:
5941: @item @code{M18} - @emph{fixed length READ not greater than zero}
5942:
5943:
5944: @item @code{M19} - @emph{cannot copy a tree or subtree onto itself}
5945:
5946:
5947: @item @code{M20} - @emph{line must have a formal parameter list}
5948:
5949:
5950: @item @code{M21} - @emph{algorithm specification invalid}
5951:
5952:
5953: @item @code{M22} - @emph{SET or KILL to ^$GLOBAL when data in global}
5954:
5955:
5956: @item @code{M23} - @emph{SET or KILL to ^$JOB for non-existent job number}
5957:
5958:
5959: @item @code{M24} - @emph{change to collation algorithm while subscripted local variables defined}
5960:
5961:
5962: @item @code{M26} - @emph{non-existent environment}
5963:
5964:
5965: @item @code{M27} - @emph{attempt to rollback a transaction that is not restartable}
5966:
5967:
5968: @item @code{M28} - @emph{mathematical function, parameter out of range}
5969:
5970:
5971: @item @code{M29} - @emph{SET or KILL on structured system variable not allowed by implementation}
5972:
5973:
5974: @item @code{M30} - @emph{reference to global variable with different collating sequence within a collating algorithm}
5975:
5976:
5977: @item @code{M31} - @emph{control mnemonic used for device without a mnemonic space selected}
5978:
5979:
5980: @item @code{M32} - @emph{control mnemonic used in user-defined mnemonic space which has no associated line}
5981:
5982:
5983: @item @code{M33} - @emph{SET or KILL to ^$ROUTINE when routine exists}
5984:
5985:
5986: @item @code{M35} - @emph{device does not support mnemonic space}
5987:
5988:
5989: @item @code{M36} - @emph{incompatible mnemonic spaces}
5990:
5991:
5992: @item @code{M37} - @emph{READ from device identified by empty string}
5993:
5994:
5995: @item @code{M38} - @emph{invalid structured system variable subscript}
5996:
5997:
5998: @item @code{M39} - @emph{invalid $NAME argument}
5999:
6000:
6001: @item @code{M40} - @emph{call-by-reference in JOB actual parameter}
6002:
6003:
6004: @item @code{M41} - @emph{invalid LOCK argument within a transaction}
6005:
6006:
6007: @item @code{M42} - @emph{invalid QUIT within a transaction}
6008:
6009:
6010: @item @code{M43} - @emph{invalid range value ($X, $Y}
6011:
6012:
6013: @item @code{M44} - @emph{invalid command outside of a transaction}
6014:
6015:
6016: @item @code{M45} - @emph{invalid GOTO reference}
6017:
6018:
6019: @item @code{M56} - @emph{identifier exceeds maximum length}
6020:
6021:
6022: @item @code{M57} - @emph{more than one defining occurrence of label in routine}
6023:
6024:
6025: @item @code{M58} - @emph{too few formal parameters}
6026:
6027:
6028: @item @code{M60} - @emph{illegal attempt to use an undefined SSVN}
6029:
6030:
6031: @item @code{M101} - @emph{invalid value for $ECODE}
6032:
6033:
6034: @item @code{M102} - @emph{synchronous and asynchronous event processing cannot be simultaneously enabled for the same event class}
6035:
6036:
6037: @item @code{M103} - @emph{invalid event identifier}
6038:
6039:
6040: @item @code{M104} - @emph{ETRIGGER event identifier for IPC event class does not match job process identifier}
6041:
6042:
6043: @end table
6044:
1.35 snw 6045:
1.1 snw 6046: @node System Configuration
6047: @chapter System Configuration
6048: @cindex configuration, system
6049:
6050: @section Installing FreeM
6051: @cindex installation
6052:
1.35 snw 6053: @subsection Installation Methods
1.1 snw 6054:
1.35 snw 6055: FreeM allows the following installation methods:
1.1 snw 6056: @table @asis
1.35 snw 6057: @item Binary Repository
1.57 snw 6058: For recent versions of the Ubuntu and Debian distributions of GNU/Linux, we provide package repositories from which FreeM may easily be installed. See the @emph{FreeM Wiki} for more information, and @emph{https://packages.coherent-logic.com} for instructions.
1.1 snw 6059:
1.35 snw 6060: If available, this is the simplest method of installing FreeM.
6061: @item Binary Packages
6062: We provide binary packages of FreeM for @emph{dpkg} and @emph{rpm}-based distributions of GNU/Linux, and @emph{pkgadd} packages for Solaris 8-10. If you cannot use repositories, this is the easiest option.
6063:
6064: See @emph{https://freem.coherent-logic.com/binaries.cfm} for downloads and instructions.
1.57 snw 6065: @item Source Tarball
1.35 snw 6066: If you prefer installing from source, we recommend that you download the latest @emph{.tar.gz} file from @emph{https://freem.coherent-logic.com/downloads.cfm}, and follow these steps:
6067:
6068: @example
6069: $ gunzip freem-@emph{<version>}.tar.gz
6070: $ tar xf freem-@emph{<version>}.tar
6071: $ cd freem
6072: $ ./configure # see the Build Configuration section for optional flags
6073: $ make
6074: $ sudo make install
6075: @end example
1.1 snw 6076:
1.35 snw 6077: Once this process has been completed, you may proceed to @emph{Initial Configuration}.
1.1 snw 6078:
1.35 snw 6079: Installation from source archive is the most challenging but flexible supported option for advanced users.
6080: @item CVS Repository
6081: If you wish to try the bleeding-edge development version of FreeM, you may do so by following these steps:
1.1 snw 6082:
1.35 snw 6083: @verbatim
6084: $ cvs -d :pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem
6085: $ cd freem
6086: $ ./autogen.sh
6087: $ ./configure # see the Build Configuration section for optional flags
1.1 snw 6088: $ make
6089: $ sudo make install
1.35 snw 6090: @end verbatim
6091:
6092: Once this process has been completed, you may proceed to @emph{Initial Configuration}.
6093:
6094: This installation method is by far the most complicated, and is intended only for those who wish to contribute to FreeM development. It is not intended for end users, and no technical support will be provided.
6095:
6096: See the @emph{Contributor Guide} on the @emph{FreeM Wiki} for more information.
6097: @end table
6098: @subsection Build Configuration
6099: @cindex build configuration
6100:
6101: When configuring FreeM with the supplied @code{configure} script, there are some FreeM-specific options that may be used to compile in optional features, or exclude default ones:
6102:
6103: @table @asis
1.1 snw 6104:
1.35 snw 6105: @item @code{--enable-mwapi} (EXPERIMENTAL)
6106: Enables experimental support for the M Windowing API (ANSI @emph{X11.6-1995}) using the OSF/Motif widget toolkit. Requires that you have the @code{X11}, @code{Xt}, @code{ICE}, and @code{Xm} libraries, as well as all of their C header files.
1.1 snw 6107:
6108: Please consult your operating system's documentation for the correct commands to install the required libraries.
6109:
6110: @emph{Example}
6111:
6112: @example
1.35 snw 6113: $ ./configure --enable-mwapi
1.1 snw 6114: $ make
6115: $ sudo make install
6116: @end example
6117:
1.57 snw 6118: @item @code{--enable-newglobals} (EXPERIMENTAL)
6119: Enables a new and modernized global handler. This global handler has a number of known bugs, and thus should be used with caution.
6120:
6121: Note that global files created in the default global handler are incompatible with the new global handler, and vice-versa. You will need to back up and remove all globals in your environments when switching global handlers.
6122:
6123:
6124: @emph{Example}
6125:
6126: @example
6127: $ ./configure --enable-newglobals
6128: $ make
6129: $ sudo make install
6130: @end example
6131:
1.35 snw 6132: @end table
1.1 snw 6133:
1.35 snw 6134: @subsection Initial Configuration
6135: Once FreeM is installed, you will need to configure it:
1.1 snw 6136:
1.35 snw 6137: @enumerate
6138: @item Create a user and group, each named @emph{freem}, under which FreeM will run
6139: @item Add any user accounts that will need to run FreeM to the @emph{freem} group
6140: @item Have all users added in step 2 sign out and sign in for the new group membership to take effect
6141: @item Run @code{fmadm configure} with superuser privileges to create the @code{DEFAULT} environment with @code{SYSTEM} and @code{USER} namespaces and default after-image journal settings, and populate the bundled vendor routines
6142: @item Run @code{fmadm start environment} with superuser privileges to start the @code{DEFAULT} environment
6143: @item Make sure the environment is ready by running @code{fmadm status environment} with superuser privileges
6144: @end enumerate
6145:
6146: @subsubsection Creating Additional Environments
6147: To create additional environments, do the following steps:
6148:
6149: @enumerate
6150: @item Create a new user and group for the environment @emph{(optional)}
6151: @item Run @code{fmadm configure -e=@emph{<environment>} -u=@emph{<username>} -g=@emph{<groupname>} [-E=@emph{true|false}]} @emph{(the @code{-E} flag enables or disables the environment)}
6152: @item Run @code{fmadm start environment -e=@emph{<environment>}} to start the environment
6153: @item Run @code{fmadm status environment} to make sure the environment is healthy
6154: @end enumerate
1.1 snw 6155:
1.35 snw 6156: @subsubsection Additional Customization
1.1 snw 6157:
1.35 snw 6158: See the FreeM @emph{environment catalog} at @code{@emph{$PREFIX}/etc/freem/env.conf}, and the @emph{fmadm}(1) @code{man} page for more information.
1.1 snw 6159:
1.35 snw 6160: @emph{$PREFIX} represents the root location of your FreeM installation. This can be @code{/usr/local}, @code{/}, or others, depending on how FreeM was built and installed.
1.1 snw 6161:
6162: @node Accessing FreeM from C Programs
6163: @chapter Accessing FreeM from C Programs
6164:
6165: 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 data access drivers for external systems.
6166:
6167: 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.
6168:
6169: 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.
6170:
6171: 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}.
6172:
6173: @section freem_ref_t Data Structure
6174: @cindex libfreem, data structures: freem_ref_t
6175:
6176: 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.
6177:
6178: The data structure, defined in @file{freem.h}, looks like this:
6179:
6180: @verbatim
6181: typedef struct freem_ref_t {
6182:
6183: /*
6184: * The 'reftype' field can be one of:
6185: *
6186: * MREF_RT_LOCAL
6187: * MREF_RT_GLOBAL
6188: * MREF_RT_SSV
6189: */
6190: short reftype;
6191:
6192: /*
6193: * The 'name' field is the name of the local variable,
6194: * global variable, or SSVN (without ^ or ^$).
6195: */
6196: char name[256];
6197:
6198: /*
6199: * Returned data goes in a string, so you've got to figure out the
6200: * whole M canonical number thing yourself. Good luck. :-)
6201: */
6202: char value[STRLEN];
6203:
6204: short status;
6205:
6206: unsigned int subscript_count;
6207: char subscripts[255][256];
6208:
6209: } freem_ref_t;
6210: @end verbatim
6211:
6212: @emph{freem_ref_t Members}
6213:
6214: @table @asis
6215: @cindex libfreem, freem_ref_t.reftype
6216: @item @option{reftype}
6217: 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}.
6218:
6219: @cindex libfreem, freem_ref_t.name
6220: @item @option{name}
6221: The @option{name} member contains the name of the global, local, or SSVN to be accessed. You @emph{must not} include leading characters, such as @code{^} or @code{^$}.
6222:
6223: @cindex libfreem, freem_ref_t.value
6224: @item @option{value}
6225: This member contains the value read from or the value to be written to the global, local, or SSVN.
6226:
6227: @cindex libfreem, freem_ref_t.status
6228: @item @option{status}
6229: This member gives us various API status values after the API call returns. In general, this value is also returned by each API function.
6230:
6231: @cindex libfreem, freem_ref_t.subscript_count
6232: @item @option{subscript_count}
6233: 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.
6234:
6235: @cindex libfreem, freem_ref_t.subscripts
6236: @item @option{subscripts}
6237: A two-dimensional array containing the subscripts to which we are referring in this API call.
6238:
6239: @end table
6240:
6241: @section freem_ent_t Data Structure
6242: @cindex libfreem, data structures: freem_ent_t
6243:
6244: 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()}).
6245:
6246: The data structure, defined in @file{freem.h}, looks like this:
6247:
6248: @verbatim
6249: typedef struct freem_ent_t {
6250:
6251: /* name of function or procedure entry point */
6252: char name[256];
6253:
6254: /* return value */
6255: char value[STRLEN];
6256:
6257: /* value of ierr on return */
6258: short status;
6259:
6260: /* argument count and array */
6261: unsigned int argument_count;
6262: char arguments[255][256];
6263:
6264: } freem_ent_t;
6265: @end verbatim
6266:
6267: @emph{freem_ent_t Members}
6268:
6269: @table @asis
6270:
6271: @item @option{name}
6272: @cindex libfreem, freem_ent_t.name
6273: The @option{name} member contains the name of the extrinsic function or procedure to be called.
6274:
6275: @cindex libfreem, freem_ent_t.value
6276: @item @option{value}
6277: This member contains the value returned by the function called. Not used by @code{freem_procedure()}.
6278:
6279: @cindex libfreem, freem_ent_t.status
6280: @item @option{status}
6281: 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}.
6282:
6283: @cindex libfreem, freem_ent_t.argument_count
6284: @item @option{argument_count}
6285: 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.
6286:
6287: @cindex libfreem, freem_ent_t.arguments
6288: @item @option{arguments}
6289: A two-dimensional array containing the arguments to be passed into the extrinsic function or procedure being called.
6290:
6291: @end table
6292:
6293: @section freem_init()
6294: @cindex libfreem, freem_init()
6295:
6296: Initializes @code{libfreem} in preparation for calling other APIs.
6297:
6298: @emph{Synopsis}
6299:
6300: @code{pid_t freem_init(char *environment_name, char *namespace_name);}
6301:
6302: @emph{Parameters}
6303:
6304: @table @asis
6305: @item @code{environment_name}
6306: Specifies the environment to use.
6307: @item @code{namespace_name}
6308: Specifies the namespace to use.
6309: @end table
6310:
6311: @emph{Return Values}
6312:
6313: Returns the process ID of the @code{libfreem} process on success, or @code{-1} on failure.
6314:
6315: @emph{Example}
6316:
6317: This example prompts the user to enter a FreeM namespace and then attempts to initialize @code{libfreem} to use the selected namespace.
6318:
6319: @verbatim
6320: #include <stdio.h>
6321: #include <string.h>
6322: #include <freem.h>
6323:
6324: int main(int argc, char **argv, char **envp)
6325: {
6326: char namespace[256];
6327:
6328: /* get the namespace name to use */
6329: printf("Enter FreeM namespace to use: ");
6330: fgets(namespace, 255, stdin);
6331:
6332: /* remove the trailing newline */
6333: namespace[strcspn(buffer, "\n")] = '\0';
6334:
6335: /* initialize libfreem using the provided namespace */
6336: if(freem_init("DEFAULT", namespace) == TRUE) {
6337: printf("\nSuccess\n");
6338: }
6339: else {
6340: printf("\nFailure\n");
6341: }
6342:
6343: return 0;
6344: }
6345: @end verbatim
6346:
6347: @section freem_version()
6348: @cindex libfreem, freem_version()
6349:
6350: Returns the version of FreeM in use.
6351:
6352: @emph{Synopsis}
6353:
6354: @code{short freem_version(char *result);}
6355:
6356: @emph{Parameters}
6357:
6358: @table @asis
6359: @item @code{result}
6360: 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.
6361: @end table
6362:
6363: @emph{Return Value}
6364:
6365: Returns @code{0}.
6366:
6367: @emph{Example}
6368:
6369: This example will display the FreeM version on standard output.
6370:
6371: @verbatim
6372: #include <stdio.h>
6373: #include <string.h>
6374: #include <freem.h>
6375:
6376: int main(int argc, char **argv, char **envp)
6377: {
6378: char version[20] = {0};
6379:
6380: freem_init(``USER'');
6381: freem_version(version);
6382:
6383: printf(``FreeM version: %s\n'', version);
6384:
6385: }
6386: @end verbatim
6387:
6388: @section freem_set()
6389: @cindex libfreem, freem_set()
6390:
6391: Sets a FreeM local node, global node, or writable SSVN node.
6392:
6393: @emph{Synopsis}
6394:
6395: @code{short freem_set(freem_ref_t *ref);}
6396:
6397: @emph{Parameters}
6398:
6399: @table @asis
6400: @item @code{freem_ref_t}
6401: This parameter is a pointer to a @code{freem_ref_t} struct. The caller must allocate the memory for this struct.
6402: @end table
6403:
6404: @emph{Return Value}
6405:
6406: Returns @code{OK} on success, or one of the other error values defined in @code{merr.h}.
6407:
6408: @emph{Example}
6409:
6410: This example sets the value @code{blue} into global node @code{^car("color")}.
6411:
6412: @verbatim
6413: #include <stdio.h>
6414: #include <string.h>
6415: #include <freem.h>
6416:
6417: int main(int argc, char **argv, char **envp)
6418: {
6419: freem_ref_t ref;
6420:
6421: /* we're setting a global */
6422: ref.reftype = MREF_RT_GLOBAL;
6423:
6424: /* access global "car" */
6425: strcpy(ref.name, "car");
6426:
6427: /* set up the subscripts */
6428: ref.subscript_count = 1;
6429: strcpy(ref.subscripts[0], "color");
6430:
6431:
6432: /* use the USER namespace */
6433: freem_init("USER");
6434:
6435: /* write the data out */
6436: freem_set(&ref);
6437:
6438: }
6439: @end verbatim
6440:
6441: @section freem_get()
6442: @cindex libfreem, freem_get()
6443:
6444: Retrieves a FreeM local node, global node, or writable SSVN node.
6445:
6446: @emph{Synopsis}
6447:
6448: @code{short freem_get(freem_ref_t *ref);}
6449:
6450: @emph{Parameters}
6451:
6452: @table @asis
6453: @item @code{freem_ref_t}
6454: This parameter is a pointer to a @code{freem_ref_t} struct. The caller must allocate the memory for this struct.
6455: @end table
6456:
6457: @emph{Return Value}
6458:
6459: Returns @code{OK} on success, or one of the other error values defined in @code{merr.h}.
6460:
6461: @emph{Example}
6462:
6463: This example retrieves the character set of the current process.
6464:
6465: @verbatim
6466: #include <stdio.h>
6467: #include <sys/types.h>
6468: #include <unistd.h>
6469: #include <string.h>
6470: #include <freem.h>
6471:
6472: int main(int argc, char **argv, char)
6473: {
6474: pid_t pid;
6475: freem_ref_t ref;
6476:
6477: /* get the PID of this process */
6478: pid = getpid();
6479:
6480: /* we want to access an SSVN */
6481: ref.reftype = MREF_RT_SSV;
6482:
6483: /* set up the name and subscripts */
6484: strcpy(ref.name, "JOB");
6485:
6486: ref.subscript_count = 2;
6487: sprintf(ref.subscripts[0], "%d", pid);
6488: strcpy(ref.subscripts[1], "CHARACTER");
6489:
6490: /* initialize libfreem, using the USER namespace */
6491: freem_init("USER");
6492:
6493: /* call libfreem API */
6494: freem_get(&ref);
6495:
6496: /* output the character set info */
6497: printf("PID %d character set is '%s'\n", pid, ref.value);
6498: }
6499: @end verbatim
6500:
6501: @section freem_kill()
6502: @cindex libfreem, freem_kill()
6503:
6504: Deletes a FreeM local node, global node, or killable SSVN node, as well as all of its children.
6505:
6506: @emph{short freem_kill(freem_ref_t *ref);}
6507:
6508: @emph{Parameters}
6509:
6510: @table @asis
6511: @item @code{freem_ref_t}
6512: This parameter is a pointer to a @code{freem_ref_t} struct. The caller must allocate the memory for this struct.
6513: @end table
6514:
6515: @emph{Return Value}
6516:
6517: Returns @code{OK} on success, or one of the other error values defined in @code{merr.h}.
6518:
6519: @emph{Example}
6520:
6521: @verbatim
6522: #include <stdio.h>
6523: #include <string.h>
6524: #include <freem.h>
6525:
6526: int main(int argc, char **argv, char **envp)
6527: {
6528: freem_ref_t ref;
6529:
6530: /* we're killing a global node */
6531: ref.reftype = MREF_RT_GLOBAL;
6532:
6533: /* access global "car" */
6534: strcpy(ref.name, "car");
6535:
6536: /* set up the subscripts */
6537: ref.subscript_count = 0;
6538:
6539: /* use the USER namespace */
6540: freem_init("USER");
6541:
6542: /* kill the global and all its descendant subscripts */
6543: freem_kill(&ref);
6544: }
6545: @end verbatim
6546:
6547: @section freem_data()
6548: @cindex libfreem, freem_data()
6549:
6550: @section freem_order()
6551: @cindex libfreem, freem_order()
6552:
6553: @section freem_query()
6554: @cindex libfreem, freem_query()
6555:
6556: @section freem_lock()
6557: @cindex libfreem, freem_lock()
6558:
6559: @section freem_unlock()
6560: @cindex libfreem, freem_unlock()
6561:
6562: @section freem_tstart()
6563: @cindex libfreem, freem_tstart()
6564:
6565: @section freem_trestart()
6566: @cindex libfreem, freem_trestart()
6567:
6568: @section freem_trollback()
6569: @cindex libfreem, freem_trollback()
6570:
6571: @section freem_tlevel()
6572: @cindex libfreem, freem_tlevel()
6573:
6574: @section freem_tcommit()
6575: @cindex libfreem, freem_tcommit()
6576:
6577: @section freem_function()
6578: @cindex libfreem, freem_function()
6579:
6580: @section freem_procedure()
6581: @cindex libfreem, freem_procedure()
6582:
6583: @node FreeM Administrator
6584: @appendix FreeM Administrator
6585: @cindex utilities, system management
6586: @cindex utilities, fmadm
6587: @cindex fmadm
6588:
6589: The @code{fmadm} utility is the preferred method of managing a FreeM installation, and will eventually replace all of the existing utilities.
1.53 snw 6590: In support of FreeM operators, @code{fmadm} presents a consistent, simple interface for all FreeM management tasks, and is namespace-aware.
6591: This appendix will document each @code{fmadm} facility as it is implemented.
1.1 snw 6592:
6593: The @code{fmadm} utility's functions all follow the below, consistent syntax:
6594:
6595: @example
6596: usage: fmadm <action> <object> <namespace> [OPTIONS]
6597: @end example
6598:
6599: The @emph{action} keyword can be one of the following:
6600:
6601: @table @emph
6602:
6603: @item list
6604: Lists instances of @emph{object}
6605:
6606: @item examine
6607: Examines a single instance of @emph{object}
6608:
6609: @item verify
6610: Verifies the integrity of @emph{object}
6611:
6612: @item compact
6613: Compacts @emph{object}
6614:
6615: @item repair
6616: Repairs integrity problems in @emph{object}
6617:
6618: @item create
6619: Creates an instance of @emph{object}
6620:
6621: @item remove
6622: Removes an instance of @emph{object}
6623:
6624: @item import
6625: Imports an @emph{object}
6626:
6627: @item export
6628: Exports an @emph{object}
6629:
6630: @item backup
6631: Creates a backup of @emph{object}
6632:
6633: @item restore
6634: Restores a backup of @emph{object}
6635:
6636: @item migrate
6637: Migrates an instance of @emph{object} from an older FreeM version to the current version
6638:
6639: @item edit
6640: Edits an instance of @emph{object}
6641:
6642: @end table
6643:
6644: The @emph{object} keyword can be one of the following:
6645:
6646: @table @emph
6647:
6648: @item lock
6649: The FreeM @code{LOCK} table.
6650:
6651: Supported actions are @code{list} and @code{remove}.
6652:
6653: @item journal
6654: FreeM after-image journaling.
6655:
6656: Supported actions are @code{examine} and @code{restore}.
6657:
6658: The @code{examine} action will dump the after-image journal entries for the selected namespace in human-readable format.
6659:
6660: The @code{restore} action will play after-image journals forward for the selected namespace.
6661:
6662: @item namespace
6663: FreeM namespaces (collections of M routines and globals).
6664:
6665: No actions yet implemented.
6666:
6667: @item global
6668: The data files representing each FreeM @emph{global}.
6669:
6670: Supported actions are @code{list}, @code{examine}, @code{remove}, and @code{verify}.
6671:
6672: @item routine
6673: An M routine, stored as a @code{.m} file.
6674:
6675: Supported actions are @code{list}, @code{examine}, @code{remove}, @code{import}, @code{export}, @code{backup}, and @code{edit}.
6676:
6677: @item job
6678: A UNIX process representing an instance of the FreeM runtime.
6679:
6680: Supported actions are @code{list} and @code{examine}.
6681:
6682: @end table
6683:
6684:
6685: @node FreeM VIEW Commands and Functions
6686: @appendix FreeM VIEW Commands and Functions
6687:
6688: @section VIEW 16: Total Count of Error Messages/View Single Error Message
6689: @cindex VIEW commands/functions, 16, total count of error messages/view single error message
6690:
6691: Unknown semantics
6692:
6693: @section VIEW 17: Intrinsic Z-Commands
6694: @cindex VIEW commands/functions, 17, intrinsic Z-commands
6695:
6696: 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.
6697:
6698: @section VIEW 18: Intrinsic Z-Functions
6699: @cindex VIEW commands/functions, 18, intrinsic Z-functions
6700:
6701: 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.
6702:
6703: @section VIEW 19: Intrinsic Special Variables
6704: @cindex VIEW commands/functions, 19, intrinsic special variables
6705:
6706: Allows the user to retrieve or specify which special variables are implemented internally.
6707:
6708: @section VIEW 20: Break Service Code
6709: @cindex VIEW commands/functions, 20, break service code
6710:
6711: Allows the user to view or specify the code that will be run when a @code{BREAK} is encountered.
6712:
6713: @section VIEW 21: View Size of Last Global
6714: @cindex VIEW commands/functions, 21, view size of last global
6715:
6716: Allows the user to view the size of the last referenced global.
6717:
6718: @section VIEW 22: Count VIEW 22 Aliases
6719: @cindex VIEW commands/functions, 22, count VIEW 22 aliases
6720:
6721: Retrieves the number of VIEW 22 aliases in effect.
6722:
6723: @section VIEW 23: View Contents of Input Buffer
6724: @cindex VIEW commands/functions, 23, input buffer contents
6725:
6726: Retrieves the contents of the I/O input buffer.
6727:
6728: @section VIEW 24: Maximum Number of Screen Rows
6729: @cindex VIEW commands/functions, 24, maximum number of screen rows
6730:
6731: Retrieves the maximum number of screen rows supported in the current FreeM build.
6732:
6733: @section VIEW 25: Maximum Number of Screen Columns
6734: @cindex VIEW commands/functions, 25, maximum number of screen columns
6735:
6736: Retrieves the maximum number of screen columns supported in the current FreeM build.
6737:
6738: @section VIEW 26: DO/FOR/XECUTE Stack Pointer
6739: @cindex VIEW commands/functions, 26, DO/FOR/XECUTE stack pointer
6740:
6741: Retrieves the @code{DO}, @code{FOR}, and @code{XECUTE} stack pointer.
6742:
6743: @section VIEW 27: DO/FOR/XECUTE Stack Pointer (On Error)
6744: @cindex VIEW commands/functions, 27, DO/FOR/XECUTE stack pointer, on error
6745:
6746: Retrieves the @code{DO}, @code{FOR}, and @code{XECUTE} stack pointer (on error).
6747:
6748: @section VIEW 29: Copy Symbol Table
6749: @cindex VIEW commands/functions, 29, copy symbol table
6750:
6751: Copies the symbol table? We aren't currently aware of what this means.
6752:
6753: @section VIEW 30: Inspect Arguments
6754: @cindex VIEW commands/functions, 30, inspect arguments
6755:
6756: Retrieves the arguments passed to the @code{freem} executable.
6757:
6758: @section VIEW 31: Count Environment Variables
6759: @cindex VIEW commands/functions, 31, count environment variables
6760:
6761: Allows the user to inspect the number of variables in the process environment table.
6762:
6763: @emph{Syntax}
6764:
6765: @example
6766: WRITE $VIEW(31),!
6767: @end example
6768:
6769: @node Implementation Limits
6770: @appendix Implementation Limits
6771:
6772: @cindex limitations, memory
6773: @cindex maximum size, routine
6774: @cindex maximum size, global
6775: @cindex maximum size, string
6776:
6777: @node US-ASCII Character Set
6778: @appendix US-ASCII Character Set
6779:
6780: @multitable {Code} {Character}
6781: @item Code @tab Character
6782: @item 000 @tab @code{<NUL>}
6783: @item 001 @tab @code{<SOH>}
6784: @item 002 @tab @code{<STX>}
6785: @item 003 @tab @code{<ETX>}
6786: @item 004 @tab @code{<EOT>}
6787: @item 005 @tab @code{<ENQ>}
6788: @item 006 @tab @code{<ACK>}
6789: @item 007 @tab @code{<BEL>}
6790: @item 008 @tab @code{<BS>}
6791: @item 009 @tab @code{<HT>}
6792: @item 010 @tab @code{<LF>}
6793: @item 011 @tab @code{<VT>}
6794: @item 012 @tab @code{<FF>}
6795: @item 013 @tab @code{<CR>}
6796: @item 014 @tab @code{<SO>}
6797: @item 015 @tab @code{<SI>}
6798: @item 016 @tab @code{<DLE>}
6799: @item 017 @tab @code{<DC1>}
6800: @item 018 @tab @code{<DC2>}
6801: @item 019 @tab @code{<DC3>}
6802: @item 020 @tab @code{<DC4>}
6803: @item 021 @tab @code{<NAK>}
6804: @item 022 @tab @code{<SYN>}
6805: @item 023 @tab @code{<ETB>}
6806: @item 024 @tab @code{<CAN>}
6807: @item 025 @tab @code{<EM>}
6808: @item 026 @tab @code{<SUB>}
6809: @item 027 @tab @code{<ESC>}
6810: @item 028 @tab @code{<FS>}
6811: @item 029 @tab @code{<GS>}
6812: @item 030 @tab @code{<RS>}
6813: @item 031 @tab @code{<US>}
6814: @item 032 @tab @code{<space>}
6815: @item 033 @tab !
6816: @item 034 @tab ``
6817: @item 035 @tab #
6818:
6819:
6820: @end multitable
6821:
6822: @node FreeM Project Coding Standards
6823: @appendix FreeM Project Coding Standards
6824:
6825: @section Module Headers
6826: @cindex coding standards, module headers
6827:
1.4 snw 6828: Module headers should adhere to the following format (where @code{Dollar} should be replaced with a dollar sign):
1.1 snw 6829:
6830: @verbatim
6831: /*
1.4 snw 6832: * DollarIdDollar
1.1 snw 6833: * Function prototypes, structs, and macros for FreeM
6834: * binding library
6835: *
6836: *
1.28 snw 6837: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 6838: * Copyright (C) 1998 MUG Deutschland
1.4 snw 6839: * Copyright (C) <Year> Coherent Logic Development LLC
6840: *
6841: * This file is part of FreeM.
6842: *
6843: * FreeM is free software: you can redistribute it and/or modify
6844: * it under the terms of the GNU Affero Public License as published by
6845: * the Free Software Foundation, either version 3 of the License, or
6846: * (at your option) any later version.
6847: *
6848: * FreeM is distributed in the hope that it will be useful,
6849: * but WITHOUT ANY WARRANTY; without even the implied warranty of
6850: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6851: * GNU Affero Public License for more details.
6852: *
6853: * You should have received a copy of the GNU Affero Public License
6854: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
6855: *
6856: * DollarLogDollar
1.1 snw 6857: *
1.4 snw 6858: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
6859: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 6860: **/
6861: @end verbatim
6862:
6863: @section Variable Naming
6864: @cindex coding standards, variable naming
6865:
6866: 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.
6867:
6868: Constants defined via the C preprocessor should be in all uppercase letters, with words within them likewise delimited by underscores, such as:
6869:
6870: @verbatim
6871: #define MY_USEFUL_CONSTANT 1
6872: @end verbatim
6873:
6874: @section Indentation and General Layout
6875: @cindex coding standards, indentation
6876: @cindex coding standards, layout
6877:
6878: 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.
6879:
6880: This project follows a modified version of what is known as the Stroustrup indentation style.
6881:
6882: @section Brace Placement (Functions)
6883: @cindex coding standards, brace placement, functions
6884:
6885: 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.
6886:
6887: Below is a correct example:
6888:
6889: @verbatim
6890: int main(int argc, char **argv, char **envp)
6891: {
6892:
6893: }
6894: @end verbatim
6895:
6896: @section Brace Placement (if-for-while-do)
6897: @cindex coding standards, brace placement, if-for-while-do
6898:
6899: 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}:
6900:
6901: @verbatim
6902: if (x) {
6903: ...
6904: }
6905: else {
6906: ...
6907: }
6908:
6909: while (1) {
6910: ...
6911: }
6912:
6913: for (i = 1; i < 10; i++) {
6914: ...
6915: }
6916:
6917: do {
6918: ...
6919: } while (x);
6920: @end verbatim
6921:
6922: Single-statement if blocks should be isolated to a single line:
6923:
6924: @verbatim
6925: if (x) stmt();
6926: @end verbatim
6927:
6928: not:
6929:
6930: @verbatim
6931: if (x)
6932: stmt ();
6933: @end verbatim
6934:
6935: Notice that there is a space between @code{if} and @code{(x)}, and also between @code{stmt} and @code{()}. This should be followed throughout the code.
6936:
6937: 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:
6938:
6939: @verbatim
6940: if (x) {
6941: foo();
6942: }
6943: else if (y) {
6944: bar();
6945: }
6946: else {
6947: bas();
6948: }
6949: @end verbatim
6950:
6951: @section Labels and goto
6952: @cindex coding standards, labels
6953: @cindex coding standards, goto
6954:
6955: Labels must begin in column 1, and have two lines of vertical space above and one beneath.
6956:
6957: @section Preprocessor Conditionals
6958: @section coding standards, preprocessor conditionals
6959:
6960: I have struggled with this, but have settled upon the standard practice of keeping them in column 1.
6961:
6962: @section Overall Program Spacing
6963: @cindex coding standards, spacing of programs
6964:
6965: @itemize @bullet
6966: @item
6967: Variable declarations fall immediately beneath the opening curly brace, and should initialize the variable right there whenever initialization is used.
6968:
6969: @item
6970: One line between the last variable declaration and the first line of real code.
6971:
6972: @item
6973: 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.
6974:
6975: @item
6976: 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.
6977: @end itemize
6978:
6979: @section The switch() Statement
6980: @cindex coding standards, switch()
6981:
6982: 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:
6983:
6984: @verbatim
6985: switch(foo) {
6986:
6987: case some_const:
6988: foo();
6989:
6990: break;
6991:
6992: case some_other_const:
6993: bar();
6994:
6995: break;
6996:
6997: default:
6998: exit(1);
6999:
7000: break;
7001: }
7002: @end verbatim
7003:
7004: @section Comments
7005: @cindex coding standards, comments
7006:
7007: We use C-style comments (@code{/* comment */}) exclusively, even on single-line comments. C++ comments (@code{// comment}) are not permitted.
7008:
7009: @node Index
7010: @unnumbered Index
7011:
7012: @printindex cp
7013:
7014: @bye
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>