1 About_GTM GT.M Version 4.4 UNIX Edition October 2003 The information in this manual is subject to change without notice and should not be construed as a commitment by Sanchez Computer Associates. The software described in this manual is furnished under a license and may be used or copied only in accordance with the terms of such a license. Copyright 1987 - 2003 Sanchez Computer Associates All rights reserved GT.M, and GT.CM are trademarks of Sanchez Computer Associates. All other company and product names may be trademarks of the respective companies with which they are associated. 1 Prog_Dev_Cycle Program Development Cycle In contrast to M environments that interpret M code, GT.M compiles M code from source files into the target machine language. The GT.M compiler produces object files, which are dynamically linked into an image. Source files and object files may be managed independently, or placed together in a specific directory. GT.M permits access to source and object files in multiple directories. GT.M databases are UNIX files identified by a small file called a Global Directory. Global Directories allow management of the database files to be independent of the placement of files containing M routines. By changing the Global Directory, you can use the same programs to access different databases. Program development may utilize both GT.M and UNIX development tools. The development methodology and environment chosen for a particular installation, and tailored by the individual user, determines the actual mix of tools. These tools may vary from entirely GT.M with little UNIX, to mostly UNIX with a modest use of GT.M. Direct Mode serves as an interactive interface to the GT.M run-time environment and the compiler. In Direct Mode, the user enters M commands at the GT.M prompt, and GT.M compiles and executes the command. This feature provides immediate turnaround for rapid program development and maintenance. The methods described in the GT.M column assume you are already at the GTM> prompt, which is also called Direct Mode. To get to this prompt, type $gtm_dist/mumps -direct. 2 Def_Env_Var Defining Environment Variables GT.M requires the definition of certain environment variables as part of setting up the environment. o To locate the files that Sanchez Computer Associates provides as part of GT.M o To hold some user-controlled information which GT.M uses for run-time operation The procedure below describes how to define an environment variable. Use this procedure to define an environment variable either at the shell prompt or in your shell startup file. If you define the variable at the shell prompt, it will be effective only until you logout. If you define it in your .profile file (.cshrc, if using a C shell variant), it will be in effect whenever you log in. Your system manager may have already defined some of these variables. Each environment variable required by GT.M is described and illustrated in individual sections following the procedure. Only gtm_dist, and in some cases gtmgbldir, gtm_principal and gtmroutines, are required by users who do not perform programming activities. To define an environment variable type the following commands: $ env_variable=env_variable_value $ export env_variable The following environment variables hold information that determines some details of GT.M run-time operation, over which the user has control. 3 gtm_dist gtm_dist gtm_dist is used to establish the location of the installed GT.M program and support files. The syntax for gtm_dist is as follows: $ gtm_dist= The standard installation places these files in /gtm/bin. Example: $ gtm_dist=/usr/staff/smith/GTM.dist $ export gtm_dist This identifies /usr/staff/smith/GTM.dist as the location of the installed GT.M files. Add gtm_dist to your PATH environment variable to have UNIX search the GT.M installation directory (when processing a command to activate or run an image). This allows you to activate GT.M and the utilities without explicitly specifying a path. To add gtm_dist to your PATH type the following commands: $ PATH=$PATH:$gtm_dist $ export PATH Most of the examples in this manual assume that you have added gtm_dist to your PATH. 3 gtmgbldir gtmgbldir gtmgbldir defines the path to a Global Directory. A Global Directory maps global variables to physical database files, and is required to locate M global variables. gtmgbldir provides the initial value for $ZGBLDIR, the intrinsic special variable that connects the GT.M run-time system to the Global Directory. It also connects the Global Directory to the utilities requiring one. If you maintain multiple global directories, define gtmgbldir to the Global Directory you currently want to use. The syntax of a gtmgbldir definition is: $ gtmgbldir=/directory/filename.gld Example: $ gtmgbldir=/usr/staff/mumps.gld $ export gtmgbldir This specifies /usr/staff as the directory containing the Global Directory file named mumps.gld. 3 gtm_principal gtm_principal The gtm_principal environment variable specifies the value for $principal, which designates the absolute pathname of the principal $IO device. This is an MDC Type A enhancement to standard M. The following is an example of gtm_principal definition: $ gtm_principal=/usr/filename $ export gtm_principal This specifies the /usr/filename as the principal $IO device, effective until changed further or until you logout of the particular session. 3 gtmroutines gtmroutines The gtmroutines environment variable specifies a search list of possible locations for M routines. This value is used to initialize $ZROUTINES, (the intrinsic special variable that enables GT.M to find the routine (program) you want to run). gtmroutines is required for ZLINKing. gtmroutines is particularly helpful in calling percent utilities and the Global Directory Editor (GDE), which are in gtm_dist. $ gtmroutines="directories in search list" The directories in the search list must be separated by a space and enclosed in quotation marks (" "). Environment variables are accepted in the search list. The following is an example of gtmroutines definition: $ gtmroutines=". $gtm_dist" $ export gtmroutines This specifies that GT.M search for a routine first in the current directory (.), then in the distribution directory (which is identified by the environment variable gtm_dist). The distribution directory is included in the list because it contains the percent routines. You will probably want the search list to contain these two items at a minimum. In addition, you may want to add directories of your own. 3 Editor Editor The EDITOR environment variable specifies the UNIX text editor used when editing a routine either from the shell or with ZEDIT. Since this is a standard part of establishing your UNIX environment, you will probably only need to define this when you want to use a different editor than the one defined in your shell startup file. Example: $ EDITOR=/usr/bin/vi $ export EDITOR This defines the current text editor to vi. 2 Prep_the_DB Preparing the Database GT.M databases consist of one or more UNIX files. Most database files have a UNIX file structure externally and a GT.M Database Structure (GDS) internally. Management of the GDS files by the GT.M run-time system assures high performance and integrity. GT.M database files are coordinated by a Global Directory. The Global Directory identifies which global names belong in which files, and specifies the creation characteristics for each file. To specify access to a database, each M process must define the gtmgbldir environment variable to point to the associated Global Directory. To define and maintain a Global Directory, use the Global Directory Editor ( GDE) utility. The GDE utility automatically upgrades existing global directories to the current format.The MUPIP command CREATE uses the characteristics as defined in the Global Directory to create the associated database. In a production environment, the system manager typically maintains Global Directories. For more information on GDE and MUPIP refer to the "Global Directory Editor" and "MUPIP" chapters in the GT.M Administration and Operations Guide . Example: This example is a sequence of events that illustrate steps you might typically perform in creating a new global directory, in our example PAYROLL.GLD. To assist you in following the sequence, each actual step appears in typewriter font, as you might see on your terminal screen, followed by an explanation in normal text font. $ ls payroll.gld payroll.gld not found The ls command verifies that there are no existing files with the name payroll.gld. $ gtmgbldir=payroll.gld $ export gtmgbldir This establishes the current value of the environment variable gtmgbldir as payroll.gld. GT.M uses gtmgbldir to identify the current Global Directory. When defined at the shell prompt, gtmgbldir maintains the defined value only for the current login session. The next time you log into UNIX, you must again define the value of gtmgbldir as payroll.gld to use it as the current Global Directory. This example defines gtmgbldir without a full pathname. The environment variable points to the payroll.gld file in the current working directory. Therefore if the default directory changes, GT.M attempts to locate the Global Directory in the new default directory and cannot use the original file. If you intend for the Global Directory to consistently point to this file, even if the default directory changes, use a full file-specification for gtmgbldir. $ gtm GTM>d ^GDE %GDE-I-GDUSEDEFS, Using defaults for Global Directory /staff/payroll.gld GDE> This invokes the Global Directory Editor from the GT.M prompt and produces an informational message. Refer to the "Program Development Cycle" in GT.M Programmer's Guide for more details. Example: $ mupip load payroll.gld GT.M 09-OCT-2001 11:26:44 keycnt: 100 max subsc len:12 max data len: 3 Last record number: 202 This uses the MUPIP LOAD command to load a sequential file into the database. Because MUPIP uses the environment variable gtmgbldir to locate a Global Directory, which identifies the database file(s), the LOAD command does not require any information about the target database. With few exceptions, the GT.M utilities work in the same way. For general information on shareable libraries in HP-UX, refer to the "Programming on HP-UX" manual. Refer to the documentation accompanying AIX for more information on shareable libraries on AIX. entryref: return-value routine-name (parameter, parameter, ..) where entryref is an M entryref, return-value is xc_long_t, xc_status_t, or void and parameter are in the format: direction:type. len: void length (I:xc_float_t*, o:xc_float_t*) Example: % echo $GTMXC_mathpak 2 Cre_Edt_Source_Prog Creating and Editing a Source Program The first step in developing a GT.M program is to create a source file. In most cases, the user can create and modify GT.M source programs using UNIX text editors. When the program is very simple (and its lines do not need revision after they are entered), you can use the cat command to direct input from your terminal to your source file. 3 Edit_from_GTM Editing from GT.M Invoke Direct Mode to create and edit a source program in GT.M. At the GTM> prompt, invoke the editor by typing: ZEDIT ZEDIT invokes the editor specified by the EDITOR environment variable, which creates a seperate file for each M source module. The GT.M environment works most efficiently if the file has the same name as the M routine it contains, and has an .m extension. Since ZEDIT automatically defaults the.m extension, it is not necessary to specify an extension unless you require a different one. If you use another extension, you must specify that extension with every reference to the file. Multiple character file extensions are permitted for M source file names. 3 Edit_from_Shell Editing from the Shell To create and edit a source program from the shell, invoke any text editor at the shell prompt and specify a UNIX file as the source. The GT.M environment works best when you give a file the name of the M routine that it contains, and an .m extension. Example: $ vi payroll.m The vi command initiates an editing session for payroll.m from the shell prompt. If payroll.m does not already exist, vi creates it. Because this example uses UNIX rather than GT.M tools, we must specify the .m file extension. 2 Comp_Source_Prog Compiling a Source Program GT.M compiles M source code files and produces object files for complete integration into the UNIX enviroment. The object modules have the same name as the compiled M source file with an .o file extension, unless otherwise specified. The object files contain machine instructions and information necessary to connect the routine with other routines, and map it into memory. An M routine source file must be compiled after it is created or modified. You can compile explicitly with the ZLINK command or implicitly with auto-ZLINK. At the shell command line, compile by issuing the mumps command. The compiler checks M code for syntax errors and displays error messages on the terminal, when processing is complete. Each error message provides the source line in error with an indicator pointing to the place on the line where the error is occurring. For a list and description of the compiler error messages, refer to the GT.M Message and Recovery Procedures Reference Manual. You can generate a listing file containing the compile results by including the -list qualifier as a modifier to the argument to the ZLINK command in Direct Mode. This can also be done by redirecting the compiler messages to a file by adding >filename 2>&1 to the mumps command when compiling a program from the shell. Refer to the "Compiling from the Shell" section for an explanation of the M command describing -list, and other valid qualifiers for the M and ZLINK commands. The compiler stops processing a routine line when it detects an error on that line. Under most conditions the compiler continues processing the remaining routine lines. This allows the compiler to produce a more complete error analysis of the routine and to generate code that may have valid executable paths. The compiler does not report multiple syntax errors on the same line. When it detects more than 127 syntax errors in a source file, the compiler ceases to process the file. 3 Comp_from_GTM Compiling from GT.M In Direct Mode, GT.M provides access to the compiler explicitly through the ZLINK and ZCOMPILE commands, and implicitly through automatic invocation of ZLINK functionality (auto-ZLINK) to add required routines to the image. ZCOMPILE is a GT.M routine compilation command, it compiles the routine and creates a new object module. The primary task of ZLINK is to place the object code in memory and "connect" it with other routines. However, under certain circumstances, ZLINK may first use the GT.M compiler to create a new object module. The difference between ZCOMPILE and ZLINK is that ZCOMPILE creates a new object module on compiling, whereas the ZLINK command links the object module with other routines and places the object code in memory. ZLINK compiles under these circumstances: o ZLINK cannot locate a copy of the object module but can locate a copy of the source module. o ZLINK can locate both object and source module, and finds the object module to be older than the source module. o The file-specification portion of the ZLINK argument includes an explicit extension of .m. Auto-ZLINK compiles under the first two circumstances, but can never encounter the last one. When a command refers to an M routine that is not part of the current image, GT.M automatically attempts to ZLINK and, if necessary, compile that routine. In Direct Mode, the most common method to invoke the compiler through an auto-ZLINK is to enter DO ^routinename at the GTM> prompt. When the current image does not contain the routine, GT.M does the following: o Locates the source and object o Determines whether the source has been edited since it was last compiled o Compiles the routine, if appropriate o Adds the object to the image By using the DO command, you implicitly instruct GT.M to compile, link, and execute the program. With this method, you can test your routine interactively. For complete descriptions of ZLINK and auto-ZLINK, refer to the "Commands" chapter in GT.M Programmer's Guide. Example: GTM>do ^payroll GTM>do ^taxes This uses the M DO command to invoke the GT.M compiler implicitly from the GTM> prompt if the routine requires new object code. When the compiler runs, it produces two object module files, payroll.o and taxes.o. If you receive error messages from the compilation, you may fix them immediately by returning to the editor and correcting the source. By default, the GT.M compiler operates in "compile-as-written" mode, and produces object code even when a routine contains syntax errors. This code includes all lines that are correct and all commands on a line with an error, up to the error. Therefore, you may decide to tailor the debugging cycle by running the program without removing the syntax errors. 3 Comp_from_Shell Compiling from the Shell From the shell, invoke the compiler by entering mumps file-name at the shell prompt. Example: $ mumps payroll.m $ mumps taxes.m This uses the mumps command to invoke the GT.M compiler from the shell prompt, and creates .o versions of these files. Use the mumps command at the shell prompt to: o Check the syntax of a newly entered program. o Optionally, get a formatted listing of the program. o Ensure that all object code is up to date before linking. The mumps command invokes the compiler to translate an M source file into object code. The format for the MUMPS command is: MUMPS [-qualifier[...]] pathname o Source programs must have an extension of .m. o Each pathname identifies an M source program to compile. o Qualifiers determine characteristics of the compiler output. o Qualifiers must appear after the command, but before the file name to be properly applied. o GT.M allows the UNIX * and ? wildcards in a file name. The * wildcard accepts any legal combination of numbers and characters including a null, in the position the wildcard holds. The ? wildcard accepts exactly one legal character in its position. For example, mumps *.m compiles all files in the current default directory with an .m extension. mumps *pay?.m compiles .m files with names that contain any characters followed by pay, followed by one character. Unlike when using ZLINK or ZCOMPILE, the filename must be fully specified when compiling from the shell. 1 Opr_Dbg_Dir_Mode Operating and Debugging in Direct Mode Direct Mode is an important tool in GT.M because it allows you to interactively debug, modify, and execute M routines. Direct Mode is a shell that immediately compiles and executes GT.M commands providing an interpretive-like interface. M simplifies debugging by using the same commands for debugging that are used for programming. The focus of this chapter is to describe the debugging process in Direct Mode, and to illustrate the GT.M language extensions that enhance the process. Command functionality is described only in enough detail to illustrate why a particular command is useful for a debugging activity being described. If you have specific functionality questions about a command or variable, refer to the "Commands", "Functions" or "Intrinsic Special Variables" chapters in GT.M Programmer's Guide. 2 Opr_Dir_Mode Operating in Direct Mode This section provides an overview of the following basic operational issues in Direct Mode: o Entering Direct Mode o Available functionality o Exiting Direct Mode 3 Entr_Dir_Mode Entering Direct Mode To enter Direct Mode, type $gtm_dist/mumps -direct at the shell prompt. Example: $ $gtm_dist/mumps -direct GTM> This shows using $gtm_dist/mumps -direct at the prompt to enter Direct Mode. To create a gtm alias in your shell startup file (in the example below the startup file is assumed to be a .profile file): o Open an edition session for your .profile file by typing: $vi .profile o Add a function to the file to define your gtm alias o gtm() { $gtm_dist/mumps -direct } o save the file. Now, when you want to enter Direct Mode for an editing or debugging session, simply type gtm at the shell prompt. Example: $ gtm GTM> This shows that the gtm alias typed at the shell prompt also takes you to the Direct Mode. 3 Func_in_Dir_Mode Functionality Available in Direct Mode This section provides an overview of basic functionality and concepts that enhance your use of Direct Mode. 4 Comm_Recall Command Recall Direct Mode includes a line command recall function to display previously entered command lines. Use the Up Arrow key at the GTM> prompt to scroll back through command lines. Usethe Down Arrow key to scroll forward through the command lines. GT.M displays one command line at a time. You may delete and reenter characters starting at the end of a recalled line. The RECALL command is another way to access previously entered Direct Mode command lines. RECALL is only valid in Direct Mode and causes an error if it appears in other M code. The format of the RECALL command is: REC[ALL] [intlit|strlit] o The optional integer literal specifies a previously entered command by the counting back from the present. o The optional string literal specifies the most recently entered command line that starts with characters matching the (case-sensitive) literal. o When the RECALL command has no argument, it displays up to a maximum of 99 available past Direct Mode entries. If the Direct Mode session has just started, you may not have entered 99 lines for GT.M to save and therefore you will not have 99 lines to look at. The most recently entered GT.M command line has the number one (1), older lines have higher numbers. GT.M does not include the RECALL command in the listing. If the RECALL command is issued from a location other than the Direct Mode prompt, GT.M issues a run-time error. Example: GTM>WRITE $ZGBLDIR M.GLD GTM>SET $ZGBLDIR TEST.GLD GTM>SET A=10 GTM>SET B=A GTM>REC 1 SET B=A 2 SET A=10 3 SET $ZGBLDIR TEST.GLD 4 WRITE $ZGBLDIR This REC[ALL] command displays the previously entered commands. You can also display a selected command by entering RECALL and the line number of the command you want to retrieve. Example: GTM>REC 2 GTM>SET A=10 This RECALLs the line number two (2). If the RE[CALL] command includes a text parameter, GT.M displays the most recent command matching the text after the RE[CALL] command. Example: GTM>REC WRITE GTM>WRITE $ZGBLDIR MUMPS.GLD This RECALLs "WRITE", the command most recently beginning with this text. Note that the RECALL command text is case sensitive. The RECALL command with a text argument treats WRITE and write differently, that is, it treats them case sensitively. If you first type the WRITE command in lower-case and then type WRITE in upper-case to recall it, the RECALL command does not find a match. 4 Line_Editing Line Editing GT.M permits the use of the GT.M command line editor at the Direct Mode prompt and during M READs from a terminal. The GT.M line editor allows cursor positioning using the key, edit keypad and function keys. The GT.M Direct Mode line editing keys are as follows: Backspace Deletes the character to the left of the cursor Delete Same as backspace Up-arrow Moves to a less recent item in the RECALL list Down-arrow Moves to a more recent item in the RECALL list Left-arrow Moves the cursor one character to the left Right-arrow Moves the cursor one character to the right Moves the cursor to the beginning of the line Moves the cursor one character towards the beginning of the line Deletes the character at the cursor position Moves the cursor to the end of the line Moves the cursor one character towards the end of the line Deletes all characters from the cursor to the end of the line Deletes the entire line 4 M_Invo_Stack The M Invocation Stack The ANSI M Standard describes certain M operations in terms of how a stack-based virtual machine would operate. A stack is a repository for tracking temporary information on a "last-in/first-out" (LIFO) basis. M program behavior can be understood using a stack-based model. However, the standard is not explicit in defining how an implementation must maintain a stack or even whether it must use one at all. The stack model provides a trail of routines currently in progress that shows the location of all the M operations that performed the invocations leading to the current point. 3 Exit_Dir_Mode Exiting Direct Mode Four M commands terminate a Direct Mode session: o HALT o ZCONTINUE o GOTO o ZGOTO The HALT command exits Direct Mode and terminates the M process. The ZCONTINUE command instructs GT.M to exit Direct Mode and resume routine execution at the current point in the M invocation stack. This may be the point where GT.M interrupted execution and entered Direct Mode. However, when the Direct Mode interaction includes a QUIT command, it modifies the invocation stack and causes ZCONTINUE to resume execution at another point. The GOTO and ZGOTO commands instruct GT.M to leave Direct Mode, and transfer control to a specified entry reference. 2 Debug_Rtn_Dir_Mode Debugging a Routine in Direct Mode To begin a debugging session on a specific routine, type the following command at the GTM prompt: GTM>DO ^routinename You can also begin a debugging session by pressing after running an M application at the shell. To invoke Direct Mode by pressing , process must have the Principal Device in the CENABLE state and not have the device set to CTRAP=$C(3). When GT.M receives a command from the principal device, it invokes Direct Mode at the next opportunity, (usually at a point corresponding to the beginning of the next source line). GT.M can also interrupt at a FOR loop iteration or during a command of indeterminate duration such as JOB, LOCK, OPEN or READ. The GT.M USE command enables/disables the interrupt with the [NO]CENABLE deviceparameter. By default, GT.M starts enabled. The default setting for handling is controlled by GTM$DEFAULTS.M64 and is enabled in the distribution version of that file. GT.M displays the GTM> prompt on the principal device. Direct Mode accepts commands from, and reports errors to, the principal device. GT.M uses the current device for all other I/O. If the current device does not match the principal device when GT.M enters Direct Mode, GT.M issues a warning message on the principal device. A USE command changes the current device. For more information on the USE command, refer to the "Input/Output Processing" chapter. The default "compile-as-written" mode of the GT.M compiler lets you run a program with errors as part of the debugging cycle. The object code produced includes all lines that are correct and all commands on a line with an error, up to the error. When GT.M encounters an error, it XECUTEs non empty values of $ETRAP or $ZTRAP. By default $ZTRAP contains a BREAK command, so GT.M enters Direct Mode. The rest of the chapter illustrates the debugging capabilities of GT.M by taking a sample routine, dmex, through the debugging process. dmex is intended to read and edit a name, print the last and first name, and terminate if the name is an upper-case or lower-case "Q". Each of the remaining sections of the chapter uses dmex to illustrate an aspect of the debugging process in GT.M. 3 Creat_Display_M_Rtn Creating and Displaying M Routines To create or edit a routine, use the ZEDIT command. ZEDIT invokes the editor specified by the EDITOR environment variable, and opens the specified file. dmex.m, for editing. Example: GTM>ZEDIT "dmex" Once in the editor, use the standard editing commands to enter and edit text. When you finish editing, save the changes, which returns you to Direct Mode. For further details and examples, refer to the GT.M Programmer's Guide. 3 Exec_M_Rtn_Inter Executing M Routines Interactively To execute an M routine interactively, it is not necessary to explicitly compile and link your program. When you refer to an M routine that is not part of the current image, GT.M automatically attempts to compile and ZLINK the program. Example: GTM>DO ^dmex Name: Revere, Paul %GTM-E-UNDEF, Undefined local variable: bame At M source location name+3^dmex GTM> In this example GT.M places you in Direct Mode, but also cites an error found in the program with a run-time error message. In this example, it was a reference to bame, which is undefined. To see additional information about the error message, examine the $ECODE or $ZSTATUS special variables. $ECODE is read-write intrinsic special variable that maintains a list of comma delimited codes that describe a history of past errors - the most recent ones appear at the end of the list. In $ECODE, standard errors are prefixed with an "M", user defined errors with a "U", and GT.M errors with a "Z". A GT.M code always follows a standard code. $ZSTATUS is a read-write intrinsic special variable that maintains a string containing the error condition code and location of the last exception condition occurring during routine execution. GT.M updates $ZSTATUS only for errors found in routines and not for errors entered at the Direct Mode prompt. For further details and examples, refer to the GT.M Programmer's Guide. 3 Proc_with_Runtime_Syn_Err Processing with Run-time and Syntax Errors When GT.M encounters a run-time or syntax error, it stops executing and displays an error message. GT.M reports the error in the message. In this case, GT.M reports an undefined local variable and the line in error, name+3^dmex. Note that GT.M re-displays the GTM> prompt so that debugging may continue. To re-display the line and identify the error, use the ZPRINT command. Example: GTM>ZPRINT, name+3 %GTM-E-SPOREOL, Either a space or an end-of-line was expected but not found ZP, name+3 ^_____ GTM> This example shows the result of incorrectly entering a ZPRINT command in Direct Mode. GT.M reports the location of the syntax error in the command line with an arrow. $ECODE and $ZSTATUS do not maintain this error message because GT.M did not produce the message during routine execution. Enter the correct syntax, (i.e., remove the comma) to re-display the routine line in error. Example: GTM>WRITE $ZPOS name+3^dmex This example writes the current line position. $ZPOSITION is a read-only GT.M special variable that provides another tool for locating and displaying the current line. It contains the current entry reference as a character string in the format label+offset^routine, where the label is the closest preceding label. The current entry reference appears at the top of the M invocation stack, which can also be displayed with a ZSHOW "S" command. To display the current value of every local variable defined, use the ZWRITE command with no arguments. Example: GTM>ZWRITE ln=12 name="Revere, Paul" This ZWRITE displays a listing of all the local variables currently defined. ZWRITE displays the variable name. ZWRITE does not display a value for bame, confirming that it is not defined. 3 Correcting_Errors Correcting Errors Use the ZBREAK command to establish a temporary breakpoint and specify an action. ZBREAK sets or clears routine-transparent breakpoints during debugging. This command simplifies debugging by interrupting execution at a specific point to examine variables, execute commands, or to start using ZSTEP to execute the routine line by line. GT.M suspends execution during execution when the entry reference specified by ZBREAK is encountered. If the ZBREAK does not specify an expression "action", the process uses the default, BREAK, and puts GT.M into Direct Mode. If the ZBREAK does specify an expression "action", the process XECUTEs the value of "action", and does not enter Direct Mode unless the action includes a BREAK. The action serves as a "trace-point". The trace-point is silent unless the action specifies terminal output. Example: GTM>ZBREAK name+3^dmex:"set bame=name" This uses a ZBREAK with an action that SETs the variable bame equal to name. 3 Stepping_Thru_Rtn Stepping Through a Routine The ZSTEP command provides a powerful tool to direct GT.M execution. When you issue a ZSTEP from Direct Mode, GT.M executes the program to the beginning of the next target line and performs the ZSTEP action. The optional keyword portion of the argument specifies the class of lines where ZSTEP pauses its execution, and XECUTEs the ZSTEP action specified by the optional action portion of the ZSTEP argument. If the action is specified, it must be an expression that evaluates to valid GT.M code. If no action is specified, ZSTEP XECUTEs the code specified by the $ZSTEP intrinsic special variable; by default $ZSTEP has the value "B", which causes GT.M to enter Direct Mode. ZSTEP actions, that include commands followed by a BREAK, perform the specified action, then enter Direct Mode. ZSTEP actions that do not include a BREAK perform the command action and continue execution. Use ZSTEP actions that issue conditional BREAKs and subsequent ZSTEPs to perform tasks such as test for changes in the value of a variable. Use ZSTEP to incrementally execute a routine or a series of routines. Execute any GT.M command from Direct Mode at any ZSTEP pause. To resume normal execution, use ZCONTINUE. Note that ZSTEP arguments are keywords rather than expressions, and they do not allow indirection. Example: GTM>ZSTEP INTO Break instruction encountered during ZSTEP action At M source location print^dmex GTM>ZSTEP OUTOF Paul Revere Name: Q %GTM-I-BREAKZST, Break instruction encountered during ZSTEP action At M source location name^dmex GTM>ZSTEP OVER Break instruction encountered during ZSTEP action At M source location name+1^dmex This example shows using the ZSTEP command to step through the routine dmex, starting where execution was interrupted by the undefined variable error. The ZSTEP INTO command executes line name+3 and interrupts execution at the beginning of line print. The ZSTEP OUTOF continues execution until line name. The ZSTEP OVER, which is the default, executes until it encounters the next line at this level on the M invocation stack. In this case, the next line is name+1. The ZSTEP OVER could be replaced with a ZSTEP with no argument because they do the same thing. 3 Cont_Exec_Frm_Breakpt Continuing Execution From a Breakpoint Use the ZCONTINUE command to continue execution from the breakpoint. Example: GTM>ZCONTINUE Paul Revere Name: q Name: QUIT Name: ? Please use last-name, first name middle-initial or 'Q' to Quit. Name: This uses a ZCONTINUE command to resume execution from the point where it was interrupted. As a result of the ZBREAK action, bame is defined and the error does not occur again. Because the process does not terminate as intended when the name read has q as a value, we need to continue debugging. 3 Interr_Execution Interruption Execution Press to interrupt execution, and return to the GTM prompt to continue debugging the program. Example: %GTM-I-CTRLC, CTRLC_C encountered. GTM> This invokes direct mode with a . 3 Using_Invoc_Stac_in_Debug Using the Invocation Stack in Debugging M DOs, XECUTEs, and extrinsics add a level to the invocation stack. Matching QUITs take a level off the stack. When GT.M executes either of these commands, an extrinsic function, or an extrinsic special variable, it "pushes" information about the new environment on the stack. When GT.M executes the QUIT, it "pops" the information about the discarded environment off the stack. It then reinstates the invoking routine information using the entries that have now arrived at the active end of the stack. In the M stack model, a FOR command does not add a stack frame, and a QUIT that terminates a FOR loop does not remove a stack frame. 4 Deter_Levels_of_Nest Determining Levels of Nesting $STACK contains an integer value indicating the "level of nesting" caused by DO commands, XECUTE commands, and extrinsic functions in the M virtual stack. $STACK has an initial value of zero (0), and increments by one with each DO, XECUTE, or extrinsic function. Any QUIT that does not terminate a FOR loop or any ZGOTO command decrements $STACK. In accordance with the M standard, a FOR command does not increase $STACK. M routines cannot modify $STACK with the SET or KILL commands. Example: GTM>WRITE $STACK 2 GTM>WRITE $ZLEVEL 3 GTM> This example shows the current values for $STACK and $ZLEVEL. $ZLEVEL is like $STACK except that uses one (1) as the starting level for the M stack, which $STACK uses zero (0), which means that $ZLEVEL is always one more than $STACK. Using $ZLEVEL with "Z" commands and functions, and $STACK with standard functions avoids the need to calculate the adjustment. 4 Look_Invoc_Stack Looking at the Invocation Stack The $STACK intrinsic special variable and the $STACK() function provide a mechanism to access M stack context information. Example: GTM>WRITE $STACK 2 GTM>WRITE $STACK(2,"ecode") ,M6,Z150373850, GTM>WRITE $STACK(2,"place") name+3^dmex GTM>WRITE $STACK(2,"mcode") if ln<30,bame?1.a.1"-".a1","1" "1a.ap do print q GTM> This example gets the value of $STACK and then uses that value to get various types of information about that stack level using the $STACK() function. The "ecode" value of the error information for level two, "place" is similar to $ZPOSITION, "mcode" is the code for the level. In addition to the $STACK intrinsic special variable, which provides the current stack level, $STACK(-1) gives the highest level for which $STACK() can return valid information. Until there is an error $STACK and $STACK(-1) are the same, but once $ECODE shows that there is an "current" error, the information returned by $STACK() is frozen to capture the state at the time of the error; it unfreezes after a SET $ECODE="". Example: GTM>WRITE $STACK 2 GTM>WRITE $STACK(-1) 2 GTM> This example shows that under the conditions created (in the above example), $STACK and $STACK(-1) have the same value. The $STACK() can return information about lower levels. Example: +1^GTM$DMOD GTM>WRITE $STACK(1,"ecode") GTM>WRITE $STACK(1,"place") beg^dmex GTM>WRITE $STACK(1,"mcode") beg for read !,"Name:",namde do name GTM> This example shows that there was no error at $STACK level one, as well as the "place" and "mcode" information for that level. 4 Using_ZSHOW_Ex_Context_Info Using ZSHOW to Examine Context Information The ZSHOW command displays information about the M environment. Example: GTM>ZSHOW "*" $DEVICE="" $ECODE=",M6,Z150373850," $ESTACK=2 $ETRAP="" $HOROLOG="59149,36200" $IO="/dev/pts/17" $JOB=310051 $KEY="" $PRINCIPAL="/dev/pts/17" $QUIT=0 $REFERENCE="" $STACK=2 $STORAGE=1072300032 $SYSTEM="47,gtm_sysid" $TEST=1 $TLEVEL=0 $TRESTART=0 $X=0 $Y=23 $ZA=0 $ZB=$C(13) $ZCMDLINE="" $ZCOMPILE="" $ZCSTATUS=0 $ZDIRECTORY="/ext1/home/" $ZEDITOR=0 $ZEOF=0 $ZERROR="Unprocessed $ZERROR, see $ZSTATUS" $ZGBLDIR="/ext1/home/mumps.gld" $ZININTERRUPT=0 $ZINTERRUPT="IF $ZJOBEXAM()" $ZIO="/dev/pts/17" $ZJOB=0 $ZLEVEL=3 $ZMODE="INTERACTIVE" $ZPOSITION="name+3^dmex" $ZPROCESS="" $ZPROMPT="GTM>" $ZROUTINES=". /usr/library/gtm_dist" $ZSOURCE="" $ZSTATUS="150373850,name+3^dmex, %GTM-E-UNDEF, Undefined local variable: bame" $ZSYSTEM=0 $ZTRAP="B" $ZVERSION="GT.M V4.3-001D AIX RS6000" $ZYERROR="" bame="?" ln=12 name="" /dev/pts/17 OPEN TERMINAL NOPAST NOESCA NOREADS TYPE WIDTH=80 LENG=24 name+3^dmex ($ZTRAP) (Direct mode) beg^dmex ^GTM$DMOD (Direct mode) GTM> This example uses the asterisk (*) argument to show all information that ZSHOW offers in this context. First are the Intrinsic Special Variables ($DEVICE-$ZYERROR, also available with ZSHOW "I"), then the local variables (bame, ln and name, also available with ZSHOW "V"), then the ZBREAK locations (name+3^dmex, also available with ZSHOW "B"), then the device information (also available with ZSHOW "D"), then the M stack (also available with ZSHOW "S"). ZSHOW "S" is the default for ZSHOW with no arguments. Context information that does not exist in this example includes M LOCKs of this process ( ZSHOW "L"). In addition to directing its output to the current device, ZSHOW can place its output in a local or global variable array. For more information, refer to the ZSHOW section of the "Commands" chapter in GT.M Programmer's Guide. ZSHOW "V" produces the same output as ZWRITE with no arguments, but ZSHOW "V" can be directed to a variable as well as a device. 3 Transf_Rtn_Control Transferring Routine Control The ZGOTO command transfers control from one part of the routine to another, or from one routine to another, using the specified entry reference. The ZGOTO command takes an optional integer expression that indicates the M stack level reached by performing the ZGOTO, and an optional entry reference specifying the location to where ZGOTO transfers control. A ZGOTO command, with an entry reference, performs a function similar to the GOTO command with the additional capability of reducing the M stack level. In a single operation, the process executes $ZLEVEL-intexpr, implicit QUITs from DO or extrinsic operations, and a GOTO operation transferring control to the named entry reference. The ZGOTO command leaves the invocation stack at the level of the value of the integer expression. GT.M implicitly terminates any intervening FOR loops and unstacks variables stacked with NEW commands, as appropriate. ZGOTO $ZLEVEL:LABEL^ROUTINE takes the same action as GO LABEL^ROUTINE. ZGOTO $ZLEVEL-1 produces the same result as QUIT (followed by ZCONTINUE, if in Direct Mode). If the integer expression evaluates to a value greater than the current value of $ZLEVEL, or less than zero (0), GT.M issues a run-time error. If ZGOTO has no entry reference, it performs some number of implicit QUITs and transfers control to the next command at the specified level. When no argument is specified, ZGOTO 1 is the result, and operation resumes at the lowest level M routine as displayed by ZSHOW "S". In the image invoked by mumps -direct, or a similar image, a ZGOTO without arguments returns the process to Direct Mode. 3 Disp_Source_code Displaying Source Code Use the ZPRINT command to display source code lines selected by its argument. ZPRINT allows you to display the source for the current routine and any other related routines. Use the ZPRINT command to display the last call level. Example: GTM>ZPRINT beg beg for read !,"Name: ",name do name This example uses a ZPRINT command to print the line indicated as the call at the top of the stack. Notice that the routine has an error in logic. The line starting with the label beg has a FOR loop with no control variable, no QUIT, and no GOTO. There is no way out of the FOR loop. 3 Correct_Errs_in_M_Rtn Correcting Errors in an M Routine Now that the routine errors have been identified, correct them in the M source file. Use ZEDIT to invoke the editor and open the file for editing. Correct the errors previously identified and exit the editor. Example: GTM>ZEDIT "dmex" dmex ;dmex - Direct Mode example ; beg for read !,"Name: ",name do name q:name="Q" quit name set ln=$l(name) if ln,$e("QUIT",1,ln)=$tr(name,"quit","QUIT") d q . s name="Q" if ln<30,name?1.a.1"-".a1","1" "1a.ap do print q write !,"Please use last-name, " write "first-name middle-initial or 'Q' to Quit." quit print write !,$p(name,", ",2)," ",$p(name,", ") quit GTM> This example shows the final state of a ZEDIT session of dmex.m. Note that the infinite FOR loop at line beg is corrected. 3 Relink_Edited_Rtn Relinking the Edited Routine Use the ZLINK command to add the edited routine to the current image. ZLINK automatically recompiles and relinks the routine. If the routine was the most recent one ZEDITed or ZLINKed, you do not have to specify the routine name with the ZLINK command. You may have to issue a ZGOTO or a QUIT command to remove the unedited version of the routine from the M invocation stack before ZLINKing the edited version. Example: GTM>ZLINK Cannot ZLINK an active routine This illustrates a GT.M error report caused by an attempt to ZLINK a routine that is part of the current invocation stack. To ZLINK the routine, remove any invocation levels for the routine off of the call stack. You may use the ZSHOW "S" command to display the current state of the call stack. Use the QUIT command to remove one level at a time from the call stack. Use the ZGOTO command to remove multiple levels off of the call stack. For further details and examples, refer to the GT.M Programmer's Guide. 3 Reexec_the_Rtn Re-executing the Routine Re-display the DO command using the RECALL command. Execute the routine using the DO command. Example: GTM>D ^dmex Name: Revere, Paul Paul Revere Name: q This example illustrates a successful execution of dmex. 3 Using_Forked_Proc Using Forked Processes The ZSYSTEM command creates a new process called the child process, and passes its argument to the shell for execution. The new process executes in the same directory as the initiating process. The new process has the same operating system environment, such as environment variables and input/output devices, as the initiating process. The initiating process pauses until the new process completes before continuing execution. Example: GTM>ZSYSTEM $ ls dmex.* dmex.m dmex.o $ ps PID TTY TIME COMMAND 7946 ttyp0 0:01 sh 7953 ttyp0 0:00 gtm 7955 ttyp0 0:00 ps $ exit GTM> This example uses ZSYSTEM to create a child process, perform some shell actions, and return to GT.M. 1 Lang_Features_M General Language Features of M MUMPS is a general purpose language with an embedded database system. This section of the help file describes the features of the language that are not covered as Commands, Functions, or Intrinsic Special Variables. 2 Data_Types Data Types M operates with a single basic data type, string. However, M evaluates data using methods that vary according to context. 3 Num_Expressions Numeric Expressions When M syntax specifies a numexpr, M evaluates the data as a sequence of ASCII characters that specify a number. M stops the evaluation and provides the result generated from successfully evaluated characters when it encounters any character that is not the following: o A digit 0-9 o A plus sign (+) or minus sign (-) and also the first character in the string o The first decimal point (.) in the string 3 Num_Accuracy Numeric Accuracy GT.M provides 18 digits of accuracy, independent of the decimal point (.) placement, and a numeric range from 10**(-43) to (10**47). Numbers with three digits or fewer to the right of the decimal point are precise. 3 Int_Expressions Integer Expressions When M syntax specifies an intexpr, M evaluates the data as it would a numexpr except that it stops the evaluation at any decimal point including the first. 3 Truth_valued_Expr Truth-valued Expressions When M syntax specifies a tvexpr, M evaluates the data as a numeric. However, it stops the evaluation and returns a true value (1) as soon as it encounters a non-zero digit, otherwise it returns a false value (0). In other words, M treats expressions that have a non-zero numeric value as true, and expressions that have a zero numeric value as false. The sign and/or decimal have no affect on the evaluation of a truth-valued expression. 2 M_Names M Names M uses names for variables, LOCK command arguments, labels on lines, and routine names. M names are alphanumeric and must start with an alphabetic character or a percent sign (%). The percent sign can only appear as the first character in a name. By convention, names starting with percent signs are generally application-independent or distinguished in some similar way. M does not reserve any names. That is, M always distinguishes keywords by context. Therefore, M permits a variable or a label called SET even though the language has a command called SET. M names are case sensitive. That is, M treats ABC, Abc, ABc, AbC ABC, and abc as six different names. M does not restrict the length of names in the main body of the standard. However, the portability section of the standard recommends limiting names to a maximum of eight (8) characters. GT.M effectively limits names to eight characters by ignoring any characters after the first eight. 2 Variables Variables M does not require predefinition of variable type or size. M variables are either local or global. Any variable may be unsubscripted or subscripted. 3 Arrays_Subscripts Arrays and Subscripts In M, subscripted variables identify elements in sparse arrays. Sparse arrays comprise existing subscripts and data nodes - no space is reserved for potential data nodes. These arrays generally serve logical, rather than mathematical, purposes. M array subscripts are expressions, and are not restricted to numeric values. The format for an M global or local variable is: [^]name[(expr1[,...])] o The optional leading caret symbol (^) designates a global variable. o The name specifies a particular array. o The optional expressions specify the subscripts o and must be enclosed in parentheses and separated by commas (,). The body of the M standard places no restrictions on variable names. However, the portability section of the standard does suggest limits on the length of an individual subscript expression, and on the total length of a variable name. The measurement for the length of names includes the length of the global variable name itself, the sum of the lengths of all the evaluated subscripts, and an allowance for an overhead of two (2) times the number of subscripts. The total must not exceed 237. For globals, GT.M permits this total to be modified with GDE up to 255. For locals, GT.M limits the length of individual subscripts to the maximum string length of 32,767. GT.M restricts the number of subscripts for local or global variables to 32. 3 M_Collation_Seq M Collation Sequences M collates all canonic numeric subscripts ahead of all string subscripts, including strings such as those with leading zeros that represent non-canonic numbers. Numeric subscripts collate from negative to positive in value order. String subscripts collate in ASCII sequence. In addition, GT.M allows the empty string subscript in most contexts, (the null, or empty, string collates ahead of all canonic numeric subscripts). GT.M allows definition of alternative collation sequences. For complete information on enabling this functionality, refer to the "Internationalization" chapter in GT.M Programmer's Guide. 3 Local_Variables Local Variables A local variable in M refers to a variable used solely within the scope of a single process. Local variable names have no leading delimiter. M makes a local variable available and subject to modification by all routines executed within a process from the time that variable is first SET until it is KILLed, or until the process stops executing M. However, M "protects" a local variable after that variable appears as an argument to a NEW command, or after it appears as an element in a formalist used in parameter passing. When M protects a local variable, it saves a copy of the variable's value and makes that variable undefined. M restores the variable to its saved value during execution of the QUIT that terminates the process stack level associated with the "protecting" NEW or formalist. For more information on NEW and QUIT, refer to the "Commands" chapter in GT.M Programmer's Guide. M restricts the following uses of variables to local variables: o FOR command control variables. o Elements within the parentheses of an "exclusive" KILL. o TSTART [with local variables list]. o A KILL with no arguments removes all current local variables. o NEW command arguments. Actualnames used by pass-by-reference parameter passing. 3 Glob_Var_Resrc_Nam_Env Global Variables and Resource Name Environments M recognizes an optional environment specification in global names or in the LOCK resource names (nrefs), which have analogous syntax. Global variable names have a leading caret symbol (^) as a delimiter. M makes a global variable available, and subject to modification by all routines executed within all processes in an environment, from the time that variable is first SET until it is KILLed. 4 Naked_References Naked References M accepts an abbreviation of the global name under some circumstances. When the leading caret symbol (^) immediately precedes the left parenthesis delimiting subscripts, the global variable reference is called a naked reference. M evaluates a naked reference by prefixing the last used global variable name, except for its last subscript, to the list of subscripts specified by the naked reference. The prefixed portion is known as the naked indicator. An attempt to use a naked reference when the prior global reference does not exist, or did not contain a subscript, generates an error. Because M has only one process-wide naked indicator which it maintains as a side affect of every evaluation of a global variable, using the naked reference requires an understanding of M execution sequence. M execution generally proceeds from left to right within a line, subject to commands that change the flow of control. However, M evaluates the portion of a SET command argument to the right side of the equal sign before the left side. Also, M does not evaluate any further $SELECT() arguments within the function after it encounters a true selection argument. In general, using naked references only in very limited circumstances prevents problems associated with the naked indicator. 4 Glob_Var_Name_Env Global Variable Name Environments M recognizes an optional environment specification in global names. The environment specification designates one of some set of alternative database files. The syntax for global variable names that include an environment specification is: ^|expr|name[(subscript[,...])] In GT.M, the expression identifies the Global Directory for mapping the global variable. Environment specifications permit easy access to global variables in alternative databases, including other "copies" of active variables in the current database. Environment specifications are sometimes referred to as extended global syntax or extended value syntax. GT.M also allows: ^|expr1,expr2|name[(subscript[,...])] Where the first expression identifies the Global Directory and the second expression is accepted but ignored by GT.M. To improve compatibility with some other M implementations, GT.M also accepts another non-standard syntax. In this syntax, the leading and trailing up-bar (|) are respectively replaced by a left square-bracket ([) and a right square-bracket (]). This syntax also requires expratoms, rather than expressions. The formats for this non-standard syntax are: ^[expratom1]name[(subscript...)] or ^[expratom1,expratom2]name[(subscript...)] Where expratom1 identifies the Global Directory and expratom2 is a dummy variable. Note that the first set of brackets in each format is part of the syntax. The second set of square brackets is part of the meta-language identifying an optional element. Example: $ gtmgbldir=Test.GLD $ export gtmgbldir $ GTM GTM>WRITE $ZGBLDIR TEST.GLD GTM>WRITE ^A THIS IS ^A IN DATABASE RED GTM>WRITE ^|"M1.GLD"|A THIS IS ^A IN DATABASE WHITE GTM>WRITE $ZGBLDIR TEST.GLD GTM>HALT $ echo gtmgbldir TEST.GLD The statement WRITE ^|"M1.GLD"|A writes variable ^A using the Global Directory, M1.GLD, but does not change the current Global Directory. Example: GTM>WRITE $ZGBLDIR M1.GLD GTM>WRITE ^A THIS IS ^A IN DATABASE WHITE GTM>WRITE ^|"M1.GLD"|A THIS IS ^A IN DATABASE WHITE The statement WRITE ^|"M1.GLD"|A is equivalent to WRITE ^A. Specifying separate Global Directories does not always translate to using separate databases. Example: GTM>WRITE ^|"M1.GLD"|A,!,^|"M2.GLD"|A,!,^|"M3.GLD" |A,! THIS IS ^A IN DATABASE WHITE THIS IS ^A IN DATABASE BLUE THIS IS ^A IN DATABASE WHITE In this example, the WRITE does not display ^A from three GT.M database files. Mapping specified by the Global Directory Editor (GDE) determines the database file to which a Global Directory points. This result could have occurred under the following mapping: ^|"M1.GLD"|A --> REGIONA --> SEGMENTA --> FILE1.DAT ^|"M2.GLD"|A --> REGIONA --> SEGMENT1 --> FILE2.DAT ^|"M3.GLD"|A --> REGION3 --> SEGMENT3 --> FILE1.DAT For more information on Global Directories, refer to the "Global Directory Editor" chapter of the GT.M Administration and Operations Guide. 4 Opt_GTM_Env_Trans_Facility Optional GT.M Environment Translation Facility For users who wish to dynamically (at run-time) determine a global directory from non-global directory information (typically UCI and VOL) in the environment specification, GT.M provides an interface to add an appropriate translation. Using this facility impacts the performance of every global access that uses environment specification. Make sure you use it only when static determination of the global directory is not feasible. When used, make every effort to keep the translation routines very efficient. The use of this facility is enabled by the definition of the environment variable gtm_env_translate, which contains the path of a shared library with the following entry point: 5 gtm_env_xlate gtm_env_xlate If the shared object is not accessible or the entry point is not accessible, GT.M reports an error. The gtm_env_xlate() routine has the following C prototype: int gtm_env_xlate(xc_string_t *in1, xc_string_t *in2, xc_string *in3, xc_string_t *out) where xc_string_t is a structure defined in gtmxc_types.h as follows: typedef struct { int length; char *address; } xc_string_t; The purpose of the function is to use its three input arguments to derive and return an output argument that can be used as an environment specification by GT.M. Note that the input values passed (in1, in2 and in3) are the result of M evaluation and must not be modified. The first two arguments are the expressions passed within the up-bars "| |" or the square-brackets "[ ]", and the third argument is the current working directory as described by $ZDIRECTORY. A return value other than zero (0) indicates an error in translation, and is reported by a GT.M error If the length of the output argument is non-zero, GT.M appends a secondary message of GTM-I-TEXT, containing the text found at the address of the output structure. GT.M does not do any memory management related to the output argument - space for the output should be allocated by the external routine. The routine must place the returned environment specification at the address it has allocated and adjust the length accordingly. On a successful return, the return value should be zero. If the translation routine must communicate an error to GT.M, it must return a non-zero value, and if it is to communicate additional error information, place the error text at the address where the environment would normally go and adjust the length to match the length of the error text. Length of the return value may range from 0-32767, otherwise GT.M reports an error. A zero-length (empty) string specifies the current value of $ZGBLDIR. Non-zero lengths must represent the actual length of the file specification pointed to by address, excluding any terminator. If the address field of the output argument is NULL, GT.M issues an error. The file specification may be absolute or relative and may contain an environment variable. If the file specified is not accessible, or is not a valid global directory, GT.M reports errors in the same way it does for any invalid global directory. It is possible to write this routine in M (as a call-in), however, global variables in such a routine would change the naked indicator, which environment references normally do not. Depending on the conventions of the application, there might be difficult name-space management issues such as protecting the local variables used by the M routine. While it is possible for this routine to take any form that the application designer finds appropriate within the given interface definition, the following paragraphs make some recommendations based on the expectation that a routine invoked for any more than a handful of global references should be efficient. It is expected that the routine loads one or more tables, either at compilation or the first time it is invoked. The logic of the routine performs a look up on the entry in the set of tables. The lookup might be based on the length of the strings and some unique set of characters in the names, or a hash, with collision provisions as appropriate. The routine may have to deal with a case where one or both of the inputs have zero length. A subset of these cases may have the first string holding a comma limited string that needs to be re-interpreted as being equivalent to two input strings (note that the input strings must never be modified). The routine may also have to handle cases where a value (most likely the first) is accidentally or intentionally, already a global directory specification. Example: > cat gtm_env_translate.c #include #include #include "gtmxc_types.h" static int init = 0; typedef struct { xc_string_t field1, field2, ret; } line_entry ; static line_entry table[5], *line, linetmp; /* Since these errors may occur before setup is complete, they are statics */ static char *errorstring1 = "Error in function initialization, environment variable GTM_CALLIN_START not defined. Environment translation failed."; static char *errorstring2 = "Error in function initialization, function pointers could not be determined. Envrironment translation failed."; #define ENV_VAR "GTM_CALLIN_START" typedef int (*int_fptr)(); int_fptr GTM_MALLOC; int init_functable(xc_string_t *ptr) { /* This function demonstrates the initialization of other function pointers as well (if the user-code needs them for any reason, they should be defined as globals)*/ char *pcAddress; long lAddress; void **functable; void (*setup_timer) (); void (*cancel_timer) (); pcAddress = getenv(ENV_VAR); if (pcAddress == NULL) { ptr->length = strlen(errorstring1); ptr->address = errorstring1; return 1; } lAddress = -1; lAddress = atol(pcAddress); if (lAddress == -1) { ptr->length = strlen(errorstring2); ptr->address = errorstring2; return 1; } functable = (void *)lAddress; setup_timer = (void(*)()) functable[2]; cancel_timer = (void(*)()) functable[3]; GTM_MALLOC = (int_fptr) functable[4]; return 0; } void copy_string(char **loc1, char *loc2, int length) { char *ptr; ptr = (char *) GTM_MALLOC(length); strncpy( ptr, loc2, length); *loc1 = ptr; } int init_table(xc_string_t *ptr) { int i = 0; char buf[100]; char *buf1, *buf2; FILE *tablefile; char *space = " "; char *errorstr1 = "Error opening table file table.dat"; char *errorstr2 = "UNDETERMINED ERROR FROM GTM_ENV_XLATE"; if ((tablefile = fopen("table.dat","r")) == (FILE *)NULL) { ptr->length = strlen(errorstr1); copy_string(&(ptr->address), errorstr1, strlen(errorstr1)); return 1; } while (fgets(buf, (int)SIZEOF(buf), tablefile) != (char *)NULL) { line= &table[i++]; buf1 = buf; buf2 =strstr(buf1, space); line->field1.length = buf2 - buf1; copy_string( &(line->field1.address), buf1, line->field1.length); buf1 = buf2+1; buf2 = strstr(buf1, space); line->field2.length = buf2-buf1; copy_string( &(line->field2.address), buf1, line->field2.length); buf1 = buf2+1; line->ret.length = strlen(buf1) - 1; copy_string( &(line->ret.address), buf1, line->ret.length); } fclose(tablefile); /* In this example, the last entry in the table is the error string */ line = &table[4]; copy_string( &(line->ret.address), errorstr2, strlen(errorstr2)); line->ret.length = strlen(errorstr2); return 0; } int cmp_string(xc_string_t str1, xc_string_t str2) { if (str1.length == str2.length) return strncmp(str1.address, str2.address, (int) str1.length); else return str1.length - str2.length; } int cmp_line(line_entry *line1, line_entry *line2) { return (((cmp_string(line1->field1, line2->field1))||(cmp_string(line1->field2, line2->field2)))); } int look_up_table(line_entry *aline, xc_string_t *ret_ptr) { int i; int ret_v; for(i=0;i<4;i++) { line = &table[i]; ret_v = cmp_line( aline, line); if (!ret_v) { ret_ptr->length = line->ret.length; ret_ptr->address = line->ret.address; return 0; } } /*ERROR OUT*/ line = &table[4]; ret_ptr->length= line->ret.length; ret_ptr->address = line->ret.address; return 1; } int gtm_env_xlate(xc_string_t *ptr1, xc_string_t *ptr2, xc_string_t *ptr_zdir, xc_string_t *ret_ptr) { int return_val, return_val_init; if (!init) { return_val_init = init_functable(ret_ptr); if (return_val_init) return return_val_init; return_val_init = init_table(ret_ptr); if (return_val_init) return return_val_init; init = 1; } linetmp.field1.length= ptr1->length; linetmp.field1.address= ptr1->address; linetmp.field2.length= ptr2->length; linetmp.field2.address= ptr2->address; return_val = look_up_table(&linetmp, ret_ptr); return return_val; } > cat table.dat day1 week1 mumps day2 week1 a day3 week2 b day4 week2 c.gld This example demonstrates the mechanism. A table is set up the first time for proper memory management, and for each reference, a table lookup is performed. Note that for the purpose of simplicity, no error checking is done, so table.dat is assumed to be in the correct format, and have exactly four entries. 2 Literals Literals M has both string and numeric literals. 3 String_Literals String Literals String literals (strlit) are enclosed in quotation marks (" ") and must only contain graphic characters. In other words, control characters (ASCII 0-31 and 127) cannot appear in a strlit. M attempts to use character text that appears outside of quotation mark delimiters according to context, which generally means as a local variable name. To include a quotation mark (") within a strlit, use a set of two quotation marks ("" ""). Example: GTM>WRITE """" " GTM> The WRITE displays a single quotation mark because the first quotation mark delimits the beginning of the string literal, the next two quotation marks denote a single quote within the string, and the last quotation mark delimits the end of the string literal. Use the $CHAR function and the concatenation operator to include control characters within a string. Example: GTM>WRITE "A"_$CHAR(9)_"B" A B GTM> The WRITE displays an "A," followed by a tab (), followed by a "B" using $CHAR(), to introduce the non-graphic character. 3 Numeric_Literals Numeric Literals In M, numeric literals (numlit) are entered without surrounding delimiters. Example: GTM>WRITE 1 1 GTM> WRITE 1.1 1.1 These display numeric literals that are integer and decimal. M also accepts numeric literals in the form of a mantissa and an exponent, separated by a delimiter of "E" in uppercase. The mantissa may be an integer or a decimal fraction. The integer exponent may have an optional leading minus sign (-). Example: GTM>WRITE 8E6 8000000 GTM> WRITE 8E-6 .000008 GTM> 2 Expressions Expressions The following items are legal M expression atoms (expratom). An expression atom is a component of an M expression. o Local variables o Global variables o Intrinsic special variables o Intrinsic functions o Extrinsic functions o Extrinsic special variables o Numeric literals o String literals o An expression enclosed in parentheses o Any of the above preceded by a unary operator In addition, any of these items may be combined with a binary operator and another expression atom. 2 Operators Operators M has both unary and binary operators. 3 Precedence Precedence All unary operations have right to left precedence. All M binary operations have strict left to right precedence. This includes all arithmetic, string, and logical operations. Hierarchies of operations require explicit establishment of precedence using parentheses (). Although this rule is counterintuitive, it is easy to remember and has no exceptions. 3 Arithmetic_Operators Arithmetic Operators All arithmetic operators force M to evaluate the expressions to which they apply as numeric. The arithmetic operators are: + as a unary operator simply forces M to evaluate the expression following as numeric; as a binary operator it causes M to perform addition. - as a unary operator causes M to negate the expression following; as a binary operator it causes M to perform subtraction. * binary operator for multiplication. ** binary operator for exponentiation. / binary operator for fractional division. \ binary operator for integer division. # binary operator for modulo, that is, causes M to produce the remainder from integer division of the first argument by the second. Remember that precedence is left to right for all arithmetic operators. Example: GTM>WRITE 1+1 2 GTM>WRITE 2-1 1 GTM>WRITE 2*2 4 GTM>WRITE 3**2 9 GTM>WRITE 4/2 2 GTM>WRITE 7 2 GTM>WRITE 7#3 1 GTM> This simple example demonstrates how each arithmetic binary operation uses numeric literals. Example: GTM>WRITE +"12ABC" 12 GTM>WRITE --"-3-4" -3 GTM> The first WRITE shows the unary plus sign (+) operation forcing the numeric evaluation of a string literal. The second WRITE demonstrates the unary minus sign (-). Note the second minus sign within the string literal does not cause subtraction, but rather, terminates the numeric evaluation with the result of negative three (-3). Each of the leading minus signs causes one negation and therefore, the result is negative three (-3). 3 Logical_Operators Logical Operators M logical operators always produce a result that is TRUE (1) or FALSE (0). All logical operators force M to evaluate the expressions to which they apply as truth-valued. The logical operators are: ' unary NOT operator negates current truth-value; M accepts placement of the NOT operator next to a relational operator, for example, A'=B as meaning '(A=B). & binary AND operator produces a true result only if both of the expressions are true. ! binary OR operator produces a true result if either of the expressions is true. Remember that precedence is always left to right, and that logical operators have the same precedence as all other operators. Example: GTM>WRITE '0 1 GTM>WRITE '1 0 GTM>WRITE '5689 0 GTM>WRITE '-1 0 GTM>WRITE '"ABC" 1 GTM> The above example demonstrates the unary NOT operation. Note that any non-zero numeric value is true and has a false negation. Example: GTM>WRITE 0&0 0 GTM>WRITE 1&0 0 GTM>WRITE 0&1 0 GTM>WRITE 1&1 1 GTM>WRITE 2&1 1 GTM>WRITE 0!0 0 GTM>WRITE 1!0 1 GTM>WRITE 0!1 1 GTM>WRITE 1!1 1 GTM>WRITE 2!1 1 GTM> The above example demonstrates all cases covered by the binary logical operators. 3 String_Operators String Operators All string operators force M to evaluate the expressions to which they apply as strings. The string operator is: _ binary operator causes M to concatenate the second expression with the first expresion Example: GTM>WRITE "B"_"A" BA GTM>WRITE "A"_1 A1 GTM> The above example demonstrates M concatenation. 3 Num_Relational_Operators Numeric Relational Operators M relational operators always generate a result of TRUE (1) or FALSE (0). All numeric relational operators force M to evaluate the expressions to which they apply as numeric. The numeric relational operators are: > binary arithmetic greater than < binary arithmetic less than The equal sign (=) does not force numeric evaluation, and should be viewed as a string operator. However, the equal sign between two numeric values tests for numeric equality. Other numeric relations are formed using the logical NOT operator apostrophe (') as follows: '> not greater than, that is, less than or equal to '< not less than, that is, greater than or equal to '= not equal, numeric or string operation Example: GTM>WRITE 1>2 0 GTM>WRITE 1<2 1 GTM> The above example demonstrates the basic arithmetic relational operations. Example: GTM>WRITE 1'<2 0 GTM>WRITE 2'<1 1 GTM> The above example demonstrates combinations of arithmetic, relational operators with the logical NOT operator. 3 Str_Relational_Operators String Relational Operators M relational operators always generate a result of TRUE (1) or FALSE (0). All string relational operators force M to evaluate the expressions to which they apply as strings. The string relational operators are: = binary operator causes M to produce a TRUE if the expressions are equal. [ binary operator causes M to produce a TRUE if the first expression contains the ordered sequence of characters in the second expression. ] binary operator causes M to produce a TRUE if the first expression lexically follows the second expression in the character encoding sequence, which by default is ASCII. ]] binary operator causes M to produce a TRUE if the first expression lexically sorts after the second expression in the subscript collation sequence. Note that all non-empty strings lexically follow the empty string, and every string contains the empty string. Other string relations are formed using the logical NOT operator apostrophe (') as follows: '[ does not contain. '] does not follow, that is, lexically less than or equal to. ']] does not sort after, that is, lexically less than or equal to in the subscript collation sequence. '= not equal, numeric or string operation. Example: GTM>WRITE "A"="B" 0 GTM>WRITE "C"="C" 1 GTM>WRITE "A"["B" 0 GTM>WRITE "ABC"["C" 1 GTM>WRITE "A"]"B" 0 GTM>WRITE "B"]"A" 1 GTM>WRITE "A"]]"B" 0 GTM>WRITE "B"]]"A" 1 These examples demonstrate the string relational operators using string literals. Example: GTM>WRITE 2]10 1 GTM>WRITE 2]]10 0 GTM>WRITE 0]"$" 1 GTM>WRITE 0]]"$" 0 These examples illustrate that when using the primary ASCII character set, the main difference in the "follows" (]) operator and the "sorts-after" (]]) operator is the way they treat numbers. Example: GTM>WRITE 1=1 1 GTM>WRITE 1=2 0 GTM>WRITE 1="1" 1 GTM>WRITE 1=01 1 GTM>WRITE 1="01" 0 GTM>WRITE 1=+"01" 1 GTM> These examples illustrate the dual nature of the equal sign operator. If both expressions are string or numeric, the results are straight forward. However, when the expressions are mixed, the native string data type prevails. Example: GTM>WRITE "a"'="A" 1 GTM>WRITE "FRED"'["RED" 0 GTM>WRITE "ABC"']"" 0 These examples demonstrate combinations of the string relational operators with the NOT operator. 3 Pat_Match_Operator Pattern Match Operator The pattern match operator (?) causes M to return a TRUE if the expression ahead of the operator matches the characteristics described by the pattern following the operator. The pattern is not an expression. Patterns are made up of two elements: o A repetition count o A pattern code, a string literal or an alternation list The element following the pattern match operator may consist of an indirection operator, followed by an element that evaluates to a legitimate pattern. The repetition count consists of either a single integer literal or a period (.) delimiter with optional leading and trailing integer literals. A single integer literal specifies an exact repetition count. The period syntax specifies a range of repetitions where the leading number is a minimum and the trailing number is a maximum. When the repetition count is missing the leading number, M assumes there is no minimum, (i.e., a minimum of zero). When the repetition count is missing the trailing number, M does not place a maximum on the number of repetitions. The pattern codes are: A alphabetic characters upper or lower case C control characters ASCII 0-31 and 127 E any character; used to pass all characters in portions of the string where the pattern is not restricted L lower-case alphabetic characters, ASCII 97-122 N digits 0-9, ASCII 48-57 P punctuation, ASCII 32-47, 58-64, 91-96, 123-126 U upper-case alphabetic characters, ASCII 65-90 Pattern codes may be upper or lower case and may be replaced with a string literal. GT.M allows the M pattern match definition of patcodes A, C, N, U, L, and P to be extended or changed, (A can only be modified implicitly by modifying L or U) and new patcodes added. For detailed information on enabling this functionality, refer to the "Internationalization" chapter in GT.M Programmer's Guide. The GT.M compiler accepts pattern codes other than those explicitly defined above. If, at run-time, the pattern codes come into use and no pattern definitions are available, GT.M issues a run-time error (PATNOTFOUND). GT.M does not currently implement a mechanism for Y and Z patterns and continues to treat those as compile-time syntax errors. Example: GTM>WRITE "ABC"?3U 1 GTM>WRITE "123-45-6789"?3N1"-"2N1"-"4N 1 The first WRITE has a simple one-element pattern while the second has multiple elements including both codes and string literals. All the repetition counts are fixed. Example: I x?.E1C.E W !,"Must not contain a control character" Q This example uses a pattern match to test for control characters. Example: I acn?1U.20A1","1U.10A D .S acn=$G((^ACX($P(acn,","),$P(acn,",",2))) This example uses a pattern match with implicit minimums to determine that an "account number" is actually a name, and to trigger a look-up of the corresponding account number in the ^ACX cross index. The pattern match operator accepts the alteration syntax. Alteration consists of a repeat count followed by a comma-delimited list of patatoms enclosed in parentheses "()". The semantic is that the pattern matches if any of the listed patterns matches the operand string. For example, ?1(2N1"-"7N,3N1"-"2N1"-"4N).1U might be a way to match either a social security number or a taxpayer ID. Since alternation is defined as one of the ways of constructing a patatom, alternation can nest (be used recursively). Complex pattern matches may not be efficient to evaluate, so every effort should be made to simplify any commonly used pattern and to determine if more efficient alternative logic would be more appropriate. 2 Gen_M_Comm General M Commands M commands may be abbreviated to a defined prefix. Most commands have arguments. However, some commands have either optional arguments or no arguments. When a command has no argument and is followed by more commands on the same line, at least two spaces () must follow the command without arguments. Commands that accept arguments generally accept multiple arguments on the same command. M treats multiple arguments the same as multiple occurrences of the same command, each with its own argument. 3 Postconditionals Postconditionals M provides postconditionals as a tool for placing a condition on the execution of a single command and, in some cases, a single command argument. A postconditional consists of a colon (:) delimiter followed by a truth-valued expression. When the expression evaluates to true, M executes the command occurrence. When the expression evaluates to false, M does not execute the command occurrence. 4 Comm_Postconditionals Command Postconditionals Command postconditionals appear immediately following a command and apply to all arguments for the command when it has multiple arguments. All commands except commands that themselves have a conditional aspect accept a command postconditional. Among the M standard commands, ELSE, FOR, and IF do not accept command postconditionals. All the GT.M command extensions accept command postconditionals. 4 Arg_Postconditionals Argument Postconditionals Commands that affect the flow of control may accept postconditionals on individual command arguments. Because multiple arguments act as multiple commands, this is a straight-forward application of the same principal as command postconditional. The only M standard commands that accept argument postconditionals are DO, GOTO, and XECUTE. The GT.M command extensions that accept argument postconditionals are BREAK, ZGOTO, and ZSYSTEM. 3 Timeouts Timeouts M provides timeouts as a tool to retain program control over commands of indefinite duration. A timeout consists of a colon (:) delimiter on an argument, followed by a numeric expression specifying the number of seconds for M to attempt to execute the command. When the timeout is zero (0), M makes a single attempt to complete the command. GT.M has been designed to allow large timeout values, and to protect against arithmetic overflow when converting large timeout values to internal representations. When a command has a timeout, M maintains the $TEST intrinsic special variable as the command completes. If the command completes successfully, M sets $TEST to TRUE (1). If the command times out before successful completion, M sets $TEST to FALSE (0). When a command argument does not specify a timeout, M does not maintain $TEST. The following commands accept timeouts: o LOCK o JOB o OPEN o READ o ZALLOCATE When a READ times out, M returns any characters that have arrived between the start of the command and the timeout. M does not produce any partial results for any of the other timed commands. 2 Gen_M_Intrin_Func General M Intrinsic Functions M Intrinsic Functions start with a single dollar sign ($) and have one or more arguments enclosed in parentheses () and separated by commas (,). These functions provide an expression result by performing actions that would be impossible or difficult to perform using M commands. It is now possible to invoke a C function in a package via the external call mechanism. 2 Gen_M_Intr_Spec_Var General M Intrinsic Special Variables M Intrinsic Special Variables start with a single dollar sign ($). GT.M provides such variables for program examination. In some cases, the Intrinsic Special Variables may be SET to modify the corresponding part of the environment. 2 Routines Routines M routines have a name and consist of lines of code followed by an end-of-record which is a carriage return, formfeed () sequence. M separates the name of a routine from the body of the routine with an end-of-line which is a carriage-return, line-feed () sequence. GT.M stores routine sources in UNIX files and implicitly supplies the end-of-record and end-of-line character sequences. In M, a routine has no particular impact on variable management and may include code that is invoked at different times and has no logical intersection. 3 Lines Lines A line of M code consists of the following elements in the following order: o An optional label. o A line-start delimiter. The standard defines the line-start delimiter as a space () character. In order to enhance routine readability, GT.M extends M by accepting one or more tab () characters as line-start delimiters. o Zero or more level indicators, which are periods (.). The level indicators show the level of nesting for argumentless DO commands: the more periods, the deeper the nesting. M ignores lines that contain level indicators unless they directly follow an argumentless DO command with a matching level of nesting. o Zero or more commands and their arguments. M accepts multiple commands on a line. The argument(s) of one command are separated from the next command by a command-start delimiter, consisting of one or more spaces (). o A terminating end-of-line, which is a carriage return, line feed () sequence. 4 Labels Labels In addition to labels that follow the rules for M names, M accepts labels consisting only of digits. In a label consisting only of digits, leading zeros are considered significant. For example, labels 1 and 01 are different. Formalists may immediately follow a label. A Formalists consists of one or more names enclosed in parentheses (). Formalists identify local variables that "receive" passed values in M parameter passing. In GT.M, a colon (:) delimiter may be appended to the label, which causes the label to be treated as "local." Within the routine in which they appear, they perform exactly as they would without the trailing colon but they are inaccessible to other routines. Using local labels reduces object size and linking overhead, for both ZLINK and host linking. 4 Comments Comments In addition to commands, a line may also contain a comment that starts with a leading semi-colon (;) delimiter. The scope of a comment is the remainder of the line. In other words, M ignores anything to the right of the comment delimiter. The standard defines the comment delimiter (;) as it would a command, and therefore requires that it always appear after a linestart. GT.M extends the standard to permit comments to start at the first character of a line or in an argument position. 3 Entry_Ref Entry References M entryrefs provide a generalized target for referring to a line within a routine. An entryref may contain some combination of a label, an offset, and a routine name (in that order). The offset is delimited by a plus sign (+) and the routinename is delimited by a caret symbol(^). When an entryref does not contain a label, M assumes the offset is from the beginning of the routine. When an entryref does not contain an offset, M uses an offset of zero (0). When an entryref does not contain a routine name, M assumes the routine that is currently executing. M permits every element in an entryref to have the form of an indirection operator, followed by an element that evaluates to a legitimate occurrence of that portion of the entryref. While most commands and functions that use entryrefs permit argument indirection, M does not accept indirection that resolves to a combination of label and offset or offset and routine name. Offsets provide an extremely useful tool for debugging. However, avoid their use in production code because they generally produce maintenance problems. 3 Label_Ref Label References M labelrefs are a subset of entryrefs that exclude offsets and separate indirection. Labelrefs are used with parameter passing. 2 Indirection Indirection M provides indirection as a means to defer definition of elements of the code until run-time. Indirection names a variable that holds or "points" to the element. The indirection operator is the "at" symbol (@). 3 Arg_Indirection Argument Indirection Most commands accept indirection of their entire argument. Example: GTM>SET x="^INDER" GTM>DO @x This example is equivalent to DO ^INDER. 3 Atomic_Indirection Atomic Indirection Any expratom or any local or global variable name may be replaced by indirection. Example: GTM>SET x="HOOP",b="x" GTM>WRITE a="HULA "__@b HULA HOOP GTM> This example uses indirection within a concatenation operation. 3 Entryref_Indirection Entryref Indirection Any element of an entryref may be replaced by indirection. Example: GTM>SET lab="START",routine="PROG" GTM>DO @lab^@routine This example is equivalent to DO START^PROG. 3 Patt_Code_Indirection Pattern Code Indirection A pattern code may be replaced by indirection. Example: GTM>FOR p="1U.20A1"",""1U.20A",5N IF x?@p QUIT GTM>ELSE WRITE !,"Incorrect format" QUIT This example uses pattern code indirection to test x for either a name or a number. 3 Name_Indirection Name Indirection Indirection may replace the prefix of a subscripted global or local variable name. This "name" indirection requires two indirection operators, a leading operator similar to the other forms of indirection, and a trailing operator marking the transition to those subscripts that are not specified by indirection. Example: GTM>SET from="B",to="^A(15),x="" GTM>FOR SET x=$O(@from@(x)) Q:x="" S @to@(x)=@from@(x) This example uses name indirection to copy the level contents of a local array to a part of a global array. The example assumes that all existing first level nodes of variable B have data. 3 Indirection_Concerns Indirection Concerns M indirection provides a very powerful tool for allowing program abstraction. However, because indirection is frequently unnecessary and has some disadvantages, use it carefully. Because routines that use indirection in some ways do not contain adequate information for easy reading, such routines tend to be more difficult to debug and maintain. To improve run-time performance, GT.M tends to move work from run-time to compile-time. Indirection forces compiler actions to occur at run-time, which minimizes the benefits of compilation. M allows most forms of indirection to be recursive. However, in real applications, recursive indirection typically makes the code obscure and slow. There are circumstances where indirection serves a worthwhile purpose. For instance, certain utility functions with a general nature may be clearly abstracted and coded using indirection. Because M has no "CASE" command, DO (or GOTO) with argument indirection provides a clear solution to the problem of providing complex branching. Some M users prototype with indirection and then replace indirection with generated code that reduces run-time overhead. In any case, always consider whether indirection can be replaced with a clearer or more efficient approach. 2 Param_Passing Parameter Passing Parameter passing provides a way of explicitly controlling some or all of the variable context transferred between M routines. M uses parameter passing for: o A DO command with parameters o Extrinsic functions and special variables Parameter passing is optional on DO commands. Parameter passing uses two argument lists: the actuallist that specifies the parameters that M passes to an invoked routine, and the formalist that specifies the local variables to receive or associate with the parameters. 3 Actuallists Actuallists An actuallist specifies the parameters M passes to the invoked routine. The actuallist contains a list of zero or more parameters enclosed in parentheses, immediately following a DO or extrinsic function. An actuallist: o Is made up of items separated by commas o Contains expressions and/or actualnames. Items may be missing, that is, two commas may appear next to each other, with nothing between them. o Must be used in an invocation of a label with a formallist, except in the case of extrinsic special variables. o Must not contain undefined variables. o Must not have more items than a formallist with which it is used. o May contain the same item in more than one position. Example: GTM>DO MULT(3,X,.RESULT) This example illustrates a DO with parameters. The actuallist contains: o 3 - a numeric literal o X - a local variable o .RESULT - an actualname 3 Actualnames Actualnames An actualname starts with a leading period (.) delimiter, followed by an unsubscripted local variable name. Actualnames identify variables that are passed by reference, as described in a subsequent section. While expressions in an actualname are evaluated when control is transferred to a formallabel, the variables identified by actualnames are not; therefore, they do not need to be defined at the time control is transferred. 3 Formallists Formallists A formallist specifies the variables M uses to hold passed values. A formallist contains a list of zero or more parameters enclosed in parentheses, immediately following a label. A formallist: o Is made up of items separated by commas. o Contains unsubscripted local variable names. o Must be used and only used with a label invoked with an actuallist or an extrinsic. o May contain undefined variables. o May have more items than an actuallist with which it is used. o Must not contain the same item in more than one position. o Must contain at least as many items as the actuallist with which it is used. Example: MULT(MP,MC,RES) SET RES=MP*MC QUIT RES In this example, illustrating a simple parameterized routine, the formallist contains the following items: o MP o MC o RES An example in the section describing "Actuallists" shows an invocation that matches this routine. 3 Formallabel Formallabel A label followed by a formallist is called a formallabel. 3 Param_Pass_Operation Parameter Passing Operation M performs an implicit NEW on the formallist names and replaces the formallist items with the actuallist items. M provides the actuallist values to the invoked procedure by giving each element in the formallist the value or reference provided by the corresponding element in the actuallist. M associates the first name in the formallist with the first item in the actuallist, the second name in the formallist with the second item in the actuallist and so on. If the actuallist is shorter than the formallist, M ensures that the formallist items with no corresponding value are in effect NEWed. If the formallist item has no corresponding item in the actuallist (indicated by two adjacent commas in the actuallist), that item in the formallist becomes undefined. If the actuallist item is an expression and the corresponding formallist variable is an array, parameter passing does not affect the subscripted elements of the array. If an actualname corresponds to a formallist variable, M reflects array operations on the formallist variable, by reference, in the variable specified by the actualname. M treats variables that are not part of the formallist as if parameter passing did not exist (i.e., M makes them available to the invoked routine). M initiates execution at the first command following the formallabel. A QUIT command terminates execution of the invoked routine. At the time of the QUIT, M restores the formallist items to the values they had at the invocation of the routine. In the case where a variable name appears as an actualname in the actuallist, and also as a variable in the formallist, the restored value reflects any change made by reference. A QUIT from a DO does not take an argument, while a QUIT from an extrinsic must have an argument. This represents one of the two major differences between the DO command with parameters and the extrinsics. M returns the value of the QUIT command argument as the value of the extrinsic function or special variable. The other difference is that M stacks $TEST for extrinsics. Example: SET X=30,Z="Hello" DO WRTSQR(X) ZWRITE QUIT WRTSQR(Z) SET Z=Z*Z WRITE Z,! QUIT Produces: 900 X=30 Z="Hello" 3 Param_Pass_Mechanism Parameter Passing Mechanisms M passes the actuallist values to the invoked routine using two parameter-passing mechanisms: o Call-by-Value - where expressions appear o Call-by-Reference - where actualnames appear A call-by-value passes a copy of the value of the actuallist expression to the invoked routine by assigning the copy to a formallist variable. If the parameter is a variable, the invoked routine may change that variable. However, because M constructs that variable to hold the copy, it deletes the variable holding the copy when the QUIT restores the prior formallist values. This also means that changes to the variable by the invoked routine do not affect the value of the variable in the invoking routine. Example: SET X=30 DO SQR(X) ZWRITE QUIT SQR(Z) SET Z=Z*Z QUIT Produces: X=30 A period followed by a name identifies an actualname and causes a call-by-reference. A call-by-reference passes a pointer to the variable of the invoked routine so operations on the assigned formallist variable also act on the actualname variable. Changes, including KILLs to the formallist variable, immediately have the same affect on the corresponding actualname variable. This means that M passes changes to formallist variables in the invoked routine back to the invoking routine as changes in actualname variables. Example: SET X=30 DO SQR(.X) ZWRITE QUIT SQR(Z) SET Z=Z*Z QUIT Produces: X=900 3 GTM_Param_Pass_Extn GT.M Parameter Passing Extensions The standard does not provide for indirection of a labelref because the syntax has an ambiguity. Example: DO @X(1) This example could be: o An invocation of the label specified by X with a parameter of 1. o An invocation of the label specified by X(1) with no parameter list. GT.M processes the latter interpretation as illustrated in the following example. Example: The syntax: SET A(1)="CUBE",X=5 DO @A(1)(.X) WRITE X,! QUIT CUBE(C) ;cube a variable SET C=C*C*C QUIT Produces the result: 125 GT.M follows analogous syntax for routine indirection: DO ^@X(A) invokes the routine specified by X(A). DO ^@(X)(A) invokes the routine specified by X and passes the parameter A. DO ^@X(A)(A) invokes the routine specified by X(A) and passes the parameter A. 2 Ext_Calls External Calls GT.M allows references to a GT.M database from programs written in other programming languages that run under UNIX. In GT.M, calls to C language routines may be made with the following syntax: DO &[packagename.]name[^name][parameter-list] or as an expression element, $&[packagename.]name[^name][parameter-list] Where packagename, like the name elements is a valid M name. Because of the parsing conventions of M, the identifier between the ampersand (&) and the optional parameter-list has precisely constrained punctuation - a latersection describes how to transform this into a more richly punctuated name should that be appropriate for the called function. While the intent of the syntax is to permit the name^name to match an M labelref, there is no semantic implication to any use of the up-arrow (^). 2 Extrinsic_Func Extrinsic Functions An extrinsic function is an M subroutine that another M routine can invoke to return a value. The format for extrinsic functions is: $$[label][^routinename]([expr|.lname[,...]]) o The optional label and optional routinename make up the formallabel that specifies the name of the subroutine performing the extrinsic function. The formallabel must contain at least one of its optional components. o The optional expressions and actualnames make up the actuallist that specifies the list of actual parameters M passes to the invoked routine. M stacks $TEST for extrinsic functions. This is one of the two major differences between the DO command with parameters and extrinsics. On return from an extrinsic function, M restores the value of $TEST to what it was before the extrinsic function, regardless of the actions executed by the invoked routine. M requires a routine that implements an extrinsic function to terminate with an explicit QUIT command which has an argument. M returns the value of the QUIT command argument as the value of the extrinsic function. This is the other major difference between the DO command with parameters and extrinsics. It is now possible to invoke a C function in a package via the external call mechanism. Example: GTM>ZPRINT ^POWER POWER(V,X,S,T) ;extrinsic to raise to a power ;ignores fractional powers SET T=1,S=0 IF X<0 SET X=-X,S=1 FOR X=1:1:X S T=T*V QUIT $S(S:1/T,1:T) GTM> WRITE $$^POWER(3,4) 81 GTM> The POWER routine uses a formallist that is longer than the "expected" actuallist to protect local working variables. Such practice may be encouraged or discouraged by your institution's standards. 2 Extrinsic_Spc_Vars Extrinsic Special Variables An extrinsic special variable is a user-written M subroutine that another M routine can invoke to return a value. The format for extrinsic special variables is: $$[label][^routinename] o The optional label and optional routinename make up the formallabel, which specifies the name of the subroutine performing the extrinsic function. The formallabel must contain at least one of its optional component. An extrinsic special variable can be thought of as an extrinsic function without input parameters. $$x is equivalent in operation to $$x(). Extrinsic special variables are the only case where invocation of a formallabel does not require an actuallist. M stacks $TEST for extrinsic special variables. M requires that a routine that implements an extrinsic special variable terminate with an explicit QUIT command which has an argument. M returns the value of the QUIT command argument as the value of the extrinsic special variable. Example: GTM>ZPRINT ^DAYOWEEK DAYOWEEK() ;extrinsic special variable to ;provide the day of the week QUIT $ZD($H,"DAY") GTM>WRITE $$DAYOWEEK^DAYOWEEK MON 2 Trans_Processing Transaction Processing Transaction Processing (TP) provides a way for M programs to organize database updates into logical groups that occur as a single event (i.e., either all the database updates in a transaction occur, or none of them occur). No other process may behave as if it observed any intermediate state. Transaction processing has been designed to improve output and eliminate "live lock" conditions. The number of attempts to complete the transaction is limited to four. The fourth attempt is made inside a "critical section" with all other processes temporarily locked out of the database. Between the second and third tries, GT.M waits for a random interval between 0 and 500 milliseconds. 3 TP_Def TP Definitions In M, a transaction is a sequence of commands that begins with a TSTART command, ends with a TCOMMIT command, and is not within the scope of another transaction. A successful transaction ends with a COMMIT that is triggered by the TCOMMIT command at the end of the transaction. A COMMIT causes all the database updates performed within the transaction to become available to other processes. An unsuccessful transaction ends with a ROLLBACK. ROLLBACK is invoked explicitly by the TROLLBACK command, or implicitly at a process termination that occurs during a transaction in progress. An error within a transaction does not cause an implicit ROLLBACK. A ROLLBACK removes any database updates performed within the transaction before they are made available to other processes. ROLLBACK also releases all resources LOCKed since the start of the transaction, and makes the naked reference undefined. A RESTART is a transfer of control to the TSTART at the beginning of the transaction. RESTART implicitly includes a ROLLBACK and may optionally restore local variables to the values they had when the initial TSTART was originally executed. A RESTART always restores $TEST and the naked reference to the values they had when the initial TSTART was executed. RESTART does not manage device state information. A RESTART is invoked by the TRESTART command or by M if it is determined that the transaction is in conflict with other database updates. RESTART can only successfully occur if the initial TSTART includes an argument that enables RESTART. 3 TP_Characteristics TP Characteristics Most transaction processing systems try to have transactions meet the "ACID" test-Atomic, Consistent, Isolated, and Durable. To conform with the M approach of providing maximum flexibility and, when possible, backwards compatibility with older versions of the standard, M transaction processing requires the use of programming conventions that meet the ACID test. For example, some effects of the BREAK, CLOSE, JOB, OPEN, READ, USE WRITE, and ZSYSTEM commands may be observed by parties to the system. Because the effects of these commands might cause an observing process or person to conclude that a transaction executing them was in progress and perhapsfinished, they violate, in theory, the principle of Isolation. The LOCK command is another example. A program may attempt to use a LOCK to determine if another process has a transaction in progress. The answer would depend on the management of LOCKs within transactions, which is implementation-specific. This would therefore clearly violate the principle of Isolation. The LOCK command is discussed later in this section. The simplest way to construct a transaction that meets the ACID test is not to use any commands within a transaction whose affects may be immediately "visible" outside the transaction. Unfortunately, because M applications are highly interactive, this is not entirely straightforward. When a user interaction relies on database information, one solution is for the program to save the initial values of any global values that could affect the outcome, in local variables. Then, once the interaction is over and the transaction has been initiated, the program checks the saved values against the corresponding global variables. If they are the same, it proceeds. If they differ, some other update has changed the information, and the program must issue a TROLLBACK, and initiate another interaction as a replacement. Even when the "visible" commands appear within a transaction, an M application may provide wholesome operation by relying on additional programming or operating conventions. A program using LOCKs to achieve serializability relies on properly designed and universally followed LOCKing conventions to achieve Isolation with respect to database operations. LOCKs placed outside the transaction (usually a LOCK immediately before the TSTART and an unlock immediately after the TCOMMIT) achieve serializability by actually serializing any approximately concurrent transaction. LOCKs placed inside the transaction (frequently a LOCK immediately after the TSTART and an unlock immediately before the TCOMMIT) signal M to ensure that no operations using the same LOCK resource(s) overlap. Within a transaction, an M implementation may defer both LOCKing and unlocking to achieve its goal of serializability. A program using TSTARTs with the SERIAL keyword replaces the convention with a guarantee from M that all the database activity of the transaction meets the test of Isolation with respect to database activity. In GT.M the Durability aspect of the ACID properties relies on the journaling feature. When journaling is on, every transaction is recorded in the journal file as well as in the database. The journal file constitutes a serial record of database actions and states. It is always written before the database updates and is designed to permit recovery of the database if the database should be damaged. By default when a process commits a transaction, it does not return control to the application code until the transaction has reached the journal file. The exception to this is that when the TSTART specifies TRANSACTIONID="BATCH" the process resumes application execution without waiting for the file system to confirm the successful write of the journal record. The idea of the TRANSACTIONID="BATCH" has nothing inherently to do with "batch" processing - it is to permit maximum throughput for transactions where the application has its own check-pointing mechanism, or method of recreating the transaction in case of a failure. The real durability of transactions is a function of the durability of the journal files. Putting journal files on reliable devices (RAID with UPS protection) and eliminating common points of failure with the path to the database (separate drives, controllers cabling) improve durability. The use of the replication feature can also improve durability by moving the data to a separate site in real time. Attempting to QUIT (implicitly or explicitly) from code invoked by a DO, XECUTE, or extrinsic after that code issued a TSTART not yet matched by a TCOMMIT, produces an error. Although this is a consequence of the RESTART capability, it is true even when that capability is disabled. For example, this means that an XECUTE containing only a TSTART fails, while an XECUTE that performs a complete transaction succeeds. 3 TP_Performance TP Performance To achieve the best GT.M performance, transactions should: o be as short as possible o consist, as much as possible, only of global updates o be SERIAL with no associated LOCKs o have RESTART enabled with a minimum of local variables protected by a restart portion of the TSTART argument. Large concurrent transactions using TCOMMIT may result in repeated and inefficient attempts by competing processes to capture needed scarce resources, resulting in poor performance. Example: TSTART ():SERIAL SET (ACCT,^M(0))=^M(0)+1 SET ^M(ACCT)=PREC,^PN(NAM)=ACCT TCOMMIT This transaction encapsulates these two SETs. The first increments the tally of patients registered, storing the number in local variable ACCT for faster access in the current program, and in global variable ^M(0). The second SET stores a patient record by account number and the third cross-references the account number with the patient name. Placing the SETs within a single transaction ensures that the database always receive either all of the SETs or none of them, thus protecting database integrity against process or system failure. Similarly, another concurrent process, whether using transactions or not, never finds one of the SETs in place without also finding the other one. Example: TSTART ():SERIAL IF $TRESTART>3 DO QUIT .TROLLBACK .WRITE !,"Too many RESTARTs" .QUIT SET (NEXT,^ID(0))=^ID(0)+1 SET ^ID(NEXT)=RECORD,^XID(ZIP,NEXT)="" TCOMMIT This transaction will automatically restart if it cannot serialize the SETs to the database, and will terminate with a TROLLBACK if more than 3 RESTARTs occur. GT.M provides a way to monitor transaction restarts by reporting them to the operator logging facility. If the environment variable TPRESTART_SYSLOG_DELTA is defined, GT.M reports every Nth restart where N is the numeric evaluation of the value of TPRESTART_SYSLOG_DELTA. If the environment variable TPRESTART_SYSLOG_LIMIT is defined, the restart reporting begins after the number of restarts specified by the value of TPRESTART_SYSLOG_LIMIT. For example, defining both the environment variable to the value 1, causes all TP restarts to be logged. When TPRESTART_SYSLOG_DELTA is defined, leaving TPRESTART_SYSLOG_LIMIT undefined is equivalent to giving it the value 1. For more information on enhancements related to TP performance refer to the "NOISOLATION" section under VIEW command topic in the "Commands" chapter in GT.M Programmer's Guide. 3 TP_Example TP Example Here is a transaction processing example that lets you exercise the concept. If you use this example, be mindful that the functions "holdit" and "trestart" are included as tools to allow you access to information within a transaction which would normally be hidden from users. These types of functions would not normally appear in production code. Comments have been inserted into the code to explain the function of various segments. trans ;This sets up the program constants ;for doit and trestart n s $p(peekon,"V",51)="" s $p(peekon,"V",25)="Peeking inside Job "_$j s $p(peekoff,"^",51)="" s $p(peekoff,"^",25)="Leaving peeking Job "_$j ;This establishes the main loop s CNFLTMSG="Conflict, please reenter" f r !,"Name: ",nam q:'$l(nam) d .i nam="?" d q ..w !,"Current data in ^trans:",! d:$d(^trans) q ...zwrite ^trans .f s ok=1 d q:ok w !,$C(7),CNFLTMSG,$C(7),! ..s old=$g(^trans(nam),"?") ..i old="?" w !,"Not on file" d q ...;This is the code to add a new name ...f d q:data'="?" ....r !,"Enter any info using '#' delimiter: ",!,data ...i data="" w !,"No entry made for ",nam q ...TSTART ():SERIAL i $$trestart ;$$trestart for demo ...i $d(^trans(nam)) s ok=^trans(nam)=data TRO q ...s ^trans(nam)=data ...TCOMMIT:$$doit ;$$doit for demo ..;This is the beginning of the change and delete loop ..f d q:fld=+fld!'$l(fld) w " must be numeric" ...w !,"Current data: ",!,old ...r !,"Piece no. (negative to delete record) : ",fld ..i 'fld w !,"no change made" q ..;This is the code to delete a new name ..i fld<0 d q ; delete record ...f d q:"YyNn"[x ....w !,"Ok to delete ",nam," Y(es) or N(o) ? " ....r x s x=$e(x) ...i "Yy"'[x!'$l(x) w !,"No change made" q ...TSTART ():SERIAL i $$trestart ;$$trestart for demo ...i $g(^trans(nam),"?")'=old TROLLBACK s ok=0 q ...kill ^trans(nam) ...TCOMMIT:$$doit; $$doit for demo ..;This is the code to change a field ..f r !,"Data: ",data q:data'="?"&(data'["#") d ...w " must not be a single '?' or contain any '#'" ..TSTART ():SERIAL i $$trestart ;$$trestart for demo ..i '$d(^trans(nam)) s ok=0 TROLLBACK q ..i $p(^trans(nam),"#",fld)=$p(old,"#",fld) d q ...s ok=$p(^trans(nam),"#",fld)=data TROLLBACK ..s $p(^trans(nam),"#",fld)=data ..TCOMMIT:$$doit; $$doit for demo q doit() ;This inserts delay and an optional ;rollback only to show how it works w !!,peekon d disp f d q:"CR"[act .r !,"C(ommit), R(ollback), or W(ait) ? ",act .s act=$tr($e(act),"cr","CR") .i act="?" d disp i act="R" TROLLBACK w !,"User requested DISCARD" w !,peekoff,! q $TLEVEL trestart() ;This is only to show what is happening i $TRESTART d .w !!,peekon,!,">>>RESTART<<<",! d disp w !,peekoff,! q 1 disp w !,"Name: ",nam w !,"Original data: ",!,old,!,"Current data: " w !,$g(^trans(nam),"KILLED!") q Generally, this type of program would be receiving data from multiple sessions into the same global. 1 BREAK Break The BREAK command pauses execution of the code and initiates Direct Mode. The format of the BREAK command is: B[REAK][:tvexpr] [expr[:tvexpr][,...]] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The optional expression contains a fragment of GT.M code to XECUTE before the process enters Direct Mode. o The BREAK command without an argument causes a pause in execution of the routine code and immediately initiates Direct Mode. In this case, at least two (2) spaces must follow the BREAK to separate it from the next command on the line. o The optional truth-valued expression immediately following the expression is the argument postconditional that controls whether GT.M XECUTEs the argument. If present and true, the process executes the code before entering Direct Mode. If present and false, the process does not execute the code before entering Direct Mode. o An indirection operator and an expression atom evaluating to a list of one or more BREAK arguments form a legal argument for a BREAK. Issuing a BREAK command inside a transaction destroys the Isolation of that transaction. Beacuse of the way that GT.M implements transaction processing, a BREAK within a transaction may suffer an indefinite number of restarts ("live lock"). Generally, programs in production must not include BREAK commands. Therefore, GT.M provides the ZBREAK and ZSTEP commands, which insert temporary breakpoints into the process rather than the source code. BREAKs inserted with ZBREAK only exist until the image terminates or until explicitly removed by another ZBREAK command. ZSTEP also inserts temporary BREAKs in the image that only exist for the execution of the ZSTEP command. In the GT.M debugging environment, ZBREAKs and ZSTEPs that insert BREAKs provide a more flexible and less error-prone means of setting breakpoints than coding BREAKs directly into a routine. For more information on ZBREAK and ZSTEP, refer to the sections that describe those commands. To resume execution of the interrupted program, use the ZCONTINUE command. GT.M displays messages identifying the source of a BREAK as: o The body of a program o A o ZBREAK action o A device EXCEPTION o A ZSTEP action The VIEW "BREAKMSG" mask selectively enables or disables these messages. See the section on "VIEW" for an explanation of the mask. By default, a process executing a GT.M image displays all BREAK messages. When a process encounters a BREAK, it displays a prompt indicating readiness to process commands in Direct Mode. By default, Direct Mode displays the GTM> prompt. SETting the $ZPROMPT intrinsic special variable alters the prompt. 2 Ex_of_Break Examples of BREAK Example: LOOP0 F S act=$O(^act(act)) Q:act="" B:debug D LOOP1 This FOR loop contains a BREAK with a command postconditional. Example: B:$D(x) "W !,""OK""":x,"W !,""Wrong again""":'x This uses a BREAK with both command and argument postconditionals. The actions display debugging messages. 1 CLOSE Close The CLOSE command breaks the connection between a process and a device. The format of the CLOSE command is: C[LOSE][:tvexpr] expr[:(keyword[=expr][:...])][,...] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The required expression specifies the device to CLOSE. o The optional keywords specify device parameters that control device behavior; some device parameters take arguments delimited by an equal sign (=). If there is only one keyword, the surrounding parentheses are optional. o An indirection operator and an expression atom evaluating to a list of one or more CLOSE arguments form a legal argument for a CLOSE. 1 DO Do The DO command makes an entry in the GT.M invocation stack and transfers execution to the location specified by the entryref. The format of the DO command is: D[O][:tvexpr] [entryref[(expr|.lvn[,...])][:tvexpr][,...]] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The optional entryref specifies a location (with some combination of label, offset, and routinename) at which execution continues immediately following the DO. o A DO command without an argument (that is, a DO followed by two (2) spaces) transfers execution to the next line in the routine if that line contains a number of periods (.) after the optional label and before the required linestart. These periods indicate the current level of "immediate" nesting caused by argumentless DOs. If the line following the DO contains too many periods, GT.M reports an error; if the line following the DO contains too few periods, GT.M ignores the DO command. o A DO command without an argument stacks the current value of $TEST, in contrast to a DO with an argument, which does not protect the current value of $TEST. o The optional parameter list enclosed in parentheses ( ) contains parameters to pass to the routine entry point. o If the DO specifies a parameter list, the entryref location must start with a label and an argument list (that is, GT.M prohibits entryrefs with offsets during parameter passing). o If an element in the parameter list starts with a period, it specifies an unsubscripted local variable name and the DO passes that variable by reference. Otherwise, the element specifies an expression that the DO evaluates and passes as a value. o The optional truth-valued expression following the parameter list, or the entryref if the argument contains no parameter list, specifies the argument postconditional and controls whether GT.M performs a DO with that argument. o An indirection operator and an expression atom evaluating to a list of one or more DO arguments form a legal argument for a DO. An explicit or implicit QUIT within the scope of the DO, but not within the scope of any other DO, FOR, XECUTE, or extrinsic, returns execution to the instruction following the calling point. This point may be the next DO argument or another command. At the end of a routine, or the end of a nesting level created by an argumentless DO, GT.M performs an implicit QUIT. Any line that reduces the current level of nesting by changing the number of leading periods (.) causes an implicit QUIT, even if that line only contains a comment. Terminating the image and execution of ZGOTO commands are the only ways to avoid eventually returning execution to the calling point. A DO command may optionally pass parameters to the invoked subroutine. 2 Ex_of_Do Examples of DO Example: GTM>DO ^%RD This example invokes the routine directory utility program (%RD) from Direct Mode. The caret symbol (^) specifies that the DO command invokes %RD as an external routine. Example: GTM>DO A(3) This example invokes the subroutine at label A and passes the value 3 as a parameter. Because the DO argument does not have a caret symbol (^), it identifies A as a label in the current routine. Example: Label A; SET di="" U outfile FOR SET di=$O(^div(di)) Q:di="" D PREP D D POST .SET de="",(nr,gr)=0 .WRITE "Division ",di,! F S de=$O(^de(di,de)) Q:de="" D ..WRITE "Department ",de," Gross Rev: ",^grev(di,de),! ..WRITE "Department ",de," Net Rev: ",^nrev(di,de),! ..SET gr=gr+^grev(di,de),nr=nr+^nrev(di,de) .W "Division Gross Rev: ",gr,!,"Division Net Rev: ",nr,! DO PRINT^OUTPUT(outfile) QUIT This routine first uses a DO with a label argument (PREP) to do some pre-processing. Then, it uses an argumentless DO to loop through each division of a company to format a report. Within the first argumentless DO, a second argumentless DO (line 4) loops through and formats each department within a division. After the processing of all departments, control returns to the first argumentless DO, which prints a summary of the division. Following processing of all divisions, a DO with a label argument (POST) does some post-processing. Finally, at the next-to-last line, the routine uses a DO that invokes a subroutine at a label (PRINT) in an external routine (^OUTPUT), passing the name of the output file (outfile) as a parameter. 1 ELSE Else GT.M executes the remainder of the line after the ELSE if $TEST is FALSE (0). GT.M does not execute the rest of the line if $TEST is TRUE (1). The format of the ELSE command is: E[LSE] o Because ELSE is a conditional command, it does not support a command postconditional. o The scope of the ELSE is the remainder of the line. o Because the ELSE has no argument, at least two (2) spaces must follow the command to separate it from the next command on the line. Because the scopes of both the IF and the ELSE commands extend to the rest of the GT.M line, placing an ELSE on the same line as the corresponding IF cannot achieve the desired result. If an ELSE were placed on the same line as its corresponding IF, then the expression tested by the IF would be either TRUE or FALSE. If the condition is TRUE, the code following the ELSE would not be executed. If the condition is FALSE, the ELSE and everything following it would not be executed. ELSE is analogous to IF '$TEST, except the latter statement switches $TEST to its complement and ELSE never alters $TEST. The scope of an ELSE can be extended with DO or XECUTE commands. 2 Ex_of_Else Examples of Else Example: IF x=+x SET x=x+y ELSE WRITE !,x The IF command evaluates the conditional expression x=+x and sets $TEST. If $TEST=1 (TRUE), GT.M executes the commands following the IF. The ELSE on the following line specifies an alternative action to take if the expression is false. Example: IF x=+x DO ^GOFISH ELSE SET x=x_"^"_y The DO with an argument after the IF raises the possibility that the routine ^GOFISH changes the value of $TEST, thus making it possible to execute both the commands following the IF and the commands following the ELSE. Example: OPEN dev::0 ELSE WRITE !,"Device unavailable" QUIT This ELSE depends on the result of the timeout on the OPEN command. If the OPEN succeeds, it sets $TEST to one (1) and GT.M skips the rest of the line after the ELSE. If the OPEN fails, it sets $TEST to zero (0), and GT.M executes the remainder of the line after the ELSE. 1 FOR For The FOR command provides a looping mechanism in GT.M. A FOR command does not generate an additional level on the GT.M invocation stack. The format of the FOR command is: F[OR][lvn=expr[:numexpr1[:numexpr2]][,...]]] o Because FOR is a conditional command, it does not support a command postconditional. o The scope of the FOR is the remainder of the line. o When the FOR has no argument, at least two (2) spaces must follow the command to separate it from the next command on the line. This specifies a loop that must be terminated by a QUIT, HALT, GOTO, or ZGOTO. o The optional local variable name specifies a loop control variable delimited by an equal sign (=). A FOR command has only one control variable, even when it has multiple arguments. o When initiating the FOR, GT.M assigns the loop control variable the value of the expression. When only an initial value appears, GT.M executes the remainder of the line once for that argument without forcing the control variable to be numeric. o If the argument includes an increment and, optionally, a terminator, GT.M treats the initial expression as a number. o The optional numeric expression after the first colon (:) delimiter specifies the increment for each iteration. The FOR command does not increment the control variable on the first iteration. o The optional numeric expression after the second colon (:) delimiter specifies the limiting value for the control variable. This expression is evaluated only when the control variable is initialized to the corresponding initial value, then used for all subsequent iterations. o GT.M does not execute the commands on the same line following the FOR if: The increment is non-negative and the initial value of the control variable is greater than the limiting value. The increment is negative and the initial value of the control variable is less than the limiting value. o After the first iteration, GT.M does not alter the control variable and ceases execution under the control of the FOR if: The increment is non-negative, and altering the control variable by the increment would cause the control variable to be greater than the limiting value. The increment is negative, and altering the control variable by the increment would cause the control variable to be less than the limiting value. o When the FOR has multiple arguments, each one affects the loop control variable in sequence. For an argument to gain control, no prior argument to the FOR can have an increment without a limit. Increments and limits may be positive, negative, an integer, or a fraction. GT.M never increments a control variable "beyond" a limit. Other commands may alter a control variable within the extended scope of a FOR that it controls. When the argument includes a limit, such modification can cause the FOR argument to yield control at the start of the next iteration. The scope of a FOR can be extended with DO or XECUTE commands. GT.M terminates the execution of a FOR when it executes an explicit QUIT or a GOTO (or ZGOTO in GT.M) that appears on the line after the FOR. FOR commands with arguments that have increments without limits and argumentless FORs can be infinite loops. Such FORs must terminate with a QUIT or a GOTO within the immediate scope of the FOR. Also, such FORs can, but seldom, terminate by a HALT within the scope of the FOR as extended by DOs, XECUTEs, and extrinsics. FORs terminated by such commands act as "while" or "until" control mechanisms. 2 Ex_of_For Examples of FOR Example: GTM>KILL i FOR i=1:1:5 WRITE !,i 1 2 3 4 5 GTM>WRITE i 5 GTM> This FOR loop has a control variable, i, which has the value one (1) on the first iteration, then the value two (2), and so on, until in the last iteration i has the value five (5). The FOR terminates because incrementing i would cause it to exceed the limit. Notice that i is not incremented beyond the limit. Example: GTM>FOR x="hello",2,"goodbye" WRITE !,x hello 2 goodbye GTM> This FOR loop uses the control variable x and a series of arguments that have no increments or limits. Notice that the control variable may have a string value. Example: GTM>FOR x="hello":1:-1 WRITE !,x GTM>ZWRITE x x=0 GTM> Because the argument has an increment, the FOR initializes the control variable x to the numeric evaluation of "hello" (0). Then, GT.M never executes the remainder of the line because the increment is positive, and the value of the control variable (0) is greater than the limiting value (-1). Example: GTM>FOR y=-1:-3:-6,y:4:y+10,"end" WRITE !,y -1 -4 -4 0 4 end GTM> This FOR uses two limited loop arguments and one value argument. The first argument initializes y to negative one (-1), then increments y to negative four (-4). Because another increment would cause y to be less than the limit (-6), the first argument terminates with y equal to negative four (-4). The second argument initializes the loop control variable to its current value and establishes a limit of six (6=-4+10). After two iterations, incrementing y again would cause it to be greater than the limit (6), so the second argument terminates with y equal to four (4). Because the final argument has no increment, the FOR sets y to the value of the argument, and GT.M executes the commands following the FOR one more time. Example: GTM>S x="" F S x=$O(ar(x)) Q:x="" W !,x This example shows an argumentless FOR used to examine all first level subscripts of the local array ar. When $ORDER indicates that this level contains no more subscripts, the QUIT with the postconditional terminates the loop. 1 GOTO Goto The GOTO command transfers execution to a location specified by its argument. The format of the GOTO command is: G[OTO][:tvexpr] entryref [:tvexpr][,...] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The required entryref specifies the target location for the control transfer. o The optional truth-valued expression immediately following the entryref specifies the argument postconditional, and controls whether GT.M performs a GOTO with that argument. o An indirection operator and an expression atom evaluating to a list of one or more GOTO arguments form a legal argument to a GOTO. A GOTO command within a line following a FOR command terminates that FOR command. 2 Ex_of_Goto Examples of GOTO Example: GTM>GOTO TIME+4 This GOTO command transfers control from Direct Mode to the line that is four (4) lines after the line labeled TIME (in the currently active routine). Using an offset is typically a debugging technique and rarely used in production code. Example: GOTO A:x<0,^A:x=0,A^B This GOTO command transfers control to label A in the current routine, if x is less than zero (0), to routine ^A if x is equal to zero (0), or to label A in routine ^B. Once any of the transfers occurs, the rest of the arguments have no effect. 1 HALT Halt The HALT command stops GT.M program execution and causes GT.M to return control to the operating system environment that invoked the GT.M image. The format of the HALT command is: H[ALT][:tvexpr] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether GT.M executes the command. o Because the HALT command has no argument, at least two (2) spaces must follow the command to separate it from the next command on the line. Note that additional commands do not serve any purpose unless the HALT has a postconditional. A HALT releases all shared resources held by the process, such as devices OPENed in GT.M, databases, and GT.M LOCKs. If the value of $TLEVEL is greater than zero (0), a ROLLBACK is performed. Because HALT and HANG share the same abbreviation (H), GT.M differentiates them based on whether an argument follows the command. Example: $ gtm GTM>HALT $ Because we invoke this GT.M image interactively, the HALT in Direct Mode leaves the process at the shell prompt. 1 HANG Hang The HANG command suspends GT.M program execution for a period of time specified by the command argument. The format of the HANG command is: H[ANG][:tvexpr] numexpr[,...] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The numeric expression specifies the time in seconds to elapse before resuming execution; actual elapsed time may vary slightly from the specified time. If the numeric expression is negative, HANG has no effect. Portability requirements for GT.M only guarantee accuracy to the nearest second.However, more accuracy can be found on different UNIX systems. o An indirection operator and an expression atom evaluating to a list of one or more HANG arguments form a legal argument to a HANG. A process that repeatedly tests for some event, such as a device becoming available or another process modifying a global variable, may use a HANG to limit its consumption of computing resources. Because HALT and HANG share the same abbreviation (H), GT.M differentiates them based on whether an argument follows the command. 2 Ex_of_Hang Examples of HANG Example: FOR QUIT:$D(^CTRL(1)) HANG 30 This FOR loop repeatedly tests for the existence of ^CTRL(1), and terminates when that global variable exists. Otherwise the routine HANGs for 30 seconds and tests again. Example: SET t=1 F Q:$D(^CTRL(1)) H t I t<30 S t=t+1 This is similar to the previous example, except that it uses an adaptive time that lengthens from 1 second to a limit of 30 seconds if the routine stays in the loop. 1 IF IF The IF command provides conditional execution of the remaining commands on the line. When IF has an argument, it updates $TEST with the truth value of its evaluated argument. GT.M executes the remainder of a line after an IF statement when $TEST is 1 (TRUE). When $TEST is 0 (FALSE), GT.M does not execute the rest of the line. The format of the IF command is: I[F] [tvexpr[,...]] o Because IF is a conditional command, it does not support a command postconditional. o The scope of the IF is the remainder of the line. o The action of IF is controlled by the value of the expression and by $TEST, if there is no expression. o IF with no argument acts on the existing value of $TEST (which it does not change); in this case, at least two (2) spaces must follow the IF to separate it from the next command on the line. o An indirection operator, and an expression atom evaluating to a list of one or more IF arguments form a legal argument to IF. Example: IF A,B ... is equivalent to IF A IF B An IF with more than one argument behaves as if those arguments were logically "ANDed." However, execution of the line ceases with the evaluation of the first false argument. For IF argument expressions containing the "AND" operator (&), execution still ceases with the evaluation of the first false argument. Any global references within the expression act in sequence to maintain the naked reference. Postconditionals perform a function similar to IF; however, their scope is limited to a single command or argument, and they do not modify $TEST. For more information on postconditionals. 2 Ex_of_IF Examples of IF Example: IF x=+x!(x="") DO BAL In this example, the DO executes if x contains a number or a null string. Example: WRITE !,?50,BAL IF 'BAL WRITE "****" IF S EMPTY(acct)="" The IF in the first line changes the value of $TEST, determining the execution of the code following the argumentless IF in the second line. Such argumentless IFs may serve as a form of line continuation. Example: GTM>SET X=1,Y=1,Z=2 KILL UNDEF GTM>IF X=1,Y=1,Z=3,UNDEF=0 W "HI" GTM> The IF command causes GT.M to cease executing the line after it determines Z is not equal to three (3). Therefore, GT.M never evaluates the reference to the undefined variable and never generates an error. Example: GTM>SET X=1 KILL UNDEF GTM>IF X=1!(UNDEF=3) WRITE "HI" HI GTM> Because GT.M recognizes that the X=1 fulfills the IF, it skips evaluation of the UNDEF variable and executes this IF command without generating an error. Because GT.M does not require such optimizations and in fact discourages them by requiring that all global references maintain the naked indicator, other implementations may generate an error. 1 JOB Job The JOB command initiates another GT.M process that executes the named routine. $ZJOB is set to the pid of the process created by the JOB command. For details refer to the "$ZJOB" section in the "Intrinsic Special Variable" chapter of GT.M Programmer's Guide. The format of the JOB command is: J[OB][:tvexpr] entryref [(expr[,...])] [:[(keyword[=value][:...])][:numexpr]][,...] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The required entryref specifies a location at which the new process starts. o The optional parameter list enclosed in parentheses () contains parameters to pass to the routine entry point. o If the JOB specifies a parameter list, the entryref location must start with a label and a formallist. GT.M prohibits entryrefs with offsets during parameter passing. o The optional elements in the parameter list specify expressions that the JOB evaluates and passes as values. o The keywords specify optional processparameters that control aspects of the environment for the new process. o If the JOB command has only one processparameter, the surrounding parentheses are optional. o Some keywords take numeric or string literals delimited by an equal sign (=) as arguments. Because the values are constants, strings must be enclosed in quotation marks (" "), and variable arguments require that the entire argument be constructed and referenced using indirection. o The optional numeric expression specifies a time in seconds after which the command should timeout if unsuccessful; 0 results in a single attempt. o When a JOB command contains no processparameters, double colons (::) separate the time-out numeric expression from the entryref. o An indirection operator and an expression atom, evaluating to a list of one or more JOB command arguments, form a legal argument for a JOB command. o The maximum command-line length from a JOB command is 8192 bytes. The operating system deletes the resultant process when execution of its GT.M process is complete. The resultant process executes asynchrounously with the current process. Once GT.M starts the resultant process, the current process continues. If a JOB command specifies a timeout, and GT.M creates the resultant process before the timeout elapses, JOB sets $TEST to true (1). If GT.M cannot create the process within the specified timeout, JOB sets $TEST to false (0). If a JOB command does not specify a timeout, the execution of the command does not affect $TEST. If GT.M cannot create the process because of something that is unlikely to change during the timeout interval, such as invalid DEFAULT directory specification, or the parameter list is too long, the JOB command generates a run-time error. If the command does not specify a timeout and the environment does not provide adequate resources, the process waits until resources become available to create the resultant process. 2 The_JOB_Env The JOB Environment When the JOB is forked, UNIX creates the environment for the new process by copying the environment of the process issuing the JOB command and making a few minor modifications.By default, the standard input is assigned to the null device, the standard output is assigned to routinename.mjo, and the standard error is assigned to routinename.mje. 3 JOB_Impl_for_Dir JOB Implications for Directories By default, GT.M uses the current working directory of the parent process for the working directory of the initiated process. If the files specified by processparameters do not exist, and GT.M does not have permission to create them, the JOBed process terminates. When the corresponding files are in the current working directory, the OUTPUT, INPUT, and ERROR processparameters do not require a full pathname. 2 JOB_ProcParam JOB Processparameters The following sections describe the processparameters available for the JOB command in GT.M. 3 DEFAULT DEF[AULT]=strlit The string literal specifies the default directory. The maximum directory length is 255 characters. If the JOB command does not specify a DEFAULT directory, GT.M uses the current default directory of the parent process. 3 ERROR ERR[OR]=strlit The string literal specifies a value for stderr. The maximum string length is 255 characters. By default, JOB constructs the error file from the routinename using a file extension of .mje: the default directory of the process created by the JOB command. 3 GBLDIR GBL[DIR]=strlit The string literal specifies a value for the environment variable gtmgbldir. The maximum length of the value permitted is 255 characters. By default, the job uses the same specification for gtmgbldir as that defined for the process using the JOB command. 3 INPUT IN[PUT]=strlit The string literal specifies a value for stdin. The maximum string length is 255 characters. GT.M does not supply a default file extension. By default, the job takes its input from the null device. 3 OUTPUT OUT[PUT]=strlit The string literal specifies a value for stdout. The maximum string length is 255 characters. By default, JOB constructs the output file pathname from the routinename using a file extension of .mjo and the current default directory of the process created by the JOB command. 3 STARTUP STA[RTUP]=strlit The string literal specifies a command line that GT.M invokes a shell to execute before executing the GT.M routine. The command line may invoke a shell script or other images. The executed command does not affect the environment of the JOBed process. 2 Ex_of_JOB Examples of JOB Example: GTM>JOB ^TEST This creates a job that starts doing the routine ^TEST in the current working directory. Example: JOB PRINTLABELS(TYPE,PRNTR,WAITIM) This passes three values (TYPE, PRNTR, and WAITIM) to the new job, which starts at the label PRINTLABELS of the current routine. 1 KILL Kill The KILL command deletes local or global variables and their descendant nodes. The format of the KILL command is: K[ILL][:tvexpr] [glvn|[(]lvn[,...][)][,...]] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The optional global or local variable name specifies the variable to delete; KILL deletes not only the variable specified in the argument, but also all variables descended from that variable, that is, those starting with the identical key-prefix. o KILLing a variable that does not currently exist has no effect. o The KILL command without an argument deletes all currently existing local variables; in this case, at least two (2) spaces must follow the KILL to separate it from the next command on the line. o When a KILL argument is enclosed in parentheses, that "exclusive" KILL deletes all local variables except those listed in the argument. o An indirection operator and an expression atom evaluating to a list of one or more KILL arguments o form a legal argument for a KILL. KILL does not affect copies of local variables that have been "stacked" by NEW or parameter passing. Because a KILL can have a major impact, use KILL with caution. 2 Ex_of_Kill Examples of KILL Example: GTM>KILL SET a=0,a(1)=1,a(1,1)="under" KILL a(1) ZWR a=0 GTM> This uses an argumentless KILL to get a "fresh start" by deleting all existing local variables. After SETting a, a(1), and a(1,1), the KILL deletes a(1) and its descendants. The ZWRITE shows only a remaining. Example: GTM>KILL (a,b),^AB(a,b) The first argument (an exclusive KILL) specifies to KILL all local variables except a and b. The second argument deletes ^AB(a,b) and any descendants of that global variable node. 1 LOCK Lock The LOCK command is used to reserve and release resource names, providing a semaphore capability for GT.M processes. This capability can be used for interprocess synchronization and signaling. Assigning a LOCK does not specify any explicit control over variables and does not directly effect either read or write access to global (or local) data. However, an application that adheres to clearly defined conventions of LOCKing before any access can indirectly achieve such an effect. The format of the LOCK command is: L[OCK][:tvexpr] [[-|+]nref|(nref[,...])[:numexpr] [,...]] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The nref argument specifies a resource name in the format of the GT.M name, with or without subscripts and with or without a preceding caret (^). An nref can optionally have an environment specification, including one without a preceding caret (^). o Outside of transactions, only one process in an environment can own a particular LOCK at any given time. o Because the data storage in GT.M uses hierarchical sparse arrays, and LOCK frequently serves to protect that data from inappropriate "simultaneous" access by multiple processes, LOCK treats resource names in a hierarchical fashion; a LOCK protects not only the named resource, but also its ancestors and descendants. o When one or more nrefs are enclosed in parentheses (), LOCK reserves all the enclosed names "simultaneously," that is, it reserves none of them until all become available. o A LOCK with no argument or an argument with no leading sign releases all names currently reserved with previous LOCK commands by the process; when a LOCK has no argument, at least two (2) spaces must follow the LOCK to separate it from the next command on the line. o A LOCK argument with a leading plus sign (+) acquires the named resources without releasing currently held resources; if the named resource is already LOCKed, such a LOCK "counts up" the process interest in the resource. o A LOCK argument with a leading minus sign (-) "counts down" the process interest in a named resource; if the count on a particular lock reaches zero (0), GT.M releases the lock without releasing any other currently held locks; a LOCK that releases a named resource not currently owned by the process has no effect. o The optional numeric expression specifies a time in seconds after which the command should timeout if unsuccessful; 0 provides a single attempt. o An indirection operator and an expression atom evaluating to a list of one or more LOCK arguments form a legal argument for a LOCK. GT.M records LOCK and ZALLOCATE information in the "lock database." GT.M distributes the lock database in space associated with the database identified by the current Global Directory. However, the lock database does not overlap or coincide with the body of the database files holding the global data. Only the LOCK, ZALLOCATE and ZDEALLOCATE commands, and the LKE utility program access the lock database. GT.M maps reservations of names starting with ^ to the database file used to map global variables of the same name. If the Global Directory maps the name A to file A.DAT, GT.M maps all reservations on ^A to file space associated with A.DAT. GT.M maps reservations on names not starting with ^ to the region of the database specified with the GDE command LOCK -REGION=. By default, when GDE creates a Global Directory any reservations of local names are mapped to the region DEFAULT. These two factors effect the following result in the programming environment: o ^ reservations automatically intersect for all users of the same data in any database file independent of the Global Directory mapping that file. o reservations without a leading ^ intersect in an arbitrary pattern dependent on the Global Directory and therefore controlled by a design decision made independently of application code design. Since GT.M uses resource names as semaphores for signaling among multiple processes in a database environment, they interlock in a tree structured fashion. When LOCK or ZALLOCATE reserves a subscripted resource name such as ^D(1), other users of the database mapped by the LOCKing (or ZALLOCATEing) process cannot reserve ancestors of that name, such as ^D, or descendants, such as ^D(1,2), until LOCK or ZDEALLOCATE releases that name. Execution of the LOCK command does not affect the value or the state of a variable. LOCK tests each argument to determine whether the process can claim the name space. If another GT.M process has a LOCK on that name space, GT.M suspends the current process until the other process releases the name space. To prevent the potential "infinite" suspension of a routine execution, specify a timeout for the LOCK command. LOCK with a leading plus (+) or minus (-) sign (incremental LOCKing) allows the acquisition of locks without releasing currently held locks. This can lead to deadlocks. To avoid deadlocks, use LOCK without a leading + or - sign on its arguments because such a command releases all previously LOCKed resources; or use a timeout with the LOCK command. If a LOCK command specifies a timeout, and GT.M acquires ownership of the named resource before the timeout elapses, LOCK sets $TEST to TRUE (1). If GT.M cannot acquire ownership of the named resource within the specified timeout, LOCK sets $TEST to FALSE (0). If a LOCK command does not specify a timeout, the execution of the command does not affect $TEST. If a LOCK with an argument having a leading minus sign (-) specifies a timeout, the command always sets $TEST to TRUE (1). If a process issues a LOCK command for a named resource already ZALLOCATEd by that process, the resource is both ZALLOCATEd and LOCKed. LOCK does not release ZALLOCATEd resources. To release such a named resource, the process must both ZDEALLOCATE and unLOCK the resource. For more information on ZALLOCATE, refer to the "ZALLOCATE". 2 Locks_within_Trans Using Locks within Transactions Within transactions LOCKs are used by GT.M to ensure the ability to serialize. There is no guarantee, however, that attempts by other processes to examine LOCKs held with a transaction will produce the same results as when LOCKs are outside of a transaction. In other words, LOCKs within transactions should never be used as simple semaphores. The LOCK command locks a specified resource name that controls a tree structured name space. Outside of transactions when one process in an environment acquires a LOCK or a ZALLOCATE on a named resource, no other GT.M process in that environment can LOCK a resource with an "overlapping" name until the first process releases the LOCK that it holds. 2 Ex_of_Lock Examples of LOCK Example: LOCK A,^B,@C LOCK (A,B,@C) The first LOCK command LOCKs A and unLOCKs A before LOCKing ^B, then unLOCKs ^B before locking the name specified by the variable C. The second LOCK command acquires all three resources at once. GT.M waits until all the named resources in the argument list become available before LOCKing all the resources. For example, if the resource specified by the variable C is not available for LOCKing, GT.M waits until that resource becomes available before LOCKing A and ^B. Example: LOCK (A,B) LOCK +C LOCK -B This LOCKs A and B, then incrementally LOCKs C. Finally it releases the LOCK on B, while retaining the LOCKs on A and C. Example: LOCK (A,B,C) LOCK +(B,C) LOCK -(B) This LOCKs A, B and C together. It then increments the lock "counts" of B and C. The last LOCK command removes one "count" of B, leaving one count of A and B and two counts of C. Example: LOCK ^D:5 This command attempts to LOCK ^D with a timeout of five seconds. If LOCK acquires the named resource before the timeout elapses, GT.M sets $TEST to 1 (TRUE). If LOCK fails to acquire the named resource before the timeout elapses, GT.M sets $TEST to 0 (FALSE). 1 MERGE Merge The MERGE command copies a variable and all its descendants into another variable. MERGE does not delete the destination variable, nor any of its descendants. The format of MERGE command is: M[ERGE][:tvexpr] glvn1=glvn2[,...] o The optional truth-valued expression immediately following the command is a command post conditional that controls whether or not GT.M executes the command. o When both glvn1 and glvn2 are local variables, the naked indicator is not changed. o If glvn2 is a global variable and glvn1 is a local variable, then the naked indicator references glvn2. o When both are global variables, the state of the naked indicator is unchanged if glvn2 is undefined ($DATA(glvn2)=0). o In all other cases including $DATA(glvn2)=10, the naked indicator takes the same value that it would have if the SET command replaced the MERGE command and glvn2 had a value. o If glvn1 is a descendant of glvn2, or if glvn2 is a descendant of glvn1; GT.M generates an error. o An indirection operator and an expression atom evaluating to a list of one or more MERGE arguments form a legal argument for a MERGE. MERGE simplifies the copying of a sub-tree of a local or global variable to another local or global variable. A sub-tree is all global or local variables that are descendants of an specified variable. MERGE offers a one-command alternative to the current technique for doing sub-tree copy (that is, a series of SET commands with $ORDER references). GT.M may permit certain syntax or actions that are described by the standard as in error. For example, a MERGE command that specifies an operation where the source and destination overlap but $DATA(source)=0 does not produce an error (which is equivalent to a no-operation). 2 Ex_of_Merge Examples of MERGE Example: GTM>SET ^gbl1="one" GTM>SET ^gbl1(1,1)="oneone" GTM>SET ^gbl1(1,1,3)="oneonethree" GTM>SET ^gbl1(1,2,4)="onetwofour" GTM>SET ^gbl2(2)="gbl2_2" GTM>SET ^gbl2(2,1,3)="gbl2_2_1_3" GTM>SET ^gbl2(2,1,4,5)="gbl2_2_1_4_5" GTM>MERGE ^gbl1(1)=^gbl2(2) GTM>WRITE $REFERENCE ^gbl1(1) GTM>ZWRITE ^gbl1 ^gbl1="one" ^gbl1(1)="gbl2_2" ^gbl1(1,1)="oneone" ^gbl1(1,1,3)="gbl2_2_1_3" ^gbl1(1,1,4,5)="gbl2_2_1_4_5" ^gbl1(1,2,4)="onetwofour" GTM>ZWRITE ^gbl2 ^gbl2(2)="gbl2_2" ^gbl2(2,1,3)="gbl2_2_1_3" ^gbl2(2,1,4,5)="gbl2_2_1_4_5" GTM> The example illustrates how MERGE copies a sub-tree of one global into another. The nodes in the sub-tree of ^gbl(2), for which $DATA() value is 1 or 11, are copied to sub-tree of ^gbl1(1) as follows: ^gbl1(1) is updated with value of ^gbl2(2) ^gbl1(1,1,3) is updated with value of ^gbl2(2,1,3) ^gbl1(1,1,4,5) is updated with value of ^gbl2(2,1,4,5) Since ^gbl1(2,1) and ^gbl2(2,2,4) do not have values ($DATA()=0), the corresponding nodes ^gbl1(1,1) and ^gbl(1,2,4) respectively are left unchanged. The naked indicator takes the value ^gbl(1) as if SET replaced MERGE. Notice that the MERGE command does not change ^gbl2(2) or its descendants. Ancestor nodes of ^gbl(1) are also left unchanged. Example: GTM>KILL GTM>SET ^gbl(1,2)="1,2" GTM>MERGE lcl(3,4)=^gbl(1) GTM>SET ^("naked")=2 GTM>ZWRITE ^gbl ^gbl(1,2)="1,2" ^gbl("naked")=2 GTM>ZWRITE lcl lcl(3,4,2)="1,2" GTM> The example illustrates how MERGE creates a sub-tree of a variable when the variable does not exist. Also, notice how the naked indicator is set when the source of the MERGE is a global and the destination a local. 1 NEW New The NEW command "stacks" copies of local variables and reinitializes the variables. An explicit or implicit QUIT from a DO, XECUTE or extrinsic function "unstacks" the NEWed variables, that is, restores the variable to the stacked value. A NEW lasts only for the current scope of execution. The format of the NEW command is: N[EW][:tvexpr] [[(]lvn[,...][)][,...]] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o NEW arguments are unsubscripted local variable names; NEW affects not only the variable specified in the argument, but also all variables descended from that variable. o When an undefined variable is NEWed, the fact that it is undefined is "stacked", and when leaving the current scope, it returns to being undefined, that is, the variable is KILLed. o Without an argument GT.M NEWs all currently existing local variables; in this case, at least two (2) spaces must follow the NEW to separate it from the next command on the line. o When a NEW argument is enclosed in parentheses, that NEW is considered "exclusive" and the variables inside the parentheses are excluded from the effect of the NEW. o When the flow of execution leaves the scope of an argumentless or an exclusive NEW, GT.M restores all stacked variables to their previous values, and deletes all other local variables. o The intrinsic special variables $ESTACK, $ETRAP, $ZGBLDIR, and $ZYERROR can be an explicit argument of a NEW. o The intrinsic special variable $ZTRAP can also be an explicit argument of a NEW; this stacks the current value of $ZTRAP and assigns $ZTRAP a null value ($ZTRAP=""). o An indirection operator and an expression atom evaluating to a list of one or more NEW arguments form a legal argument for a NEW. The NEW command provides a means of confining the scope of local variables. NEW operates only on unsubscripted local names and acts on the entire named array. 2 Ex_of_New Examples of NEW Example: SET A(1)=1,B=4,C=5 WRITE !,"VARIABLES BEFORE NEW:",! ZWRITE DO LABEL WRITE !,"VARIABLES AFTER RETURN:",! ZWRITE QUIT LABEL NEW A SET C=7 WRITE !,"VARIABLES AFTER NEW:",! ZWRITE QUIT Produces the results: VARIABLES BEFORE NEW: A(1)=1 B=4 C=5 VARIABLES AFTER NEW: B=4 C=7 VARIABLES AFTER RETURN: A(1)=1 B=4 C=7 Example: SET (A,B,C,D)="TEST" DO LABEL WRITE !,"VARIABLES AFTER RETURN:",! ZWRITE QUIT LABEL NEW (B,C) SET (A,B,Z)="NEW" WRITE !,"VARIABLES AFTER EXCLUSIVE NEW:",! ZWRITE QUIT Produces the results: VARIABLES AFTER EXCLUSIVE NEW: A="NEW" B="NEW" C="TEST" Z="NEW" VARIABLES AFTER RETURN: A="TEST" B="NEW" C="TEST" D="TEST" 1 OPEN Open The OPEN command creates a connection between a GT.M process and a device. The format of the OPEN command is: O[PEN][:tvexpr] expr[:[(keyword[=expr][:...])] [:numexpr]][,...] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The required expression specifies the device to OPEN. o The optional keywords specify deviceparameters that control device behavior; some deviceparameters take arguments delimited by an equal sign (=); if the argument only contains one deviceparameter, the surrounding parentheses are optional. o The optional numeric expression specifies a time in seconds after which the command should timeout if unsuccessful; choosing 0 results in a single attempt to open the device. o When an OPEN command specifying a timeout contains no deviceparameters, double colons (::) separate the timeout numeric expression from the device expression. o An indirection operator and an expression atom evaluating to a list of one or more OPEN arguments form a legal argument for an OPEN. 1 QUIT Quit Except when a QUIT appears on a line after a FOR, the QUIT command terminates execution of the current GT.M invocation stack level initiated by a DO, XECUTE, extrinsic function or special variable, and returns control to the next "lower" level. In this case, QUIT restores any values stacked at the current level by NEWs or by parameter passing. When a QUIT appears on the line following a FOR, it terminates execution of the FOR. The format of the QUIT command is: Q[UIT][:tvexpr] [expr] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o When a QUIT terminates an extrinsic function, it must have an argument that supplies the value returned by the function; in all other cases, QUIT must not have an argument and must be followed by at least two (2) spaces to separate it from the next command on the line. o An indirection operator and an expression atom evaluating to a QUIT argument form a legal argument for a QUIT. The QUIT performs two similar, but different, functions depending on its context. Because FORs do not add levels to the GT.M invocation stack, QUITs inside FOR loops simply terminate the loop. QUITs that terminate DOs, XECUTEs and extrinsics remove a GT.M invocation stack level and therefore may adjust the local variable environment resulting from previous NEWs or parameter passing. A QUIT from an extrinsic or a frame created by an argumentless DO restores $TEST to its stacked value. Attempting to QUIT (implicitly or explicitly) from code invoked by a DO, XECUTE or extrinsic after that code issued a TSTART not yet matched by a TCOMMIT, produces an error. 2 Ex_of_Quit Examples of QUIT Example: DO A QUIT A WRITE !,"This is label A" The explicit QUIT at the line preceding the label A prevents line A from executing twice. The sub-routine at line A terminates with the implicit QUIT at the end of the routine. Example: WRITE $$ESV QUIT ESV() QUIT "value of this Extrinsic Special Variable" Because the label ESV has an argument list (which is empty), GT.M can only legally reach that label with a extrinsic invocation. The QUIT on the second line prevents execution from erroneously "falling through" to the line labelled ESV. Because ESV identifies a subroutine that implements an extrinsic special variable, the QUIT on the line after ESV has an argument to provide the value of the extrinsic. Example: SET x="" F S x=$O(^BAL(x)) Q:x]]"AR5999"!'$L(x) D STF The postconditional QUIT terminates the FOR loop. 1 READ Read The READ command transfers input from the current device to a global or local variable specified as a READ argument. For convenience, READ also accepts arguments that perform limited output to the current device. The format of the READ command is: R[EAD][:tvexpr] (glvn|*glvn|glvn#intexpr)[:numexpr]|strlit|fcc[,...] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o A subscripted or unsubscripted global or local variable name specifies a variable into which to store the input; the variable does not have to exist prior to the READ; if the variable does exist prior to the READ, the READ replaces its old value. o When an asterisk (*) immediately precedes the variable name, READ accepts one character of input and places the ASCII code for that character into the variable. o When a number-sign (#) and a non-zero integer expression immediately follow the variable name, the integer expression determines the maximum number of characters accepted as input to the read; such reads terminate when GT.M reads the number of characters specified by the integer expression or a terminator character in the input stream, whichever occurs first. o The optional numeric expression specifies a time in seconds at most, for which the command waits for input to be terminated. When a timeout is specified, if the input has been terminated before the timeout expires, $TEST is set to 1 (true), otherwise, $TEST is set to 0 (false). o To provide a concise means of issuing prompts, GT.M sends string literal and format control character (!,?intexpr,#) arguments of a READ to the current device as if they were arguments of a WRITE. o An indirection operator and an expression atom evaluating to a list of one or more READ arguments form a legal argument for a READ. 1 SET Set SET assigns values to variables or to a selected portion of a variable. The format of the SET command is: S[ET][:tvexpr] glvn|$EXTRACT()|$PIECE()|(glvn[,...])=expr[,...] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o A subscripted or unsubscripted local or global variable name on the left of the equal-sign (=) specifies a variable in which to store the expression found on the right side of the equal-sign; the variable need not exist prior to the SET; if the variable exists prior to the SET, the SET replaces its old value. o During a SET, GT.M evaluates the right side of the equal sign before the left; this is an exception to the left-to-right order of evaluation in GT.M and means that GT.M maintains the naked indicator using the expression on the right-hand side of the equal sign (=) before setting the variable. o When the portion of the argument to the left of the equal-sign is in the form of a list of variables enclosed in parentheses, SET assigns the value of the expression on the right of the equal sign to all the variables. o When the portion of the argument to the left of the equal sign is in the form of a $PIECE function, SET replaces the specified piece or pieces of the variable (specified as the first argument to the $PIECE() form) with the value of the expression on the right side of the equal-sign; if the variable did not exist prior to the SET or does not currently contain the pieces identified by the optional third and fourth arguments to the $PIECE() form, SET adds sufficient leading delimiters, as specified by the second argument to the $PIECE form, to make the assignment fit the $PIECE() form. Note that if the fourth argument exceeds the third argument, the target glvn is not changed and the naked indicator is also not modifed. o When the portion of the argument to the left of the equal sign is in the form of a $EXTRACT function, SET replaces the specified character or characters of the variable (specified as the first argument to the $EXTRACT() form) with the value of the expression on the right side of the equal-sign; if the variable did not exist prior to the SET or does not contain the characters identified by the optional second and third arguments to the $EXTRACT() form, SET adds sufficient leading spaces to make the assignment fit the $EXTRACT() form. Note that if the third argument exceeds the second argument, the target glvn is not changed and the naked indicator is also not modifed. o The left-hand side of the equal-sign may also contain any of the following Intrinsic Special Variables: $ECODE $ETRAP $X $Y $ZCOMPILE $ZDIRECTORY $ZERROR $ZGBLDIR $ZINTERRUPT $ZMAXTPTIME $ZPROMPT $ZROUTINES $ZSOURCE $ZSTATUS $ZSTEP $ZTRAP $ZYERROR o An indirection operator and an expression atom evaluating to a list of one or more SET arguments form a legal argument for a SET. Because GT.M does not require predeclaration or typing of variables, a SET with proper syntax always succeeds regardless of the prior state or value of the variable, as long as GT.M can evaluate the expression to the right of the equal sign (=). 2 Ex_of_Set Examples of SET Example: GTM>KILL SET a="x",(b,c)=1,@a="hello" ZWRITE a=x b=1 c=1 x="hello" GTM> The KILL command deletes any previously defined local variables. The SET command has three arguments. The first shows a simple direct assignment. The second shows the form that assigns the same value to multiple variables. The third shows atomic indirection on the left of the equal sign. The ZWRITE command displays the results of the assignments. Example: GTM>SET ^(3,4)=^X(1,2) Because GT.M evaluates the right-hand side of the equal sign before the left-hand side within a SET argument, the right-hand expression determines the naked reference indicator prior to evaluation of the left-hand side. Therefore, this example assigns ^X(1,3,4) the value of ^X(1,2). Example: GTM>KILL x SET $P(x,"^",3)="piece 2" ZWRITE x x="^^piece 2" GTM> This SET demonstrates a "setpiece" and shows how SET generates missing delimiters when required. Example: GTM>SET x="I love hotdogs" GTM>SET $EXTRACT(x,3,6)="want" GTM>WRITE x I want hotdogs GTM>SET $EXTRACT(x,7)=" many " GTM>WRITE x I want many hotdogs GTM> The SET $EXTRACT command replaces and extracts the specified characters with the value of the expression on the right hand side of the equal-sign (=). 1 TCOMMIT TCommit The TCOMMIT command marks the end of a transaction or sub-transaction and decrements $TLEVEL. If TCOMMIT marks the end of a transaction (decrements $TLEVEL to zero), it invokes a COMMIT, which makes the database updates performed by the transaction generally available. A TCOMMIT issued when no transaction is in progress ($TLEVEL=0) produces an error. The format of the TCOMMIT command is: TC[OMMIT][:tvexpr] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o Because TCOMMIT has no argument, at least two (2) spaces must follow the command to separate it from the next command on the line. For an example of the use of the TCOMMIT command, refer to the chapter on General Language Features of M in GT.M Programmer's Guide. 1 TRESTART TREstart The TRESTART command attempts to RESTART the current transaction. A RESTART transfers control back to the initial TSTART and restores much of the process state to what it was when that TSTART was executed. Errors are produced if a TRESTART is used when no transaction is in progress ($TLEVEL=0) and when the transaction does not have RESTART enabled. The format for the TRESTART command is: TRE[START][:tvexpr] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o Because TRESTART has no argument, at least two (2) spaces must follow the command to separate it from the next command on the line. TRESTARTs (and implicit RESTARTs) do not restore any device states; they do restore the following to the state they had when GT.M executed the initial TSTART: o $TEST o The naked indicator o LOCKs held by the process They also restore any local variables named by one or more active TSTARTs to the values they had when they were first named. For an example of the use of the TRESTART command, refer to the chapter on "General Language Features of M" in the GT.M Programmer's Guide. 1 TROLLBACK TROllback The TROLLBACK command terminates a transaction by causing a ROLLBACK, which removes all database updates performed within a transaction. TROLLBACK also sets $TLEVEL and $TRESTART to zero (0). Issuing a TROLLBACK when no transaction is in progress ($TLEVEL=0) produces an error. The format of the TROLLBACK command is: TRO[LLBACK][:tvexpr] [intexpr] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The optional integer expression indicates an argument specifying incremental rollback. If the value of the argument expression is greater than zero, it specifies the value of $TLEVEL to be achieved by the rollback. If the value of the expression is less than zero, the result is the number of levels to rollback. For example; -1 means rollback one level. If the argument expression is zero, the effect is same as not specifying the argument, that is, the entire GT.M transaction is rolled back. Attempting to rollback more than $TLEVEL levels (the outermost transaction) generates an error. o When the TROLLBACK has no argument, at least two (2) spaces must follow the command to separate it from the next command on the line. In order to allow for error recovery and/or access to the global context of the error, errors do not initiate implicit ROLLBACKs. Therefore, the code for handling errors during transactions should generally include a TROLLBACK. Because the TROLLBACK releases resources held by the transaction, it should appear as early as possible in the error handling code. A TROLLBACK does not cause a transfer of control but is typically associated with one such as a QUIT or GOTO. For an example of the use of the TROLLBACK command, refer to the chapter on "General Language Features of M" in the GT.M Programmer's Guide. 1 TSTART TStart A TSTART command marks the beginning of a transaction or sub-transaction and increments $TLEVEL. When TSTART marks the beginning of a transaction ($TLEVEL=1), its arguments determine whether the transaction may RESTART and whether serializability is enforced. If a transaction may RESTART, the TSTART arguments determine which local variables are restored during a RESTART. Serializability is enforced by LOCK commands or, if the SERIAL keyword is specified, by GT.M. The format of the TSTART command is: TS[TART][:tvexpr] [([lvn...])|lvn|*|][:keyword|(keyword...)] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o If $TLEVEL is 0 before the TSTART, the TSTART starts a transaction; otherwise it starts a sub-transaction. o If the TSTART initiates a transaction and the portion of the argument before the colon (:) delimiter is empty, the transaction is not eligible for RESTART. If the TSTART starts a transaction ($TLEVEL=0) and the portion of the argument before the colon is not empty, the transaction is eligible for RESTART. If the TSTART is nested (starts a sub-transaction), its arguments have no effect on whether the transaction is eligible for RESTART. o If the portion of the argument before the colon is an asterisk (*), any subsequent RESTART restores all local variables to the value they had when the TSTART was executed. o If the portion of the argument before the colon is an unsubscripted local variable name or a list of such names enclosed in parentheses, a RESTART restores the named variables to the value they had when the TSTART was executed. o If the portion of the argument before the colon is a set of empty parentheses (), a RESTART does not restore any local variables. o The optional portion of the argument after the colon is a keyword or a colon-separated list of keywords enclosed in parentheses, where the keywords specify transaction characteristics. o An indirection operator and an expression atom evaluating to a TSTART argument form a legal argument for a TSTART. A TSTART within a transaction starts a sub-transaction. The argument to such a TSTART has no effect on whether the existing transaction may RESTART or whether serializability of the transaction is enforced. This type of TSTART may add local variables to be restored in a transaction that has RESTART enabled. It is good coding practice to synchronize enabling of RESTART on TSTARTs at all levels of a transaction. A nested TSTART that does not permit RESTART where the transaction does, may indicate that the sub-transaction has not been coded to properly handle RESTART. Sub-transactions cannot COMMIT independently from the transaction, nor can they RESTART independently. Sub-transactions exist largely as a programming convenience to allow flexibility in organizing code in a modular fashion, and in addition to allow incremental ROLLBACKs. When journaling, a transaction with an initial TSTART that has an argument specifying TRANSACTIONID=expr, where expr is an expression that evaluates to the keyword (case insensitive) BA[TCH], does not wait for the journal update to be written before returning control to the application after a successful TCOMMIT. The goal of this feature is to permit application control over any performance impact of journaling on any subset of transactions that can be recreated or recovered by means other than journaling. For an example of the use of the TSTART command, refer to the chapter on "General Language Features of M" in the GT.M Programmer's Guide. The following keywords may appear in a TSTART argument: 2 SERIAL S[ERIAL] The SERIAL keyword indicates that GT.M must ensure the serializability of the transaction. When the SERIAL keyword is absent, the GT.M program must ensure serializability by proper use of LOCK commands. On a nested TSTART, this portion of the argument is ignored. 2 TRANSACTIONID T[RANSACTIONID]=expr The TRANSACTIONID keyword declares an arbitrary transaction identification. If TRANSACTIONID="BATCH" or "BA" at transaction completion, the process immediately continues execution. When a process issues a [final] TCOMMIT for a transaction and journaling is active, by default the process waits until the entire transaction is written to the journal file(s) before executing the next command. This ensures that every transaction is durable before the process moves on to the next step. Transactions flagged as "BATCH" have lower latency and higher throughput, but a lower guarantee of durability. Normally this flag is used when operational procedures (such as a backup) or application code (such as a checkpoint algorithm) provides an acceptable alternative means of ensuring durability. 1 USE Use The USE command selects the current device for READs (input) and WRITEs (output). The format of the USE command is: U[SE][:tvexpr] expr[:(keyword[=expr][:...])][,...] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The required expression specifies the device to make the current device. o A USE that selects a device not currently OPENed by the process causes a run-time error. o The optional keywords specify deviceparameters that control device behavior; some deviceparameters take arguments delimited by an equal sign (=); if the argument only contains one deviceparameter, the surrounding parentheses are optional. o An indirection operator and an expression atom evaluating to a list of one or more USE arguments form a legal argument for a USE. For more information on USE, devices and deviceparameters, refer to the "Input/Output Processing" chapter in the GT.M Programmer's Guide. 1 VIEW View The VIEW command adjusts an environmental factor selected by a keyword argument. For example, VIEW controls journal buffer flushing, determines whether GT.M reports undefined variables as errors or treats them as null, and determines which BREAK commands should display messages. The format of the VIEW command is: V[IEW][:tvexpr] keyword[:expr2[:...]][,...] o The optional truth-valued expression immediately following the command is a command postconditional that controls whether or not GT.M executes the command. o The keyword specifies the environmental factor to change. o The optional expression following the keyword specifies the nature of the change to the environmental factor. o An indirection operator and an expression atom evaluating to a list of one or more VIEW arguments form a legal argument for a VIEW 2 Key_Words_View Key Words in VIEW Command The following sections describe the keywords available for the VIEW command in GT.M. 3 BREAKMSG "BREAKMSG":value Sets the value of the BREAK message mask. When GT.M processes a BREAK command, the BREAK message mask controls whether to display a message describing the source of the BREAK. The mask uses the following four values that are added together to provide the BREAKMSG value. 1 - BREAKs within the body of a program 2 - BREAKs within a ZBREAK action 4 - BREAKs within a device EXCEPTION 8 - BREAKs within a ZSTEP action By default GT.M displays all BREAK messages. Example: GTM>VIEW "BREAKMSG":5 In this example the BREAKMSG value is 5, representing the sum of 1 and 4. This enables BREAKS within the body of a program (value 1) and for a device EXCEPTION (value 4). 3 GDSCERT "GDSCERT":value Enables (value=1) or disables (value=0) database block certification. Database block certification causes GT.M to check the internal integrity of every block as it writes the block. Block certification degrades performance and exists primarily as a tool for use by Sanchez. The default is GDSCERT:0. 3 JNLFLUSH "JNLFLUSH"[:region] Writes or flushes journaling buffers associated with the given region to permanent storage, for example, to disk. If the VIEW "JNLFLUSH" does not specify the optional region, GT.M flushes all active regions of the current Global Directory. Normally GT.M writes journal buffers when it fills the journal buffer pool or when some period of time passes with no journal activity. For more information on journaling, refer to the "GT.M Journaling" chapter in the GT.M Administration and Operations Guide. 3 JNLWAIT "JNLWAIT" Causes a process to pause until its journaling buffers have been written. JNLWAIT ensures that GT.M successfully transfers all database updates issued by the process to the journal file before the process continues. Normally, GT.M performs journal buffer writes asynchronously while the process continues execution. For more information on journaling, refer to the "GT.M Journaling" chapter in the GT.M Administration and Operations Guide. 3 JOBPID "JOBPID":"value" Enables (value=1) or disables (value=0) the addition of the child process ID to the output and error filenames generated by the JOB command. This option prevents output files generated by the JOB command from being overwritten each time a new job is spawned from the GT.M source file. 3 LABELS "LABELS":"value" Enables (value="LOWER") or disables (value="UPPER") case sensitivity for labels within routines. It is important to have the same case handling at compile-time and run-time. Because GT.M stores routines as regular files and file names are case sensitive on UNIX, GT.M always treates routine names as case sensitive. 3 LVNULLSUBS "[NO]LVNULLSUBS" Allows or disallows local arrays to have null subscripts. The default is LVNULLSUBS. 3 NOISOLATION "NOISOLATION": where expr must evaluate to one of the following forms o "", that is, empty string : turn off the feature for all globals for which it has previously been turned on o "^gvn1,^gvn2,..." : turn on the feature for the globals in the list, turning it off for globals for which it has previously been turned on o "+^gvn1,^gvn2,..." : add these globals to the list of globals that have this feature turned on o "-^gvn1,^gvn2,..." : turn off the feature for these globals leaving the status for other globals unchanged GT.M transaction processing permits the application to specify a set of globals that do not require GT.M to preserve Isolation, one of the "ACID" properties of TP. This shifts the responsibility for Isolation from GT.M to the application logic, and permits GT.M to relax its TP Isolation rules. This avoids TP restarts in certain cases thus improving the performance of the application. For example, if a global variable includes $JOB as a subscript, the application may be written and scheduled in such a way that no more than one process uses a node of that global at any given time. Specifying such a global as "NOISOLATED" avoids transaction restarts that occur when different processes concurrently update and access nodes that share the same GDS block. The rules for enforcement by GT.M of Isolation, and therefore potentially Consistency, are relaxed for application-specified global variables in order to allow the application to manage these properties. GT.M is responsible for Atomicity and Durability, as well as for database integrity for all variables, and for Isolation and Consistency for any global variables for which the application does not accept responsibility. Note that if an application incorrectly specifies a global to be NOISOLATED, severe, and possibly intermittent and difficult to diagnose damage to application-level integrity is likely to result. A thorough understanding of the application is necessary before declaring a global to be noisolated. GT.M preserves database integrity (accessibility) for NOISOLATED, as well as ISOLATED global variables. GT.M ignores attempts to turn on (or off) the feature for globals that already have the feature turned on (or off). It is an error to modify the isolation-status of a global variable within a transaction across different references (either reads or writes) of that global variable.The VIEW command by itself is not considered to be a reference of the global variable. While not recommended programming practice, this means that a process can change a global's isolation-status within a transaction as long as it hasn't referenced it yet. Any reads on a NOISOLATION global are validated at the time of the read and not re-validated at TCOMMIT time. This means that if the value that was read changed after the read but before the TCOMMIT, the transaction would still be committed. Therefore it is important that any reads on a NOISOLATED global (if any) should be of data that does not change with time. Sanchez has not identified applications where this could be an issue. 3 PATCODE "PATCODE":"tablename" Identifies the alternative table of unique patterns for use with the "?" operator to be loaded from the pattern definition file. For additional information refer to the "Internationalization" chapter in the GT.M Programmer's Guide. 3 PATLOAD "PATLOAD":"file-specification" Identifies the file containing definitions of unique patterns for use with the "?" operator. These pattern definitions can be used in place of, or in addition to, the standard C, N, U, L, and P. 3 UNDEF "[NO]UNDEF" Enables or disables handling of undefined variables as errors. With UNDEF, GT.M handles all references to undefined local or global variables as errors. With NOUNDEF, GT.M handles all references to undefined local or global variables as if the variable had a value of the null string. In other words, GT.M treats all variables appearing in expressions as if they were the argument of an implicit $GET(). UNDEF is the default. 3 TRACE "TRACE":value Traces GT.M program execution and generates profiling information about the lines and functions executed; with low impact on the run-time performance. The feature turns on (value=1) or turns off (value=0) tracing. must evaluate to a string containing the name of a GT.M global variable. The global may also have subscripts; however the subscripts must be literals or the special variable $JOB. The is optional when turning tracing off, if it exists, it overrides the global variable set when tracing was turned on. GT.M-tracing uses a technique called Basic Block Counting where calls are made to special profiling functions at key points in a GT.M program. A trace consists of the following run-time data as output for each GT.M function, as well as for each GT.M statement: o The number of times it is executed. o The total CPU time spent across all invocations for each function and each GT.M statement as three values: user time, system time, and total time. Instead of modifying the generated code as done by common profiling tools, such as gprof, GT.M tracing operates entirely within the GT.M run-time system; therefore, this feature does not require a special compilation, has no effect on code size and minimizes run-time overhead. When the feature is turned on, it gathers profiling information for each line and GT.M function invocation. The reported time for a GT.M line is the time spent in generated code for that line, and does not include time spent in entreyrefs called from that line. When profiling is turned off, the accumulated statistics are loaded into a GT.M global. GT.M profiling accumulates and provides the data; the user may choose tools and techniques to analyze the data. The trace information is stored in the variable in the following format: o If is a global variable without subscripts name such as "^foo", the trace information is stored in the nodes ^foo(,