/* From filemode.c. Can't go in Lisp.h because of `stat'. */
extern void filemodestring P_ ((struct stat *, char *));
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
/* if system does not have symbolic links, it does not have lstat.
In that case, use ordinary stat instead. */
Lisp_Object Qfile_name_all_completions;
Lisp_Object Qfile_attributes;
Lisp_Object Qfile_attributes_lessp;
+
+static int scmp P_ ((unsigned char *, unsigned char *, int));
\f
Lisp_Object
/* Function shared by Fdirectory_files and Fdirectory_files_and_attributes.
When ATTRS is zero, return a list of directory filenames; when
non-zero, return a list of directory filenames and their attributes. */
+
Lisp_Object
directory_files_internal (directory, full, match, nosort, attrs)
Lisp_Object directory, full, match, nosort;
Lisp_Object list, dirfilename, encoded_directory;
struct re_pattern_buffer *bufp = NULL;
int needsep = 0;
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
DIRENTRY *dp;
int retry_p;
if (!NILP (match))
{
- CHECK_STRING (match, 3);
+ CHECK_STRING (match);
/* MATCH might be a flawed regular expression. Rather than
catching and signaling our own errors, we just call
#endif /* not VMS */
/* Loop reading blocks until EOF or error. */
- errno = 0;
- while ((dp = readdir (d)) != NULL)
+ for (;;)
{
+ errno = 0;
+ dp = readdir (d);
+
+#ifdef EAGAIN
+ if (dp == NULL && errno == EAGAIN)
+ continue;
+#endif
+
+ if (dp == NULL)
+ break;
+
if (DIRENTRY_NONEMPTY (dp))
{
int len;
}
retry_p = 0;
-#ifdef EAGAIN
- retry_p |= errno == EAGAIN;
-#endif
#ifdef EINTR
retry_p |= errno == EINTR;
#endif
DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
- "Return a list of names of files in DIRECTORY.\n\
-There are three optional arguments:\n\
-If FULL is non-nil, return absolute file names. Otherwise return names\n\
- that are relative to the specified directory.\n\
-If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
-If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
- NOSORT is useful if you plan to sort the result yourself.")
- (directory, full, match, nosort)
+ doc: /* Return a list of names of files in DIRECTORY.
+There are three optional arguments:
+If FULL is non-nil, return absolute file names. Otherwise return names
+ that are relative to the specified directory.
+If MATCH is non-nil, mention only file names that match the regexp MATCH.
+If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
+ NOSORT is useful if you plan to sort the result yourself. */)
+ (directory, full, match, nosort)
Lisp_Object directory, full, match, nosort;
{
Lisp_Object handler;
return directory_files_internal (directory, full, match, nosort, 0);
}
-DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes, Sdirectory_files_and_attributes, 1, 4, 0,
- "Return a list of names of files and their attributes in DIRECTORY.\n\
-There are three optional arguments:\n\
-If FULL is non-nil, return absolute file names. Otherwise return names\n\
- that are relative to the specified directory.\n\
-If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
-If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
- NOSORT is useful if you plan to sort the result yourself.")
- (directory, full, match, nosort)
+DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
+ Sdirectory_files_and_attributes, 1, 4, 0,
+ doc: /* Return a list of names of files and their attributes in DIRECTORY.
+There are three optional arguments:
+If FULL is non-nil, return absolute file names. Otherwise return names
+ that are relative to the specified directory.
+If MATCH is non-nil, mention only file names that match the regexp MATCH.
+If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
+ NOSORT is useful if you plan to sort the result yourself. */)
+ (directory, full, match, nosort)
Lisp_Object directory, full, match, nosort;
{
Lisp_Object handler;
Lisp_Object file_name_completion ();
DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
- 2, 2, 0,
- "Complete file name FILE in directory DIRECTORY.\n\
-Returns the longest string\n\
-common to all file names in DIRECTORY that start with FILE.\n\
-If there is only one and FILE matches it exactly, returns t.\n\
-Returns nil if DIR contains no name starting with FILE.")
- (file, directory)
+ 2, 2, 0,
+ doc: /* Complete file name FILE in directory DIRECTORY.
+Returns the longest string
+common to all file names in DIRECTORY that start with FILE.
+If there is only one and FILE matches it exactly, returns t.
+Returns nil if DIR contains no name starting with FILE.
+
+This function ignores some of the possible completions as
+determined by the variable `completion-ignored-extensions', which see. */)
+ (file, directory)
Lisp_Object file, directory;
{
Lisp_Object handler;
}
DEFUN ("file-name-all-completions", Ffile_name_all_completions,
- Sfile_name_all_completions, 2, 2, 0,
- "Return a list of all completions of file name FILE in directory DIRECTORY.\n\
-These are all file names in directory DIRECTORY which begin with FILE.")
- (file, directory)
+ Sfile_name_all_completions, 2, 2, 0,
+ doc: /* Return a list of all completions of file name FILE in directory DIRECTORY.
+These are all file names in directory DIRECTORY which begin with FILE. */)
+ (file, directory)
Lisp_Object file, directory;
{
Lisp_Object handler;
struct stat st;
int directoryp;
int passcount;
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
elt = Qnil;
readfunc = readdirver;
file = Fupcase (file);
#else /* not VMS */
- CHECK_STRING (file, 0);
+ CHECK_STRING (file);
#endif /* not VMS */
#ifdef FILE_SYSTEM_CASE
actually in the way in a directory contains only one file. */
if (!passcount && TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
continue;
+ if (!passcount && len > XSTRING (encoded_file)->size)
+ /* Ignore directories if they match an element of
+ completion-ignored-extensions which ends in a slash. */
+ for (tem = Vcompletion_ignored_extensions;
+ CONSP (tem); tem = XCDR (tem))
+ {
+ int elt_len;
+
+ elt = XCAR (tem);
+ if (!STRINGP (elt))
+ continue;
+ /* Need to encode ELT, since scmp compares unibyte
+ strings only. */
+ elt = ENCODE_FILE (elt);
+ elt_len = XSTRING (elt)->size - 1; /* -1 for trailing / */
+ if (elt_len <= 0)
+ continue;
+ p1 = XSTRING (elt)->data;
+ if (p1[elt_len] != '/')
+ continue;
+ skip = len - elt_len;
+ if (skip < 0)
+ continue;
+
+ if (0 <= scmp (dp->d_name + skip, p1, elt_len))
+ continue;
+ break;
+ }
}
else
{
{
elt = XCAR (tem);
if (!STRINGP (elt)) continue;
+ /* Need to encode ELT, since scmp compares unibyte
+ strings only. */
+ elt = ENCODE_FILE (elt);
skip = len - XSTRING (elt)->size;
if (skip < 0) continue;
for (regexps = Vcompletion_regexp_list; CONSP (regexps);
regexps = XCDR (regexps))
{
- tem = Fstring_match (XCAR (regexps), elt, zero);
+ tem = Fstring_match (XCAR (regexps),
+ make_string (dp->d_name, len), zero);
if (NILP (tem))
break;
}
return Fsignal (Qquit, Qnil);
}
+/* Compare exactly LEN chars of strings at S1 and S2,
+ ignoring case if appropriate.
+ Return -1 if strings match,
+ else number of chars that match at the beginning. */
+
+static int
+scmp (s1, s2, len)
+ register unsigned char *s1, *s2;
+ int len;
+{
+ register int l = len;
+
+ if (completion_ignore_case)
+ {
+ while (l && DOWNCASE (*s1++) == DOWNCASE (*s2++))
+ l--;
+ }
+ else
+ {
+ while (l && *s1++ == *s2++)
+ l--;
+ }
+ if (l == 0)
+ return -1;
+ else
+ return len - l;
+}
+
static int
file_name_completion_stat (dirname, dp, st_addr)
Lisp_Object dirname;
#ifdef VMS
DEFUN ("file-name-all-versions", Ffile_name_all_versions,
- Sfile_name_all_versions, 2, 2, 0,
- "Return a list of all versions of file name FILE in directory DIRECTORY.")
- (file, directory)
+ Sfile_name_all_versions, 2, 2, 0,
+ doc: /* Return a list of all versions of file name FILE in directory DIRECTORY. */)
+ (file, directory)
Lisp_Object file, directory;
{
return file_name_completion (file, directory, 1, 1);
}
DEFUN ("file-version-limit", Ffile_version_limit, Sfile_version_limit, 1, 1, 0,
- "Return the maximum number of versions allowed for FILE.\n\
-Returns nil if the file cannot be opened or if there is no version limit.")
- (filename)
+ doc: /* Return the maximum number of versions allowed for FILE.
+Returns nil if the file cannot be opened or if there is no version limit. */)
+ (filename)
Lisp_Object filename;
{
Lisp_Object retval;
}
DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 1, 0,
- "Return a list of attributes of file FILENAME.\n\
-Value is nil if specified file cannot be opened.\n\
-Otherwise, list elements are:\n\
- 0. t for directory, string (name linked to) for symbolic link, or nil.\n\
- 1. Number of links to file.\n\
- 2. File uid.\n\
- 3. File gid.\n\
- 4. Last access time, as a list of two integers.\n\
- First integer has high-order 16 bits of time, second has low 16 bits.\n\
- 5. Last modification time, likewise.\n\
- 6. Last status change time, likewise.\n\
- 7. Size in bytes.\n\
- This is a floating point number if the size is too large for an integer.\n\
- 8. File modes, as a string of ten letters or dashes as in ls -l.\n\
- 9. t iff file's gid would change if file were deleted and recreated.\n\
-10. inode number. If inode number is larger than the Emacs integer,\n\
- this is a cons cell containing two integers: first the high part,\n\
- then the low 16 bits.\n\
-11. Device number.\n\
-\n\
-If file does not exist, returns nil.")
- (filename)
+ doc: /* Return a list of attributes of file FILENAME.
+Value is nil if specified file cannot be opened.
+Otherwise, list elements are:
+ 0. t for directory, string (name linked to) for symbolic link, or nil.
+ 1. Number of links to file.
+ 2. File uid.
+ 3. File gid.
+ 4. Last access time, as a list of two integers.
+ First integer has high-order 16 bits of time, second has low 16 bits.
+ 5. Last modification time, likewise.
+ 6. Last status change time, likewise.
+ 7. Size in bytes.
+ This is a floating point number if the size is too large for an integer.
+ 8. File modes, as a string of ten letters or dashes as in ls -l.
+ 9. t iff file's gid would change if file were deleted and recreated.
+10. inode number. If inode number is larger than the Emacs integer,
+ this is a cons cell containing two integers: first the high part,
+ then the low 16 bits.
+11. Device number. If it is larger than the Emacs integer, this is
+ a cons cell, similar to the inode number.
+
+If file does not exist, returns nil. */)
+ (filename)
Lisp_Object filename;
{
Lisp_Object values[12];
values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
#endif /* BSD4_2 (or BSD4_3) */
/* Cast -1 to avoid warning if int is not as wide as VALBITS. */
- if (s.st_ino & (((EMACS_INT) (-1)) << VALBITS))
+ if (FIXNUM_OVERFLOW_P (s.st_ino))
/* To allow inode numbers larger than VALBITS, separate the bottom
16 bits. */
values[10] = Fcons (make_number (s.st_ino >> 16),
values[10] = make_number (s.st_ino);
/* Likewise for device. */
- if (s.st_dev & (((EMACS_INT) (-1)) << VALBITS))
+ if (FIXNUM_OVERFLOW_P (s.st_dev))
values[11] = Fcons (make_number (s.st_dev >> 16),
make_number (s.st_dev & 0xffff));
else
}
DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, Sfile_attributes_lessp, 2, 2, 0,
- "Return t if first arg file attributes list is less than second.\n\
-Comparison is in lexicographic order and case is significant.")
- (f1, f2)
+ doc: /* Return t if first arg file attributes list is less than second.
+Comparison is in lexicographic order and case is significant. */)
+ (f1, f2)
Lisp_Object f1, f2;
{
return Fstring_lessp (Fcar (f1), Fcar (f2));
#endif /* VMS */
DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions,
- "*Completion ignores filenames ending in any string in this list.\n\
-This variable does not affect lists of possible completions,\n\
-but does affect the commands that actually do completions.");
+ doc: /* *Completion ignores filenames ending in any string in this list.
+Directories are ignored if they match any string in this list which
+ends in a slash.
+This variable does not affect lists of possible completions,
+but does affect the commands that actually do completions. */);
Vcompletion_ignored_extensions = Qnil;
}