⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sflfile.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 5 页
字号:
      {
        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 + -