/* Lisp functions for making directory listings.
Copyright (C) 1985, 1986, 1993, 1994, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
-#ifndef VMS
#include <grp.h>
-#endif
#include <errno.h>
-#ifdef VMS
-#include <string.h>
-#include <rms.h>
-#include <rmsdef.h>
-#endif
-
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#else /* not SYSV_SYSTEM_DIR */
-#ifdef NONSYSTEM_DIR_LIBRARY
-#include "ndir.h"
-#else /* not NONSYSTEM_DIR_LIBRARY */
#ifdef MSDOS
#include <dirent.h>
#else
#include <sys/dir.h>
#endif
-#endif /* not NONSYSTEM_DIR_LIBRARY */
#include <sys/stat.h>
compile_pattern to do the work for us. */
/* Pass 1 for the MULTIBYTE arg
because we do make multibyte strings if the contents warrant. */
-#ifdef VMS
- bufp = compile_pattern (match, 0,
- buffer_defaults.downcase_table, 0, 1);
-#else /* !VMS */
# ifdef WINDOWSNT
/* Windows users want case-insensitive wildcards. */
bufp = compile_pattern (match, 0,
# else /* !WINDOWSNT */
bufp = compile_pattern (match, 0, Qnil, 0, 1);
# endif /* !WINDOWSNT */
-#endif /* !VMS */
}
/* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
re_match_object = Qt;
/* Decide whether we need to add a directory separator. */
-#ifndef VMS
if (directory_nbytes == 0
|| !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)))
needsep = 1;
-#endif /* not VMS */
/* Loop reading blocks until EOF or error. */
for (;;)
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. */)
+ Otherwise, the list returned is sorted with `stringp-lessp'.
+ NOSORT is useful if you plan to sort the result yourself. */)
(directory, full, match, nosort)
Lisp_Object directory, full, match, nosort;
{
elt = Qnil;
-#ifdef VMS
- extern DIRENTRY * readdirver ();
-
- DIRENTRY *((* readfunc) ());
-
- /* Filename completion on VMS ignores case, since VMS filesys does. */
- specbind (Qcompletion_ignore_case, Qt);
-
- readfunc = readdir;
- if (ver_flag)
- readfunc = readdirver;
- file = Fupcase (file);
-#else /* not VMS */
CHECK_STRING (file);
-#endif /* not VMS */
#ifdef FILE_SYSTEM_CASE
file = FILE_SYSTEM_CASE (file);
int len;
int canexclude = 0;
-#ifdef VMS
- dp = (*readfunc) (d);
-#else
errno = 0;
dp = readdir (d);
if (dp == NULL && (0
# endif
))
{ QUIT; continue; }
-#endif
if (!dp) break;
if (!all_flag)
{
int skip;
+
+#if 0 /* FIXME: The `scmp' call compares an encoded and a decoded string. */
+ /* If this entry matches the current bestmatch, the only
+ thing it can do is increase matchcount, so don't bother
+ investigating it any further. */
+ if (!completion_ignore_case
+ /* The return result depends on whether it's the sole match. */
+ && matchcount > 1
+ && !includeall /* This match may allow includeall to 0. */
+ && len >= bestmatchsize
+ && 0 > scmp (dp->d_name, SDATA (bestmatch), bestmatchsize))
+ continue;
+#endif
+
if (directoryp)
{
#ifndef TRIVIAL_DIRECTORY_ENTRY
XSETFASTINT (zero, 0);
/* Ignore this element if it fails to match all the regexps. */
- for (regexps = Vcompletion_regexp_list; CONSP (regexps);
- regexps = XCDR (regexps))
- if (fast_string_match (XCAR (regexps), name) < 0)
- break;
+ if (completion_ignore_case)
+ {
+ for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+ regexps = XCDR (regexps))
+ if (fast_string_match_ignore_case (XCAR (regexps), name) < 0)
+ break;
+ }
+ else
+ {
+ for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+ regexps = XCDR (regexps))
+ if (fast_string_match (XCAR (regexps), name) < 0)
+ break;
+ }
+
if (CONSP (regexps))
continue;
}
/* This tests that the current file is an exact match
but BESTMATCH is not (it is too long). */
if ((matchsize == SCHARS (name)
- && matchsize + !!directoryp
- < SCHARS (bestmatch))
+ && matchsize + !!directoryp < SCHARS (bestmatch))
||
/* If there is no exact match ignoring case,
prefer a match that does not change the case
bestmatch = name;
}
bestmatchsize = matchsize;
+
+ /* If the best completion so far is reduced to the string
+ we're trying to complete, then we already know there's no
+ other completion, so there's no point looking any further. */
+ if (matchsize <= SCHARS (file)
+ && !includeall /* A future match may allow includeall to 0. */
+ /* If completion-ignore-case is non-nil, don't
+ short-circuit because we want to find the best
+ possible match *including* case differences. */
+ && (!completion_ignore_case || matchsize == 0)
+ /* The return value depends on whether it's the sole match. */
+ && matchcount > 1)
+ break;
+
}
}
#endif /* MSDOS */
bcopy (SDATA (dirname), fullname, pos);
-#ifndef VMS
if (!IS_DIRECTORY_SEP (fullname[pos - 1]))
fullname[pos++] = DIRECTORY_SEP;
-#endif
bcopy (dp->d_name, fullname + pos, len);
fullname[pos + len] = 0;
#endif /* S_IFLNK */
}
\f
-#ifdef VMS
-
-DEFUN ("file-name-all-versions", Ffile_name_all_versions,
- 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, Qnil);
-}
-
-DEFUN ("file-version-limit", Ffile_version_limit, Sfile_version_limit, 1, 1, 0,
- 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;
- struct FAB fab;
- struct RAB rab;
- struct XABFHC xabfhc;
- int status;
-
- filename = Fexpand_file_name (filename, Qnil);
- fab = cc$rms_fab;
- xabfhc = cc$rms_xabfhc;
- fab.fab$l_fna = SDATA (filename);
- fab.fab$b_fns = strlen (fab.fab$l_fna);
- fab.fab$l_xab = (char *) &xabfhc;
- status = sys$open (&fab, 0, 0);
- if (status != RMS$_NORMAL) /* Probably non-existent file */
- return Qnil;
- sys$close (&fab, 0, 0);
- if (xabfhc.xab$w_verlimit == 32767)
- return Qnil; /* No version limit */
- else
- return make_number (xabfhc.xab$w_verlimit);
-}
-
-#endif /* VMS */
-\f
Lisp_Object
make_time (time)
time_t time;
#endif
}
+/* Make an integer or float number for UID and GID, while being
+ careful not to produce negative numbers due to signed integer
+ overflow. */
+static Lisp_Object
+make_uid (struct stat *st)
+{
+ EMACS_INT uid = st->st_uid;
+
+ if (sizeof (st->st_uid) > sizeof (uid) || uid < 0 || FIXNUM_OVERFLOW_P (uid))
+ return make_float ((double)st->st_uid);
+ return make_number (uid);
+}
+
+static Lisp_Object
+make_gid (struct stat *st)
+{
+ EMACS_INT gid = st->st_gid;
+
+ if (sizeof (st->st_gid) > sizeof (gid) || gid < 0 || FIXNUM_OVERFLOW_P (gid))
+ return make_float ((double)st->st_gid);
+ return make_number (gid);
+}
+
DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 2, 0,
doc: /* Return a list of attributes of file FILENAME.
Value is nil if specified file cannot be opened.
Elements of the attribute list are:
0. t for directory, string (name linked to) for symbolic link, or nil.
1. Number of links to file.
- 2. File uid as a string or an integer. If a string value cannot be
- looked up, the integer value is returned.
+ 2. File uid as a string or a number. If a string value cannot be
+ looked up, a numeric value, either an integer or a float, is returned.
3. File gid, likewise.
4. Last access time, as a list of two integers.
First integer has high-order 16 bits of time, second has low 16 bits.
Lisp_Object handler;
struct gcpro gcpro1;
EMACS_INT ino, uid, gid;
- char *uname, *gname;
+ char *uname = NULL, *gname = NULL;
filename = Fexpand_file_name (filename, Qnil);
#endif
}
values[1] = make_number (s.st_nlink);
- uid = s.st_uid;
- gid = s.st_gid;
- if (NILP (id_format) || EQ (id_format, Qinteger))
- {
- values[2] = make_fixnum_or_float (uid);
- values[3] = make_fixnum_or_float (gid);
- }
- else
+
+ if (!(NILP (id_format) || EQ (id_format, Qinteger)))
{
BLOCK_INPUT;
uname = stat_uname (&s);
- values[2] = (uname ? build_string (uname)
- : make_fixnum_or_float (uid));
gname = stat_gname (&s);
- values[3] = (gname ? build_string (gname)
- : make_fixnum_or_float (gid));
UNBLOCK_INPUT;
}
+ if (uname)
+ values[2] = build_string (uname);
+ else
+ values[2] = make_uid (&s);
+ if (gname)
+ values[3] = build_string (gname);
+ else
+ values[3] = make_gid (&s);
+
values[4] = make_time (s.st_atime);
values[5] = make_time (s.st_mtime);
values[6] = make_time (s.st_ctime);
else
{
/* To allow inode numbers beyond 32 bits, separate into 2 24-bit
- high parts and a 16-bit bottom part. */
- EMACS_INT high_ino = s.st_ino >> 32;
+ high parts and a 16-bit bottom part.
+ The code on the next line avoids a compiler warning on
+ systems where st_ino is 32 bit wide. (bug#766). */
+ EMACS_INT high_ino = s.st_ino >> 31 >> 1;
EMACS_INT low_ino = s.st_ino & 0xffffffff;
values[10] = Fcons (make_number (high_ino >> 8),
defsubr (&Sdirectory_files);
defsubr (&Sdirectory_files_and_attributes);
defsubr (&Sfile_name_completion);
-#ifdef VMS
- defsubr (&Sfile_name_all_versions);
- defsubr (&Sfile_version_limit);
-#endif /* VMS */
defsubr (&Sfile_name_all_completions);
defsubr (&Sfile_attributes);
defsubr (&Sfile_attributes_lessp);