fnm_util - Filename Utilitiesf$parse(). File specifications have
the following structure:
node:/directory(s)/name.extension.version
Any field is optional. node is a host name; directory is one
or more names separated by "/"s; name follows the last "/" in the
pathname. version is a 3-digit number (e.g., 002) and
extension follows the last dot before the version dot.
A filename is created as follows:
#include "fnm_util.h" -- Filename utilities.
FileName fname ;
...
fname = fnmCreate ("fileSpec", NULL) ;
fnmCreate() expands the file specification, translating
environment variable references and filling in defaults for missing fields.
fnmCreate() can be passed multiple file specifications, which
are then processed from left to right in the calling sequence:
fname = fnmCreate ("spec1", ..., "specN", NULL) ;
First, the leftmost file specification is examined and any references to
environment variables are translated. The next file specification is then
examined. Environment variables are translated and fields missing in the
first file specification are supplied from the new file specification.
Subsequent file specifications are examined, in turn, and "applied" to the
results of the processing of the previous file specifications. Finally,
system defaults (e.g., the user's home directory) are supplied for missing
fields that remain.
Is that clear? I used to have a diagram that showed the file names stacked up, one on top of another:
... System Defaults ...
File_Spec_#N |
... |
File_Spec_#2 |
File_Spec_#1 V
--------------
Result
File name components would drop down through holes in lower-level
specifications to fill in missing fields in the result.
Specifying multiple file specifications is useful for replacing extensions, concatenating directories, etc.:
#include "fnm_util.h" -- Filename utilities.
FileName fname ;
... -- "/usr/me" (current directory)
fname = fnmCreate (NULL) ;
-- "/usr/me/prog.lis"
fname = fnmCreate (".lis", "prog.c", NULL) ;
-- "/usr/you/tools/dump.o"
fname = fnmCreate (".o", "tools/dump.c", "/usr/you/", NULL) ;
What can you do with a file name once it is created? You call
fnmParse() to get the whole file name or parts of the file
name as a string:
#include "fnm_util.h" -- Filename utilities.
char *s ;
FileName fname ;
...
fname = fnmCreate ("host:/usr/who/myprog.c.001", NULL) ;
s = fnmParse (fname, FnmPath) ; -- "host:/usr/who/myprog.c.001"
s = fnmParse (fname, FnmNode) ; -- "host:"
s = fnmParse (fname, FnmDirectory) ; -- "/usr/who"
s = fnmParse (fname, FnmFile) ; -- "myprog.c.001"
s = fnmParse (fname, FnmName) ; -- "myprog"
s = fnmParse (fname, FnmExtension) ; -- ".c"
s = fnmParse (fname, FnmVersion) ; -- ".001"
fnmDestroy (fname) ;
Shorthand macros - fnmPath(), fnmNode(), etc. -
are defined for each of the fnmParse() calls above.
f$parse().
fnmCreate() - creates a filename.
fnmDestroy() - destroys a filename.
fnmExists() - checks if a file exists.
fnmParse() - parses a filename.
fnmPath() - returns a filename's full pathname.
fnmNode() - returns the node from a filename.
fnmDirectory() - returns the directory from a filename.
fnmFile() - returns the file, extension, and version from a filename.
fnmName() - returns the file from a filename.
fnmExtension() - returns the extension from a filename.
fnmVersion() - returns the version number from a filename.
fnm_util.c
fnm_util.h
(See libgpl for the
complete source, including support routines and build files.)