Lugaru's Epsilon
Programmer's
Editor 14.04

Context:
Epsilon User's Manual and Reference
   Primitives and EEL Subroutines
      . . .
      Display Primitives
         Creating & Destroying Windows
         Window Resizing Primitives
         Preserving Window Arrangements
         . . .
         Colors
      File Primitives
         . . .
         Low-level File Primitives
         Directories
         Manipulating File Names
         Internet Primitives
         Tagging Internals
      Operating System Primitives
         System Primitives
         Window System Primitives
         Timing
         Calling Windows DLLs
         Running a Process
      . . .

Previous   Up    Next
Dired Subroutines  Primitives and EEL Subroutines   Internet Primitives


Epsilon User's Manual and Reference > Primitives and EEL Subroutines > File Primitives >

Manipulating File Names

absolute(char *file, ?char *dir)
relative(char *abs, char *rel, ?char *dir)
int is_relative(char *fname)

Because the current directory can change, through use of the chdir( ) primitive described above, Epsilon normally keeps file names in absolute pathname form, with all the defaults in the name made explicit. It converts a file name to the appropriate relative pathname whenever it displays the name (for example, in the mode line).

The absolute( ) primitive takes a pointer to a character array containing a file name. It makes the file name be an absolute pathname, with all the defaults made explicit. For example, if the default drive is B:, the current directory is /harold/papers, the path_sep variable is "\" and the 80 character array fname contains "proposal"; calling absolute( ) with the argument fname makes fname contain "B:\harold\papers\proposal".

The primitive relative( ) does the reverse. It takes a file name in absolute form and puts an equivalent relative file name in a character array. Unlike absolute( ), which modifies its argument in place, relative( ) makes a copy of the argument with the changes. If the default drive is B:, the current directory is \harold and the 80 character array abs contains B:\harold\papers\proposal, calling relative(abs, rel); puts "papers\proposal" in the string array rel. You can also get a relative file name by using the %r format specifier in any Epsilon primitive that accepts a printf-style format string.

The relative( ) and absolute( ) primitives each take an optional additional argument, which names a directory. The absolute( ) primitive assumes that any relative file names in its first argument are relative to the directory named by the second argument. (If the second argument is missing or null, the primitive assumes that relative file names are relative to the current directory.) Similarly, if you provide a third argument to the relative( ) primitive, it makes file names relative to the specified directory, instead of the current directory.

Note that in EEL string or character constants, the \ character begins an escape sequence, and you must double it if the character \ is to appear in a string. Thus the Windows file name \harold\papers must appear in an EEL program as the string "\\harold\\papers".

The is_relative( ) primitive returns nonzero if the file name looks like a relative pathname, not an absolute pathname. (It's not intended for use with URLs.)

char *get_tail(char *file, ?int dirok)

The get_tail( ) primitive takes a string containing a file name and returns a pointer to a position in the string after the name of the last directory. For example, suppose that file is the string "/harold/papers/proposal". Then

get_tail(file, 0)

would return a pointer to "proposal". Since the pointer returned is to the original string, you can use this primitive to modify that string. Using the above example, a subsequent

strcpy(get_tail(file, 0), "sample");

would make file contain the string "/harold/papers/sample". The dirok argument says what to do with a file name ending with a separator character "\" or "/". If dirok is nonzero the primitive returns a pointer to right after the final separator character. If dirok is zero, however, the primitive returns a pointer to the first character of the final directory name. (If file contains no directory name, the primitive returns a pointer to its first character when dirok is zero.)

char *get_extension(char *file)

The get_extension( ) primitive returns a pointer to the final extension of the file name given as its argument. For example, an invocation of

get_extension("text.c")

would return a pointer to the ".c" part, and get_extension("text") would return a pointer to the null character at the end of the string. Like get_tail( ), you can use this primitive to modify the string.

int is_path_separator(int ch)

The is_path_separator( ) primitive tells if a character is one of the characters that separate directory or drive names in a file name. It returns 1 if the character is "\" or "/", 2 if the character is ":", otherwise 0. Under Unix, it returns 1 if the character is "/", otherwise 0.

user char path_sep;

The path_sep variable contains the character for separating directory names. It is "\" under Windows, "/" under Unix.

add_final_slash(char *fname)
drop_final_slash(char *fname)

The add_final_slash( ) primitive adds a path separator character like / or \ to the end of fname, if there isn't one already. The drop_final_slash( ) primitive removes the last character of fname if it's a path separator. These primitives never count : as a path separator.

abbreviate_file_name(char *file, int room)

The abbreviate_file_name( ) subroutine defined in disp.e modifies the filename file so it's no more than room characters long, by replacing sections of it with an ellipsis (...). If file is no more than room characters long to begin with, it won't be changed. Values of room less than 10 will be treated as 10.

int is_remote_file(char *fname)
char url_services[50] = "ftp|http|telnet|scp|ssh";
int remote_file_type(char *fname)

The is_remote_file( ) primitive tells whether fname looks like a valid URL. It returns 1 if fname starts with a service name like ftp://, http://, or telnet://, or 2 if fname appears to be an Emacs-style remote file name like /hostname:filename. It uses the url_services variable to determine which service names are valid; this must be a series of |-separated names.

The remote_file_type( ) subroutine is somewhat similar; it tries to determine if a file fname refers to a remote directory, a file pattern, or some other sort of thing. It returns 1 if fname doesn't have the format of a remote file (so it might be a local file), 2 if its syntax is invalid, 3 if it's a remote file that specifies a service other than ftp or scp, 4 if there's no file name after its host name, 5 if it uses wildcards, 6 if it ends in a path separator, or 7 if it uses ~ to name a user's home directory and has no file name following that.

If none of these cases apply, the subroutine contacts the remote system to test whether fname refers to a directory or a file, and returns 8 if it's a directory, otherwise 0. (A value of 0 doesn't indicate there's necessarily a file by that name, just that there is no directory by that name.) While Epsilon is first starting up, the subroutine returns 9 instead of contacting the remote system, since Epsilon can't respond to a site's password request until it has finished initializing, and this synchronous test could otherwise block it from finishing its initialization..

get_executable_directory(char *dir)
get_executable_file(char *dest, char *prog, int quoted)

The get_executable_directory( ) function stores the full pathname of the directory containing the Epsilon executable into dir. The get_executable_file( ) function uses this; it writes into dest the full pathname of a file prog in the same directory as Epsilon's executable. If quoted is nonzero, the file name is inside a pair of quote characters, for use in a command line.

look_up_tree(char *res, char *file, char *dir, char *stop)
int is_in_tree(char *file, char *tree)   /* files.e subr. */

The look_up_tree( ) subroutine searches for file in the given directory dir, its parent directory, and so forth, until it finds a file named file or reaches the root directory. If it finds such a file, it returns nonzero and puts the absolute pathname of the file into the character array res. If it doesn't find a file with the given name, it returns zero and leaves res set to the last file it looked for. If file is an absolute pathname to begin with, it puts the same file name in res, and returns nonzero if that file exists. If dir is a null pointer, look_up_tree( ) begins at the current directory. If stop is non-null, the function only examines child directories of the directory stop. The function stops as soon as it reaches a directory other than stop or one of its subdirectories. This function assumes that all its parameters are in absolute pathname form.

The is_in_tree( ) subroutine returns nonzero if the pathname file is in the directory specified by dir or one of its subdirectories. Both of its parameters must be in absolute pathname form.

user char path_list_char;

The path_list_char variable contains the character separating the directory names in a configuration variable like EPSPATH. It is normally ";", except under Unix, where it is ":".

build_filename(char *result, char *pattern, char *file)

The build_filename( ) subroutine constructs file names from name templates (see File Name Templates). It copies pattern to result, replacing the various % template codes with parts of file, which it obtains by calling primitives such as get_tail( ) and get_extension( ). The expand_string_template( ) subroutine in Modifying Strings provides a more generalized facility to do this.

int fnamecmp(char *f1, char *f2)       /* buffer.e */
int filename_rules(char *fname)

The fnamecmp( ) subroutine compares two file names like the strcmp( ) primitive, returning 0 if they're equal, a positive number if the first comes before the second, or a negative number otherwise. However, it does case-folding on the file names first if this is appropriate for the particular file systems.

The filename_rules( ) primitive asks the operating system if a certain file system is case-sensitive or case-preserving, and returns other information too. It takes the name of any file or directory (which doesn't have to exist) on the file system, and returns a code whose values are represented by macros defined in codes.h. See File Name Case for more information on how Epsilon determines the appropriate code for each file system.

The FSYS_CASE_IGNORED code indicates a non-case-preserving file system like DOS. The FSYS_CASE_PRESERVED code indicates a case-preserving file system like NTFS or VFAT. The FSYS_CASE_SENSITIVE code indicates a case-sensitive file system like Unix. The FSYS_CASE_UNKNOWN code indicates that Epsilon couldn't determine anything about the file system.

The function also returns a bit flag FSYS_SHORT_NAMES, valid whenever any code but FSYS_CASE_UNKNOWN is returned, that indicates whether only 8+3 names are supported. Use the mask macro FSYS_CASE_MASK to strip off this bit: for example, the expression

(filename_rules(f) & FSYS_CASE_MASK) == FSYS_CASE_SENSITIVE

is nonzero if the file system is case-sensitive.

The primitive also may return a bit indicating the type of drive a file is located on, if Epsilon can determine this. FSYS_NETWORK indicates the file is on a different computer and is being accessed over a network. FSYS_CDROM indicates the file is on a CD-ROM disk. FSYS_REMOVABLE indicates the file is on a removable medium like a floppy disk or Zip disk. And FSYS_LOCAL indicates the file is on a local (non-network) hard disk. At most one of the these bits will be present.

Epsilon for Unix returns FSYS_CASE_SENSITIVE for all files, even if they happen to lie on a file system that might use different rules natively. It can't detect the type of drive a file is on either.

int ok_file_match(char *s)        /* complete.e */

The ok_file_match( ) subroutine checks a file name to see if the ignore_file_extensions variable should exclude it from completion. It returns 0 if the file name should be excluded, or 1 if the file name is acceptable.

char *lookpath(char *file, ?int curdir)
char *look_on_path(char *file, int flags, char *path, ?int skip)

The lookpath( ) primitive looks in various standard Epsilon directories for a readable file with the supplied name. As soon as Epsilon locates the file, it returns the file's name. If it can't find the file, it returns a null pointer. See How Epsilon Finds its Files for more information on Epsilon's searching rules. The look_on_path( ) primitive is similar, but you can specify the path to use, and it offers some additional flexibility. These primitives will be described together.

First (for either primitive), if the specified file name is an absolute pathname, Epsilon simply checks to see if the file exists, and returns its name if it does, or a null pointer otherwise.

Next, if you call lookpath( ) with its optional parameter curdir nonzero (or if you call look_on_path( ) with the flag PATH_ADD_CUR_DIR), Epsilon looks for the file in the current directory. If curdir is zero or omitted (or PATH_ADD_CUR_DIR isn't specified), Epsilon skips this step (unless the file name explicitly refers to the current directory, like ".\filename").

The lookpath( ) primitive next looks for the file as explained in How Epsilon Finds its Files, looking along your EPSPATH, or a default one.

Similarly, look_on_path( ) searches the provided path, which is in the same format as an EPSPATH, a list of directory names separated by semicolons for Windows, colons for Unix. The PATH_ADD_EXE_DIR bit makes it search in the executable's directory, like -w32 does for lookpath( ). The PATH_ADD_EXE_PARENT bit makes it search the executable's parent directory. It does both of these additional checks, when enabled, in the above order and just before searching the given path.

By default, look_on_path( ) only searches for files with the specified name. Add the PATH_PERMIT_DIRS flag if you want it to also return directories with that name. With the PATH_PERMIT_WILDCARDS flag, you can use a file pattern like *.c as the file name. The primitive will return the first matching file name.

If you supply look_on_path( ) with an optional skip parameter of n, it will skip over the first n matches it finds (so long as its parameter is a relative pathname). You can use this to reject a file and look for the next one on a path.

The value returned by each of these functions is only valid until the next time you call one of them. Copy the returned file name if you want to preserve it.

convert_to_8_3_filename(char *fname, ?int from8_3)

Under Windows, the convert_to_8_3_filename( ) primitive modifies the given file name by converting all long file names in fname to their short "8.3" file name aliases. Each component of a short file name has no more than eight characters, a dot, and no more than three more characters. For example, the file name "c:\Windows\Start Menu\Programs\Windows Explorer.lnk" might be translated to an equivalent file name of "c:\Windows\STARTM~1\Programs\WINDOW~1.LNK". If the optional from8_3 argument is nonzero, Epsilon translates in the reverse direction. Non-Windows versions of Epsilon will not modify the file name.



Previous   Up    Next
Dired Subroutines  Primitives and EEL Subroutines   Internet Primitives


Lugaru Epsilon Programmer's Editor 14.04 manual. Copyright (C) 1984, 2021 by Lugaru Software Ltd. All rights reserved.