Routines Example

This section provides an example routine written in the C programming language that comprehensively illustrates the DAL calls and their types of arguments. The example indicates how a calling routine specifies a GT.M database function using the syntax of the source language. For every C statement that does a DAL call, the corresponding M command is indicated as a C comment in the same line.

The routine passes arguments by descriptors. To pass arguments by descriptor from a C program, the routine must have a structure declaration that models the descriptor and assigns appropriate values to structure members. The routines must include the header file <descrip.h>, which defines the descriptor structures for all forms of descriptors.

[Note]

The example routine presented below does not check the return status of each DAL call for illustrative purposes. However, in production C code, every DAL calla??s return status must be checked immediately after the call.

The C code below also uses a VAX-C construct "globalvalue", which is similar to the ANSI-C "extern" construct. The routine assumes the existence of two global directories MUMPS.GLD and OTHER.GLD with their corresponding databases and that at the start of execution the logical corresponding to the current global directory "gtm$gbldir" points to MUMPS.GLD.

[Note]

As the keywords used in the following C program, GTMI$_GLOBAL, GTMI$_LOCAL, and so on, are defined in the module GTMI$_DEF in GTM$DIST:GTMLIB.OLB, the LINK command must include the GTM$DIST:GTMLIB.OLB object library in order to be able to successfully link and run DAL.C.

Example:

	#include <stdio.h>
	#include <descrip.h>
	
	globalvalue GTMI$_GLOBAL, GTMI$_LOCAL, GTMI$_NAKED, GTMI$_EXTGBL, GTMI$_EXTLCL;
	int			dal()
	{
	long mg = GTMI$_GLOBAL, ml = GTMI$_LOCAL, mn = GTMI$_NAKED;
	long meg = GTMI$_EXTGBL, mel = GTMI$_EXTLCL;
	long sts;
	$DESCRIPTOR (dmumps, "MUMPS");
	$DESCRIPTOR (dother, "OTHER");
	$DESCRIPTOR (dsub1, "1");
	$DESCRIPTOR (dsub2, "2");
	$DESCRIPTOR (dsuba, "a");
	$DESCRIPTOR (dsubb, "b");
	$DESCRIPTOR (ddata, "data");
	$DESCRIPTOR (dextgbl, "OTHER.GLD");
	$DESCRIPTOR (dxecstr, "set ^OTHER(1)=1");
	struct dsc$descriptor_s ddest = {0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0};
	sts = gtm$init(); 
	/* ;Call GTM$INIT before any DAL call */
	sts = gtm$interrupt(3);
	/* ;Ctrl-C is interrupt character*/
	sts = gtm$ztstart();
	/* ztstart */
	sts = gtm$put(mg, &ddata, &dmumps, &dsub1);
	/* set ^MUMPS(1)="data"*/
	sts = gtm$ztcommit(0);
	/* ztcommit 0*/
	sts = gtm$put(mg, &ddata, &dmumps, &dsub2, &dsuba); 
	/* set ^MUMPS(2,"a")="data"*/
	sts = gtm$put(mn, &ddata, &dsubb);
	/* set ^("b")="data"*/
	sts = gtm$put(meg, &ddata, &dextgbl, &dother, &dsub1); 
	/* set ^|"OTHER.GLD"|OTHER(1)="data"*/
	sts = gtm$data(mg, &ddest, &dmumps, &dsub2);
	/* set retval=$DATA(^MUMPS(2)) */
	sts = gtm$get(mg, &ddest, &dmumps, &dsub2, &dsubb);
	/* set retval=$GET(^MUMPS(2,"b")) */
	sts = gtm$order(mg, &ddest, -1, &dmumps, &dsub2); 
	/* set retval=$ORDER(^MUMPS(2),-1) */
	sts = gtm$previous(mg, &ddest, &dmumps, &dsub2); 
	/* set retval=$ZPREVIOUS(^MUMPS(2)) */
	sts = gtm$query(mg, &ddest, &dmumps, &dsub1); 
	/* set retval=$QUERY(^MUMPS(1)) */
	sts = gtm$withdraw(mg, &dmumps, &dsub2);
	/* zwithdraw ^MUMPS(2) */
	sts = gtm$setgbldir(&dextgbl); 
	/* set $zgbldir="OTHER.GLD" */
	sts = gtm$kill(mg, &dother);
	/* kill ^OTHER */
	sts = gtm$xecute(&dxecstr); 
	/* xecute "set ^OTHER(1)=""data""" */
	sts = gtm$put(ml, &ddata, &dmumps, &dsub1); 
	/* set MUMPS(1)="data" */
	sts = gtm$put(ml, &ddata, &dmumps, &dsub2, &dsuba);
	/* set MUMPS(2,"a")="data" */
	sts = gtm$data(ml, &ddest, &dmumps, &dsub2);
	/* set retval=$DATA(MUMPS(2)) */
	sts = gtm$inclock(0, mel, &dextgbl, &dother);
	/* lock +|"OTHER.GLD"|other:0 */
	sts = gtm$lock(-1, mg, &dmumps, 0, ml, &dother); 
	/* lock (^MUMPS,OTHER) */
	sts = gtm$declock(mg, &dmumps);
	/* lock -^MUMPS */
	sts = gtm$lock(); 
	/* lock */
	sts = gtm$zalloc(-1, ml, &dmumps); 
	/* zalloc MUMPS */
	sts = gtm$zdealloc(ml, &dmumps);
	/* zdealloc MUMPS */
	sts = gtm$rundown();
	/* ;Runs down all open GT.M databases */
	sts = gtm$zstatus(&ddest);
	/* ;return value of $ZSTATUS in ddest */
	return sts;
	}	
	

The routines pass arguments by descriptor. To pass arguments by descriptor from a C program, the routine must have a structure declaration that models the descriptor and assigns appropriate values to structure members. The routines must use the "include file" gtm_descript.h, which defines descriptor structures for all forms of descriptors.

The routines invoke the gtm_init() function to initialize the GT.M run-time library.

Example:

	#include "mdef.h"#include "gtmidef.h"#include "gtm_descript.h"main (){ long status,i ; short mode ;gtm_descriptor k0[10], k1[10] ; /* k0 and k1 will hold the arguments to the DAL calls. The size of the array is not significant, except that each array must have enough elements to hold all of its values. */
	status = gtm_init() ;printf("Init status : %d ",status);
	DESC_CHAR (k0[0],"Comic strip character") ;  /* The value for the node */DESC_CHAR (k1[0],"Disney character") ; /* The value for the node */
	mode = (short)GTMI_GLOBAL ;DESC_MODE (k0[1],mode);DESC_MODE (k1[1],mode);
	DESC_CHAR (k1[2],"MOUSE") ;/* The name of the global */DESC_CHAR (k0[2],"CAT") ; /* The name of the global */
	DESC_CHAR (k0[3],"Garfield") ; /* The first subscript */DESC_CHAR (k1[3],"Mickey") ; /* The first subscript */
	DESC_ZERO (k0[4]); /* Create null descriptor */DESC_ZERO (k1[4]); /* to signify no more keys*/
	status = gtm_put (k1);printf("Put ^MOUSE(Mickey)=Disney character : %d ",status);
	status = gtm_put (k0);printf("Put ^CAT(Garfield)=Comic strip character : %d ",status);
	DESC_CHAR (k0[0],"Tom & Jerry Cartoon") ; /* The value for the node */mode = (short)GTMI_NAKED ; /* The mode is GTMI_NAKED */
	DESC_MODE (k0[1],mode);
	DESC_CHAR (k0[2],"Tom") ; /* The first subscript */DESC_ZERO (k0[3]); /* Create null descriptor */ /* to signify no more keys*/
	status = gtm_put (k0);printf("Put ^(Tom)=Tom & Jerry Cartoon : %d ",status);
	mode = (short)GTMI_GLOBAL;/* The mode is GTMI_GLOBAL*/DESC_MODE (k0[1],mode);DESC_CHAR (k0[2],"COUNT");DESC_ZERO (k0[4]);
	for (i=0; i<10; i++){ DESC_LONG (k0[0],i); DESC_LONG (k0[3],i); status = gtm_put (k0); printf("Put ^COUNT(%d)=%d : %d ",i,i,status);}
	memset(k1, 0, sizeof(k1));k1[0].type = GTM_ARRAY_OF_CHARS;mode = GTMI_GLOBAL;DESC_MODE (k0[0],mode);DESC_CHAR (k0[1],"COUNT");DESC_ZERO (k0[2]);
	status = gtm_data (k0, k1);printf("$DATA(^COUNT) = %.*s : %d ",k1[0].len,k1[0].val,status);
	status = gtm_halt();printf("Halt status : %d ",status);return 1;}
	

This C routine sets three globals ^MOUSE("Mickey"), ^CAT("Tom"), ^CAT("Garfield"). The routine then sets up a loop that builds ^COUNT(1) through ^COUNT(10). Finally, a $DATA is performed on ^COUNT. The following M routine corresponds to the previous C program:

	data; S ^MOUSE("Mickey")="Disney character"S ^CAT("Garfield")="Comic strip character"S ^("Tom")="Tom & Jerry Cartoon"F i=0:1:9 S ^COUNT(i)=iW !,"Put CAT(0) through CAT(9)",!W $data(^COUNT)Q
	

Example:

	#include "mdef.h"#include "gtmidef.h"#include "gtm_descript.h"#define DESC_MODE(x,y) {x.type=GTM_MODE; x.len=sizeof(y); x.val=(void*)&y;}#define DESC_CHAR(x,y) {x.type=GTM_ARRAY_OF_CHARS; x.len=sizeof(y)-1; x.val=y;}#define DESC_ZERO(x) {x.type=0; x.len=0;}#define DESC_LONG(x,y) {x.type=GTM_LONG; x.len=sizeof(y); x.val=&y;}#define DESC_DELIM(x,y) {x.type=GTM_DELIMITER;x.len=sizeof(y);x.val=(void *)&y;}main (){longstatus,timeout ;shortmode,delim ;gtm_descriptork0[15], k1[10] ; /* k0 and k1 will hold the arguments to the DAL calls. The size of the array is not significant. */ status = gtm_init() ;printf("Init status : %d ",status);memset(k0, 0, sizeof(k0));status = gtm_lock (k0); /* L */timeout = 0 ;DESC_LONG (k0[0],timeout) ; /* Time out of zero */mode = (short)GTMI_GLOBAL ; /* The mode is GTMI_GLOBAL */DESC_MODE (k0[1],mode);DESC_CHAR (k0[2],"A") ; /* The name of the global */DESC_ZERO (k0[3]) ;status = gtm_lock (k0); /* L ^A:0 */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);timeout = 1;DESC_LONG (k0[0],timeout) ;mode = (short)GTMI_GLOBAL;DESC_MODE (k0[1],mode);DESC_CHAR (k0[2],"B") ;DESC_ZERO (k0[3]) ;status = gtm_inclock (k0); /* L +^B:1 */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);timeout=-1;DESC_LONG (k0[0],timeout) ; /* No timeout */mode = (short)GTMI_GLOBAL;DESC_MODE (k0[1],mode) ;DESC_CHAR (k0[2],"D");DESC_CHAR (k0[3],"a");DESC_CHAR (k0[4],"b");DESC_CHAR (k0[5],"c");DESC_CHAR (k0[6],"d");DESC_ZERO (k0[7]);status = gtm_inclock (k0);/* L +^D("a","b","c","d") */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);timeout = -1;DESC_LONG (k0[0],timeout) ;mode = (short)GTMI_GLOBAL;DESC_MODE (k0[1],mode);DESC_CHAR (k0[2],"C");DESC_ZERO (k0[3]);status = gtm_inclock (k0) ; /* L +^C */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);mode = (short)GTMI_GLOBAL;DESC_MODE (k0[0],mode);DESC_CHAR (k0[1],"C");DESC_ZERO (k0[2]);status = gtm_declock (k0); /* L -^C */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);DESC_CHAR (k0[1],"D");status = gtm_declock (k0); /* L -^D */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);timeout = -1;DESC_LONG (k0[0],timeout);mode = (short)GTMI_EXTGBL;DESC_MODE (k0[1],mode);DESC_CHAR (k0[2],"./M.gld"); DESC_CHAR (k0[3],"a");DESC_ZERO (k0[4]);status = gtm_zalloc (k0); /* za ^|"./M.gld"|a */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);DESC_ZERO (k0[0]);status = gtm_lock (k0); /* L */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);timeout = -1;DESC_LONG (k0[0],timeout);mode = (short)GTMI_GLOBAL;DESC_MODE (k0[1],mode);DESC_CHAR (k0[2],"A");delim = 0; /* Separator for arguments*/DESC_DELIM (k0[3],delim); /* Create null descriptor*/mode = (short)GTMI_LOCAL;DESC_MODE (k0[4],mode);DESC_CHAR (k0[5],"B");DESC_DELIM (k0[6],delim);mode = (short)GTMI_LOCAL;DESC_MODE (k0[7],mode);DESC_CHAR (k0[8],"C");DESC_ZERO (k0[9]);status = gtm_lock(k0); /* L (^A,B,C) */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);timeout = -1;DESC_LONG (k0[0],timeout);mode = GTMI_LOCAL;DESC_MODE (k0[1],mode);DESC_CHAR (k0[2],"A");DESC_CHAR (k0[3],"a");DESC_CHAR (k0[4],"b");DESC_CHAR (k0[5],"c");DESC_CHAR (k0[6],"d");DESC_DELIM (k0[7],delim);DESC_MODE (k0[8],mode);DESC_CHAR (k0[9],"D");DESC_ZERO (k0[10]);status = gtm_inclock(k0); /* L +(A("a","b","c","d"),D) */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);mode = GTMI_EXTGBL;DESC_MODE (k0[0],mode);DESC_CHAR (k0[1],"./mumps.gld");DESC_CHAR (k0[2],"a");DESC_ZERO (k0[3]);status = gtm_zdealloc (k0); /* zd ^|"./M.gld"|a */DESC_CHAR (k0[0],"zshow L w **********,!");status = gtm_xecute(k0);status = gtm_halt();printf("Halt status : %d ",status);return 1;}
	

Example:

	#include "mdef.h"#include "gtmidef.h"#include "gtm_descript.h"#define DESC_MODE(x,y) {x.type=GTM_MODE; x.len=sizeof(y); x.val=(void*)&y;}#define DESC_CHAR(x,y) {x.type=GTM_ARRAY_OF_CHARS; x.len=sizeof(y)-1; x.val=y;}#define DESC_ZERO(x) {x.type=0; x.len=0;}#define DESC_LONG(x,y) {x.type=GTM_LONG; x.len=sizeof(y); x.val=&y;}main (){longstatus,i ;shortmode ;gtm_descriptork0[10], dummy[10] ; /* k0 and dummy will hold the arguments to the DAL calls. The size is not significant.*/ status = gtm_init() ;printf("Init status : %d ",status);status = gtm_ztstart ();mode = (short)GTMI_GLOBAL;DESC_MODE (k0[0],mode);DESC_CHAR (k0[1],"CAT");status = gtm_kill (k0);status = gtm_ztstart ();DESC_CHAR (k0[0],"data");mode = (short)GTMI_GLOBAL;DESC_MODE (k0[1],mode);DESC_CHAR (k0[2],"CAT");DESC_CHAR (k0[3],"1");DESC_ZERO (k0[4]);status = gtm_put (k0);status = gtm_ztstart ();memset(dummy, 0, sizeof(dummy));dummy[0].type = GTM_ARRAY_OF_CHARS;mode = (short)GTMI_GLOBAL;DESC_MODE (k0[0],mode);DESC_CHAR (k0[1],"CAT");DESC_ZERO (k0[2]);status = gtm_data (k0, dummy);DESC_CHAR (k0[0],"2");DESC_ZERO (k0[1]);status = gtm_ztcommit (k0);DESC_MODE (k0[0],mode);DESC_CHAR (k0[1],"CAT");DESC_CHAR (k0[2],"1");DESC_ZERO (k0[3]);status = gtm_data (k0, dummy);DESC_CHAR (k0[0],"0");DESC_ZERO (k0[1]);status = gtm_ztcommit (k0);status = gtm_halt();printf("Halt status : %d ",status);return 1;}