/* Lisp functions for making directory listings.
Copyright (C) 1985, 1986, 1993, 1994, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
#endif
extern int completion_ignore_case;
+extern Lisp_Object Qcompletion_ignore_case;
extern Lisp_Object Vcompletion_regexp_list;
Lisp_Object Vcompletion_ignored_extensions;
-Lisp_Object Qcompletion_ignore_case;
Lisp_Object Qdirectory_files;
Lisp_Object Qdirectory_files_and_attributes;
Lisp_Object Qfile_name_completion;
/* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
run_pre_post_conversion_on_str which calls Lisp directly and
indirectly. */
- dirfilename = ENCODE_FILE (dirfilename);
- encoded_directory = ENCODE_FILE (directory);
+ if (STRING_MULTIBYTE (dirfilename))
+ dirfilename = ENCODE_FILE (dirfilename);
+ encoded_directory = (STRING_MULTIBYTE (directory)
+ ? ENCODE_FILE (directory) : directory);
/* Now *bufp is the compiled form of MATCH; don't call anything
which might compile a new regexp until we're done with the loop! */
name = finalname = make_unibyte_string (dp->d_name, len);
GCPRO2 (finalname, name);
- /* Note: ENCODE_FILE can GC; it should protect its argument,
+ /* Note: DECODE_FILE can GC; it should protect its argument,
though. */
name = DECODE_FILE (name);
len = SBYTES (name);
DIR *d;
int bestmatchsize = 0, skip;
register int compare, matchsize;
- unsigned char *p1, *p2;
int matchcount = 0;
/* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded.
If ALL_FLAG is 0, BESTMATCH is either nil
/* Do completion on the encoded file name
because the other names in the directory are (we presume)
encoded likewise. We decode the completed string at the end. */
- encoded_file = ENCODE_FILE (file);
+ /* Actually, this is not quite true any more: we do most of the completion
+ work with decoded file names, but we still do some filtering based
+ on the encoded file name. */
+ encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file;
encoded_dir = ENCODE_FILE (dirname);
CONSP (tem); tem = XCDR (tem))
{
int elt_len;
+ unsigned char *p1;
elt = XCAR (tem);
if (!STRINGP (elt))
if (!passcount && CONSP (tem))
continue;
+ /* FIXME: If we move this `decode' earlier we can eliminate
+ the repeated ENCODE_FILE on Vcompletion_ignored_extensions. */
+ name = make_unibyte_string (dp->d_name, len);
+ name = DECODE_FILE (name);
+
if (!passcount)
{
Lisp_Object regexps;
/* Ignore this element if it fails to match all the regexps. */
for (regexps = Vcompletion_regexp_list; CONSP (regexps);
regexps = XCDR (regexps))
- {
- tem = Fstring_match (XCAR (regexps),
- make_string (dp->d_name, len), zero);
- if (NILP (tem))
- break;
- }
+ if (fast_string_match (XCAR (regexps), name) < 0)
+ break;
if (CONSP (regexps))
continue;
}
if (directoryp)
{
/* This completion is a directory; make it end with '/' */
- name = Ffile_name_as_directory (make_string (dp->d_name, len));
+ name = Ffile_name_as_directory (name);
}
- else
- name = make_string (dp->d_name, len);
/* Test the predicate, if any. */
struct gcpro gcpro1;
GCPRO1 (name);
- decoded = Fexpand_file_name (DECODE_FILE (name), dirname);
+ decoded = Fexpand_file_name (name, dirname);
val = call1 (predicate, decoded);
UNGCPRO;
matchcount++;
if (all_flag)
- {
- name = DECODE_FILE (name);
- bestmatch = Fcons (name, bestmatch);
- }
+ bestmatch = Fcons (name, bestmatch);
else if (NILP (bestmatch))
{
bestmatch = name;
}
else
{
- compare = min (bestmatchsize, len);
- p1 = SDATA (bestmatch);
- p2 = (unsigned char *) dp->d_name;
- matchsize = scmp (p1, p2, compare);
- if (matchsize < 0)
+ Lisp_Object zero = make_number (0);
+ /* FIXME: This is a copy of the code in Ftry_completion. */
+ compare = min (bestmatchsize, SCHARS (name));
+ tem = Fcompare_strings (bestmatch, zero,
+ make_number (compare),
+ name, zero,
+ make_number (compare),
+ completion_ignore_case ? Qt : Qnil);
+ if (EQ (tem, Qt))
matchsize = compare;
+ else if (XINT (tem) < 0)
+ matchsize = - XINT (tem) - 1;
+ else
+ matchsize = XINT (tem) - 1;
+
if (completion_ignore_case)
{
/* If this is an exact match except for case,
of the actual match. */
/* This tests that the current file is an exact match
but BESTMATCH is not (it is too long). */
- if ((matchsize == len
+ if ((matchsize == SCHARS (name)
&& matchsize + !!directoryp
- < SCHARS (bestmatch))
+ < SCHARS (bestmatch))
||
/* If there is no exact match ignoring case,
prefer a match that does not change the case
prefer that one. */
/* This == checks that, of current file and BESTMATCH,
either both or neither are exact. */
- (((matchsize == len)
+ (((matchsize == SCHARS (name))
==
- (matchsize + !!directoryp
- == SCHARS (bestmatch)))
- && !bcmp (p2, SDATA (encoded_file), SCHARS (encoded_file))
- && bcmp (p1, SDATA (encoded_file), SCHARS (encoded_file))))
+ (matchsize + !!directoryp == SCHARS (bestmatch)))
+ && (tem = Fcompare_strings (name, zero,
+ make_number (SCHARS (file)),
+ file, zero,
+ Qnil,
+ Qnil),
+ EQ (Qt, tem))
+ && (tem = Fcompare_strings (bestmatch, zero,
+ make_number (SCHARS (file)),
+ file, zero,
+ Qnil,
+ Qnil),
+ ! EQ (Qt, tem))))
bestmatch = name;
}
-
- /* If this dirname all matches, see if implicit following
- slash does too. */
- if (directoryp
- && compare == matchsize
- && bestmatchsize > matchsize
- && IS_ANY_SEP (p1[matchsize]))
- matchsize++;
bestmatchsize = matchsize;
}
}
bestmatch = unbind_to (count, bestmatch);
if (all_flag || NILP (bestmatch))
- {
- if (STRINGP (bestmatch))
- bestmatch = DECODE_FILE (bestmatch);
- return bestmatch;
- }
+ return bestmatch;
if (matchcount == 1 && bestmatchsize == SCHARS (file))
return Qt;
bestmatch = Fsubstring (bestmatch, make_number (0),
make_number (bestmatchsize));
- /* Now that we got the right initial segment of BESTMATCH,
- decode it from the coding system in use. */
- bestmatch = DECODE_FILE (bestmatch);
return bestmatch;
}
Fcons (make_number (time & 0177777), Qnil));
}
+static char *
+stat_uname (struct stat *st)
+{
+#ifdef WINDOWSNT
+ return st->st_uname;
+#else
+ struct passwd *pw = (struct passwd *) getpwuid (st->st_uid);
+
+ if (pw)
+ return pw->pw_name;
+ else
+ return NULL;
+#endif
+}
+
+static char *
+stat_gname (struct stat *st)
+{
+#ifdef WINDOWSNT
+ return st->st_gname;
+#else
+ struct group *gr = (struct group *) getgrgid (st->st_gid);
+
+ if (gr)
+ return gr->gr_name;
+ else
+ return NULL;
+#endif
+}
+
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.
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.
+ 9. t if 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.
+ but still fits into a 32-bit number, this is a cons cell containing two
+ integers: first the high part, then the low 16 bits. If the inode number
+ is wider than 32 bits, this is a cons cell containing three integers:
+ first the high 24 bits, then middle 24 bits, and finally 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. */)
(filename, id_format)
Lisp_Object values[12];
Lisp_Object encoded;
struct stat s;
- struct passwd *pw;
- struct group *gr;
#if defined (BSD4_2) || defined (BSD4_3)
Lisp_Object dirname;
struct stat sdir;
char modes[10];
Lisp_Object handler;
struct gcpro gcpro1;
- EMACS_INT uid, gid, ino;
+ EMACS_INT ino;
+ char *uname, *gname;
filename = Fexpand_file_name (filename, Qnil);
#endif
}
values[1] = make_number (s.st_nlink);
- /* When make_fixnum_or_float is called below with types that are
- shorter than an int (e.g., `short'), GCC whines about comparison
- being always false due to limited range of data type. Fix by
- copying s.st_uid and s.st_gid into int variables. */
- 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);
+ values[2] = make_fixnum_or_float (s.st_uid);
+ values[3] = make_fixnum_or_float (s.st_gid);
}
else
{
BLOCK_INPUT;
- pw = (struct passwd *) getpwuid (uid);
- values[2] = (pw ? build_string (pw->pw_name)
- : make_fixnum_or_float (uid));
- gr = (struct group *) getgrgid (gid);
- values[3] = (gr ? build_string (gr->gr_name)
- : make_fixnum_or_float (gid));
+ uname = stat_uname (&s);
+ values[2] = (uname ? build_string (uname)
+ : make_fixnum_or_float (s.st_uid));
+ gname = stat_gname (&s);
+ values[3] = (gname ? build_string (gname)
+ : make_fixnum_or_float (s.st_gid));
UNBLOCK_INPUT;
}
values[4] = make_time (s.st_atime);
if (! NILP (dirname))
encoded = ENCODE_FILE (dirname);
if (! NILP (dirname) && stat (SDATA (encoded), &sdir) == 0)
- values[9] = (sdir.st_gid != gid) ? Qt : Qnil;
+ values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil;
else /* if we can't tell, assume worst */
values[9] = Qt;
#else /* file gid will be egid */
- values[9] = (gid != getegid ()) ? Qt : Qnil;
+ values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
#endif /* BSD4_2 (or BSD4_3) */
/* Shut up GCC warnings in FIXNUM_OVERFLOW_P below. */
- ino = s.st_ino;
- if (FIXNUM_OVERFLOW_P (ino))
+ if (sizeof (s.st_ino) > sizeof (ino))
+ ino = (EMACS_INT)(s.st_ino & 0xffffffff);
+ else
+ ino = s.st_ino;
+ if (!FIXNUM_OVERFLOW_P (ino)
+ && (sizeof (s.st_ino) <= sizeof (ino) || (s.st_ino & ~INTMASK) == 0))
+ /* Keep the most common cases as integers. */
+ values[10] = make_number (ino);
+ else if (sizeof (s.st_ino) <= sizeof (ino)
+ || ((s.st_ino >> 16) & ~INTMASK) == 0)
/* To allow inode numbers larger than VALBITS, separate the bottom
16 bits. */
- values[10] = Fcons (make_number (ino >> 16),
- make_number (ino & 0xffff));
+ values[10] = Fcons (make_number ((EMACS_INT)(s.st_ino >> 16)),
+ make_number ((EMACS_INT)(s.st_ino & 0xffff)));
else
- /* But keep the most common cases as integers. */
- values[10] = make_number (ino);
+ {
+ /* 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;
+ EMACS_INT low_ino = s.st_ino & 0xffffffff;
+
+ values[10] = Fcons (make_number (high_ino >> 8),
+ Fcons (make_number (((high_ino & 0xff) << 16)
+ + (low_ino >> 16)),
+ make_number (low_ino & 0xffff)));
+ }
- /* Likewise for device. */
- if (FIXNUM_OVERFLOW_P (s.st_dev))
+ /* Likewise for device, but don't let it become negative. We used
+ to use FIXNUM_OVERFLOW_P here, but that won't catch large
+ positive numbers such as 0xFFEEDDCC. */
+ if ((EMACS_INT)s.st_dev < 0
+ || (EMACS_INT)s.st_dev > MOST_POSITIVE_FIXNUM)
values[11] = Fcons (make_number (s.st_dev >> 16),
make_number (s.st_dev & 0xffff));
else
defsubr (&Sfile_attributes);
defsubr (&Sfile_attributes_lessp);
-#ifdef VMS
- Qcompletion_ignore_case = intern ("completion-ignore-case");
- staticpro (&Qcompletion_ignore_case);
-#endif /* VMS */
-
DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions,
doc: /* Completion ignores file names ending in any string in this list.
It does not ignore them if all possible completions end in one of