From:	CSBVAX::CSBVAX::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 26-JAN-1989 07:55
To:	MRGATE::"ARISIA::EVERHART"
Subj:	making a program work as both a command and foreign symbol


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Wed, 25 JAN 89 10:39:28 PDT
Received: from uwavm.acs.washington.edu (oly.acs.washington.edu) by KL.SRI.COM with TCP; Wed, 25 Jan 89 10:19:20 PST
Received: from UWAVM.ACS.WASHINGTON.EDU by uwavm.acs.washington.edu ; Wed, 25 Jan 89 10:18:21 PST
Received: from FHCRCVAX.BITNET (JOE) by UWAVM.ACS.WASHINGTON.EDU (Mailer R2.02)
 with BSMTP id 0131; Wed, 25 Jan 89 10:18:18 PST
Date: Wed, 25 Jan 89 10:17 PST
From: Joe Meadows <JOE%FHCRCVAX.BITNET@uwavm.acs.washington.edu>
Subject: making a program work as both a command and foreign symbol
To: info-vax@kl.sri.COM
X-VMS-To: IN%"info-vax@kl.sri.com"

Quite some time ago I queried the net about their preferences w.r.t. commands
vs. foreign commands. At the time, it seemed there were good arguments for
either. I planned on writing an example chunk of code to allow both forms
in one program, but I back-burner'd it for so long I completely forgot.

Since I was recently reminded, I decided to see what I could come up with.
First off, there are a few drawbacks to this method, you need to maintain
two versions of a .CLD file, one with the IMAGE statement removed. Secondly,
since you need to link in the object file (created by SET COMMAND/OBJECT)
your program will be slightly larger.

However, the technique is quite simple. First you need to determine if
you are running as a command or as a foreign symbol. The way I originally
did that, was to call CLI$GET_VALUE with the "$VERB" parameter. This returns
the last parsed real command.I just realized a (perhaps) easier way, you can
use the $LINE argument to get the whole command line, and if it starts with
a "$" then you know it's a foreign symbol.

If you have determined that it is defined as a command, you can continue
as normal. If not, you need to build up a valid command string and call
the CLI$DCL_PARSE routine to initialize the parsing context. If you've
used the $LINE parameter you could simply cut off the first part of it
(the "$imagename" part), and add the verb name to the beginning. Otherwise
you could use LIB$GET_FOREIGN to get the rest of the line and add the verb
name to the beginning of that.

Here is a chunk of example code to do all this:
/* Thanks to Michael Kimura for reminding me about
   this and sending me a related chunk of code */

/* Start of (minimal) example */
#include descrip        /* needed by init_cli */
globalvalue UAF_Table;  /* note, this name is determined by the module
                           name given in the CLD file, if none is present
                           it apparently defaults to the file name */
main()
{
  int sts;

  sts = init_cli(UAF_Table,"UAF");
  /* continue with normal parsing here... */
  /* the code from here on works like the thing was invoked as a command */
  /* whether it was or wasn't */
}

init_cli(char *table, char *name)
/* "table" is a pointer to the internal CLD (not really "char *")
 * "name" is a text string containing the name of the verb
 */
{
  struct dsc$descriptor
    prefix = {name?strlen(name):0,DSC$K_DTYPE_T,DSC$K_CLASS_S,name};
  static struct dsc$descriptor cmd = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0};
  static $DESCRIPTOR(line,"$LINE");
  static $DESCRIPTOR(verb,"$VERB");
  static $DESCRIPTOR(space," ");
  int sts;

  sts = CLI$GET_VALUE(&verb,&cmd);
  if (!(sts & 1)) return(sts);

  if (strncmp(cmd.dsc$a_pointer,name,cmd.dsc$w_length) == 0)
  {
    return(1);    /* the command must have been properly defined! */
  }
  else
  {
    sts = LIB$GET_FOREIGN(&cmd);     /* Get the command line */
    if (!(sts & 1)) return(sts);
    sts = STR$PREFIX(&cmd, &space);  /* put a space in front of it */
    if (!(sts & 1)) return(sts);
    sts = STR$PREFIX(&cmd, &prefix); /* put the verb name in front of that */
    if (!(sts & 1)) return(sts);

    return(CLI$DCL_PARSE(&cmd,table)); /* initialize the parse tables */
  }
}

/* End of (minimal) example */


  Cheers,
  Joe Meadows Jr.
  VAX/VMS System Manager / guru in training
  Fred Hutchinson Cancer Research Center
  1124 Columbia St.
  Seattle Wa. 98104
     bitnet - JOE@FHCRCVAX
     arpa   - JOE%FHCRCVAX.BITNET@OLY.ACS.WASHINGTON.EDU
     voice  - (206) 467-4970

