📄 sflfile.c
字号:
{
if (pathptr != path_name)
{
strcpy (path_name, pathptr);
pathptr = path_name;
}
strconvch (path_name, '/', '\\');
}
#endif
/* Take care of 'w' and 's' options first */
if (mode == 'w') /* Create output file locally */
return (work_name);
if (mode == 's') /* Get specific directory name */
{
if (fully_specified (work_name))
strncpy (full_name, work_name, sizeof (full_name));
else
if (pathptr && file_is_directory (pathptr))
build_next_path (full_name, pathptr, work_name);
else
#if (defined (MSDOS_FILESYSTEM))
build_next_path (full_name, ".\\", work_name);
#else
build_next_path (full_name, "./", work_name);
#endif
return (full_name);
}
/* If file exists as defined, prefix with current directory if not an */
/* absolute filename, then return the resulting filename */
if (search_curdir && file_exists (work_name))
{
if (fully_specified (work_name))
strncpy (full_name, work_name, sizeof (full_name));
else
{
curdir = get_curdir ();
snprintf (full_name, sizeof (full_name), "%s%s", curdir, work_name);
mem_free (curdir);
}
#if (defined (MSDOS_FILESYSTEM))
strconvch (full_name, '/', '\\');
#endif
return (full_name); /* Then return path + name + ext */
}
if (!pathptr) /* Now we need a path */
return (NULL); /* - if none defined, give up */
for (;;) /* Try each path component */
{
pathptr = build_next_path (full_name, pathptr, work_name);
if (file_exists (full_name))
return (full_name); /* Until we find one, */
if (*pathptr == '\0') /* or we come to the end of */
{ /* the path */
if (mode == 'r')
return (NULL); /* Input file was not found... */
else
return (full_name);
}
}
}
/* ---------------------------------------------------------------------[<]-
Function: file_where_ext
Synopsis: Scans a user-specified path symbol for a specific file, and
returns the fully-specified filename. Can also scan a series of file
extensions while looking for the file in the path. The extensions are
scanned in each directory in the path prior to moving on to the next
directory.
The mode argument can be one of: r, w, a, or s for read, write, append,
or static. The function tries to locate existing files somewhere on the
path. New files are always created in the current directory. Static
files are created in the first directory on the path.
The path argument is only used when mode is r, a, or s. If the path is
NULL or empty, it is ignored. Otherwise, the path is translated as an
environment variable. If the path cannot be translated, it is used as
a literal value. The path is then cut into a list of directory names,
as follows:
<TABLE>
MS-DOS directory names separated by ';'. ;; means current.
OS/2 directory names separated by ';'. ;; means current.
Unix directory names separated by ':'. :: means current.
VMS directory names separated by ','. " ", means current.
Other single directory name.
</TABLE>
When the mode is 'r' or 'a', it searches the current directory before
considering the path value.
The name argument is the filename with or without extension. It will
be prefixed by the path and suffixed by the extension, if required.
The ext argument is an array of default or mandatory extensions.
If the extension starts with a dot, it is mandatory and will override
any existing extension. Otherwise it is used only if the name does
not already have an extension. The filename will be tried as supplied
if ext is NULL, or if it has an extension, and one or more of the
entries is a default extension. The first extension, if any, is
always used in 'w' mode and 's' mode. The last path component and
extension will be used in 'a' mode, if either is supplied.
The total length of a name including path, name, extension, and any
delimiters is FILE_NAME_MAX. Names are truncated if too long. The
maximum size of one directory component is FILE_DIR_MAX chars.
All parameters are case-sensitive; the precise effect of this depends on
the system. On MS-DOS, filenames are always folded to uppercase, but the
path must be supplied in uppercase correctly. On UNIX, all parameters are
case sensitive. On VMS, path and filenames are folded into uppercase.
Returns a pointer to a static character array containing the filename; if
mode is 'r' and the file does not exist, returns NULL. If the mode is
'w', 'a', or 's', always returns a valid filename.
Under VMS, all filenames are handled in POSIX mode, i.e. /disk/path/file
instead of $disk:[path]file.
---------------------------------------------------------------------[>]-*/
char *
file_where_ext (
char mode,
const char *path,
const char *name,
const char **ext)
{
const char
*pathptr; /* End of directory in path */
const char
**extptr; /* Pointer to next extension */
char
*curdir;
Bool
search_curdir = TRUE; /* Look in current directory? */
ASSERT (name);
if (!name)
return NULL;
if (path != NULL && *path) /* Get value of path, or NULL */
{
pathptr = getenv (path); /* Translate path symbol */
if (pathptr == NULL)
{
pathptr = path; /* If not found, use literally */
search_curdir = FALSE; /* Path now takes priority */
}
#if (PATHFOLD == TRUE) /* Fold to uppercase if necessary */
if (pathptr)
{
ASSERT (strlen (pathptr) < PATH_MAX);
strcpy (path_name, pathptr);
strupc (path_name);
pathptr = path_name; /* Redirect to uppercase version */
}
#endif
}
else
pathptr = NULL;
#if (defined (MSDOS_FILESYSTEM))
/* Normalise the path value by changing any slashes to backslashes */
if (pathptr)
{
if (pathptr != path_name)
{
strcpy (path_name, pathptr);
pathptr = path_name;
}
strconvch (path_name, '/', '\\');
}
#endif
/* Take care of 'w' and 's' options first */
if (mode == 'w') /* Create output file locally */
{
if (ext != NULL && ext [0] != NULL)
add_extension (work_name, name, ext [0]);
else
strcpy (work_name, name);
#if (NAMEFOLD == TRUE)
strupc (work_name); /* Fold to uppercase if needed */
#endif
return (work_name);
}
if (mode == 's') /* Get specific directory name */
{
if (ext != NULL && ext [0] != NULL)
add_extension (work_name, name, ext [0]);
else
strcpy (work_name, name);
#if (NAMEFOLD == TRUE)
strupc (work_name); /* Fold to uppercase if needed */
#endif
if (fully_specified (work_name))
strcpy (full_name, work_name);
else
if (pathptr && file_is_directory (pathptr))
build_next_path (full_name, pathptr, work_name);
else
#if (defined (MSDOS_FILESYSTEM))
build_next_path (full_name, ".\\", work_name);
#else
build_next_path (full_name, "./", work_name);
#endif
return (full_name);
}
/* If file exists as defined (with one of the extensions), prefix with */
/* current directory if not an absolute filename, then return the */
/* resulting filename */
if (search_curdir)
{
extptr = ext;
do
{
if (extptr != NULL && *extptr != NULL)
add_extension (work_name, name, *extptr);
else
strcpy (work_name, name);
#if (NAMEFOLD == TRUE)
strupc (work_name); /* Fold to uppercase if needed */
#endif
if (file_exists (work_name))
{
if (fully_specified (work_name))
strcpy (full_name, work_name);
else
{
curdir = get_curdir ();
snprintf (full_name, sizeof (full_name),
"%s%s", curdir, work_name);
mem_free (curdir);
}
#if (defined (MSDOS_FILESYSTEM))
strconvch (full_name, '/', '\\');
#endif
return (full_name); /* Then return path + name + ext */
}
if (extptr)
extptr++;
}
while (extptr != NULL && *extptr != NULL);
}
if (!pathptr) /* We need a path to look further */
return (NULL); /* - if none defined, give up */
for (;;) /* Try each path component */
{ /* - and extension within that */
const char *savedptr = pathptr;
extptr = ext;
do
{
const char *extension = NULL;
if (extptr != NULL && *extptr != NULL)
extension = *extptr;
pathptr = build_next_path_ext (full_name, savedptr,
name, extension);
if (file_exists (full_name))
return (full_name); /* Until we find one that matches */
if (extptr)
extptr++;
}
while (extptr != NULL && *extptr != NULL);
if (*pathptr == '\0') /* or we come to the end of */
{ /* the path */
if (mode == 'r')
return (NULL); /* Input file was not found... */
else
return (full_name);
}
}
}
/* -------------------------------------------------------------------------
* fully_specified -- internal
*
*/
static Bool
fully_specified (const char *filename)
{
#if (defined (MSDOS_FILESYSTEM)) \
/* Under MSDOS we have a full path if we have any of:
* /directory/directory/filename
* D:/directory/directory/filename
* the variations of those with backslashes.
*/
if (filename [0] == '\\' || filename [0] == '/' ||
(isalpha (filename [0]) && filename [1] == ':' &&
(filename [2] == '\\' || filename [2] == '/')))
#else
/* Under UNIX, VMS, or OS/2, we have a full path if the path starts
* with the directory marker
*/
if (filename [0] == PATHEND)
#endif
return (TRUE);
else
return (FALSE);
}
/* -------------------------------------------------------------------------
* build_next_path -- internal
*
*/
static char *
build_next_path (char *dest, const char *path, const char *name)
{
int
length; /* length of directory name */
char
*pathptr = (char *) path;
if (path)
{
length = strcspn (path, PATHSEP);
strncpy (dest, path, length);
pathptr += length; /* Bump past path delimiter */
if (*pathptr) /* unless we are at the end */
pathptr++; /* of the path */
if ((length)
&& (dest [length - 1] != PATHEND))
dest [length++] = PATHEND; /* Add path-to-filename delimiter */
dest [length] = '\0';
strcat (dest, name);
}
else
strcpy (dest, name);
return (pathptr);
}
/* -------------------------------------------------------------------------
* build_next_path_ext -- internal
*
*/
static char *
build_next_path_ext (char *dest, const char *path,
const char *name, const char *ext)
{
int
length; /* length of directory name */
char
*pathptr = (char *) path;
if (path)
{
length = strcspn (path, PATHSEP);
strncpy (dest, path, length);
pathptr += length; /* Bump past path delimiter */
if (*pathptr) /* unless we are at the end */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -