From:	HENRY::IN%"leichter-jerry%YALE.ARPA%SRI-KL.ARPA%relay.cs.net@rca.com"  6-NOV-1986 14:57
To:	rpf@OVRO.Caltech.Edu (Ray Finch)
Subj:	Re: Parsing VMS filenames

         I am writing a user interface program for radio telescopes and
    am trying to locate a piece of code to parse VMS file names.  I
    would prefer C but we also have Fortran and Pascal compilers.  I'm
    trying to avoid having figuring out the call to SYS$PARSE and would
    rather not have to open the file at this point in the program.
Try the following (I didn't write it but I do use it).
							-- Jerry
---------------------------------Cut here-------------------------------------
/*)LIBRARY
*/

/*

fparse.c - fparse routine to emulate f$parse in DCL command files

Synposis:

	char *fparse( file_name, default_name, related_name, field)
	    char *file_name, default_name, related_name, field;

Description:

	All strings are null-terminated.  Only the first one or two characters
	are checked in field names. Parameters can be omitted by passing NULL.

	Fields are:

	    "node"		node name
	    "device"		device name
	    "directory"		directory name
	    "name"		file name
	    "type"		file type
	    "version"		file version number

	If the field parameter is null, all fields are expanded, except that
	the node name is included only if it appears in the file_name,
	default_name or related_name.  Note that field parameters
	must be given in lower-case.

	Within each field, the expanded name is taken from the file_name,
	default_name and related_name, in that order.

	The value returned is the address of the null-terminated file name;
	fparse calls malloc to reserve space for the string.

	The string "" is returned on either an RMS parse error, or
	an erroroneous field parameter name.  The RMS status error
	is not available.  Only one field may be given.

Example:


	To parse a command line LINK/EXE=exefile objfile, the default extension
	for "objfile" is .OBJ.  The default file name for "exefile" is the file
	name of "objfile", and the default extension is .EXE.

	Say that the char * variable "objfile" points to the object file
	name from the command line, and the char * "exefile" points to the
	exe file from the command line.  Then to expand these into file
	names for calls to open() or fopen():

		objfile = fparse( objfile, ".OBJ", NULL, NULL);
		exefile = fparse( exefile, ".EXE", objfile, NULL);

	To find only the directory of the object file:

		dir = fparse( objfile, ".OBJ", NULL, "directory");

	The field name could also be abbreviated:

		dir = fparse( objfile, ".OBJ", NULL, "di");

*/

#include <stdio.h>
#include <rms.h>
#include <ssdef.h>

char *fparse( file_name, default_name, related_name, field)
    char *file_name, *default_name, *related_name, *field;
{
    struct FAB ff_file_fab;
    struct NAM fn_file_nam, rn_related_nam, *nam;
    char *expanded_name, *eptr;
    int expanded_length, rms_status;
    char expand_buffer[ NAM$C_MAXRSS];

/* initialize all the blocks for RMS */

    ff_file_fab = cc$rms_fab;
    ff_file_fab.fab$l_nam = &fn_file_nam;
    ff_file_fab.fab$l_fna = file_name;
    ff_file_fab.fab$b_fns = (file_name == NULL) ? 0 : strlen( file_name);
    ff_file_fab.fab$l_dna = default_name;
    ff_file_fab.fab$b_dns = (default_name == NULL) ? 0 : strlen( default_name);

    fn_file_nam = cc$rms_nam;
    nam = &fn_file_nam;
    nam->nam$l_esa = expand_buffer;
    nam->nam$b_ess = NAM$C_MAXRSS;
    nam->nam$l_rlf = &rn_related_nam;

    rn_related_nam = cc$rms_nam;
    rn_related_nam.nam$l_rsa = related_name;
    rn_related_nam.nam$b_rsl =
      (related_name == NULL) ? 0 : strlen( related_name);

/* call SYS$PARSE to parse the file name */

    rms_status = sys$parse( &ff_file_fab);
    if (rms_status != RMS$_NORMAL)
	{  /* error in parse, so return empty string */
	expanded_name = malloc(1);
	expanded_name[0] = '\0';
	return( expanded_name);
	}

/* construct the expanded file name */

    if (field == NULL || field[0] == '\0')
	{  /* caller wants all fields */
	expanded_length = nam->nam$b_esl;
	eptr = expand_buffer;
	}
    else
	{  /* caller wants just one field */
	switch (field[0])
	    {
	    case 'n':		/* node or name */
		if (field[1] == 'o')
		    {		/* node */
		    expanded_length = nam->nam$b_node;
		    eptr = nam->nam$l_node;
		    }
		else
		    {		/* name */
		    expanded_length = nam->nam$b_name;
		    eptr = nam->nam$l_name;
		    }
		break;
	    case 'd':		/* device or directory */
		if (field[1] == 'e')
		    {		/* device */
		    expanded_length = nam->nam$b_dev;
		    eptr = nam->nam$l_dev;
		    }
		else
		    {		/* directory */
		    expanded_length = nam->nam$b_dir;
		    eptr = nam->nam$l_dir;
		    }
		break;
	    case 't':		/* type */
		expanded_length = nam->nam$b_type;
		eptr = nam->nam$l_type;
		break;
	    case 'v':		/* version */
		expanded_length = nam->nam$b_ver;
		eptr = nam->nam$l_ver;
		break;
	    default:
		expanded_length = 0;
		break;
	    }
	}
    expanded_name = malloc( expanded_length + 1);
    strncpy( expanded_name, eptr, expanded_length);
    expanded_name[ expanded_length] = '\0';
    return( expanded_name);
}
-------
