Invoking GT.M through a C main() program

There are several circumstances when it is desirable to invoke a GT.M application with a top-level C main() program rather than with mumps -run. Examples include:

To compile and run the monthstarting.zip example, perform the following steps:

  1. Download monthstarting.zip.

    monthstarting.zip contains monthstarting.m, month_starting.c, and monthstarting.ci. To download monthstarting.zip, click on Download monthstarting.zip .You can also download monthstarting.zip from http://tinco.pair.com/bhaskar/gtm/doc/books/ao/UNIX_manual/downloadables/monthstarting.zip.

  2. Run the monthstarting.m program that lists months starting with the specified day of the week and year range.

    $ mumps -run monthstarting Friday 1986 1988      
    FRI AUG 01, 1986
    FRI MAY 01, 1987
    FRI JAN 01, 1988
    FRI APR 01, 1988
    FRI JUL 01, 1988
    $

    Notice that this program consists of a main program that reads the command line in the intrinsic special variable $ZCMDLINE, and calls calcprint^monthstarting(), providing as its first parameter the day of the week to be reported.

    This step is optional as there is no need to explicitly compile monthstarting.m because GT.M autocompiles it as needed.

  3. On x86 GNU/Linux (64-bit Ubuntu 12.04), execute the following command to compile month_starting.c and create an executable called friday.

    $ gcc -c month_starting.c -I$gtm_dist
    $ gcc month_starting.o -o friday -L $gtm_dist -Wl,-rpath=$gtm_dist -lgtmshr

    For compiling the month_starting.c program on other platforms, refer to the Integrating External Routines chapter of GT.M Programmer's Guide

  4. Execute the following command:

    $ ./friday 1986 1988
    FRI AUG 01, 1986
    FRI MAY 01, 1987
    FRI JAN 01, 1988
    FRI APR 01, 1988
    FRI JUL 01, 1988
    $
  5. You can also execute the same program with the name monday. In doing so, the program displays months starting with Monday.

    $ ln -s friday monday
    $ ./monday 1986 1988
    MON SEP 01, 1986
    MON DEC 01, 1986
    MON JUN 01, 1987
    MON FEB 01, 1988
    MON AUG 01, 1988
    $

    The month_starting.c program accomplishes this by calling the same GT.M entryref calcprint^monthstarting(), and passing in as the first parameter the C string argv[0], which is the name by which the program is executed. If there are additional parameters, month_starting.c passes them to the M function; otherwise it passes pointers to null strings:

    /* Initialize and call calcprint^monthstarting() */
    if ( 0 == gtm_init() ) gtm_ci("calcprint", &status, argv[0], argc>1 ? argv[1] : "", argc>2 ? argv[2] : "");

    Prior to calling the GT.M entryref, the C program also needs to set environment variables if they are not set: gtm_dist to point to the directory where GT.M is installed, gtmroutines to enable GT.M to find the monthstarting M routine as well as GT.M's %DATE utility program, and GTMCI to point to the call-in table:

    /* Define environment variables if not already defined */
            setenv( "gtm_dist", "/usr/lib/fis-gtm/V6.1-000_x86_64", 0 );
            if (NULL == getenv( "gtmroutines" ))
            {
                    tmp1 = strlen( getenv( "PWD" ));
                    strncpy( strbuf, getenv( "PWD"), tmp1 );
                    strcpy( strbuf+tmp1, " " );
                    tmp2 = tmp1+1;
                    tmp1 = strlen( getenv( "gtm_dist" ));
                    strncpy( strbuf+tmp2, getenv( "gtm_dist" ), tmp1 );
                    tmp2 += tmp1;
                    if ( 8 == sizeof( char * ))
                    {
                            tmp1 = strlen( "/libgtmutil.so" );
                            strncpy( strbuf+tmp2, "/libgtmutil.so", tmp1 );
                            tmp2 += tmp1;
                    }
                    strcpy( strbuf+tmp2, "" );
                    setenv( "gtmroutines", strbuf, 1 );
            }
            setenv( "GTMCI", "monthstarting.ci", 0 );
            if ( 0 == gtm_init() ) gtm_ci("calcprint", &status, argv[0], argc>1 ? argv[1] : "", argc>2 ? argv[2] : "");
            gtm_exit(); /* Discard status from gtm_exit and return status from function call */

    Note that on 32-bit platforms, the last element of gtmroutines is $gtm_dist, whereas on 64-bit platforms, it is $gtm_dist/libgtmutil.so. If you are creating a wrapper to ensure that environment variables are set correctly because their values cannot be trusted, you should also review and set the environment variables discussed in “Setting up a Captive User Application with GT.M”.

    All the C program needs to do is to set environment variables and call a GT.M entryref. A call-in table is a text file that maps C names and parameters to M names and parameters. In this case, the call-in table is just a single line to map the C function calcprint() to the GT.M entryref calcprint^monthstarting():

    calcprint : gtm_int_t* calcprint^monthstarting(I:gtm_char_t*, I:gtm_char_t*, I:gtm_char_t*)