[MSDOS]: If DJGPP version 2, include fcntl.h.
[bpt/emacs.git] / src / dired.c
1 /* Lisp functions for making directory listings.
2 Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include <config.h>
23
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27
28 #ifdef VMS
29 #include <string.h>
30 #include <rms.h>
31 #include <rmsdef.h>
32 #endif
33
34 /* The d_nameln member of a struct dirent includes the '\0' character
35 on some systems, but not on others. What's worse, you can't tell
36 at compile-time which one it will be, since it really depends on
37 the sort of system providing the filesystem you're reading from,
38 not the system you are running on. Paul Eggert
39 <eggert@bi.twinsun.com> says this occurs when Emacs is running on a
40 SunOS 4.1.2 host, reading a directory that is remote-mounted from a
41 Solaris 2.1 host and is in a native Solaris 2.1 filesystem.
42
43 Since applying strlen to the name always works, we'll just do that. */
44 #define NAMLEN(p) strlen (p->d_name)
45
46 #ifdef SYSV_SYSTEM_DIR
47
48 #include <dirent.h>
49 #define DIRENTRY struct dirent
50
51 #else /* not SYSV_SYSTEM_DIR */
52
53 #ifdef NONSYSTEM_DIR_LIBRARY
54 #include "ndir.h"
55 #else /* not NONSYSTEM_DIR_LIBRARY */
56 #ifdef MSDOS
57 #include <dirent.h>
58 #else
59 #include <sys/dir.h>
60 #endif
61 #endif /* not NONSYSTEM_DIR_LIBRARY */
62
63 #ifndef MSDOS
64 #define DIRENTRY struct direct
65
66 extern DIR *opendir ();
67 extern struct direct *readdir ();
68
69 #endif /* not MSDOS */
70 #endif /* not SYSV_SYSTEM_DIR */
71
72 #ifdef MSDOS
73 #define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
74 #else
75 #define DIRENTRY_NONEMPTY(p) ((p)->d_ino)
76 #endif
77
78 #include "lisp.h"
79 #include "buffer.h"
80 #include "commands.h"
81
82 #include "regex.h"
83
84 /* Returns a search buffer, with a fastmap allocated and ready to go. */
85 extern struct re_pattern_buffer *compile_pattern ();
86
87 #define min(a, b) ((a) < (b) ? (a) : (b))
88
89 /* if system does not have symbolic links, it does not have lstat.
90 In that case, use ordinary stat instead. */
91
92 #ifndef S_IFLNK
93 #define lstat stat
94 #endif
95
96 extern int completion_ignore_case;
97 extern Lisp_Object Vcompletion_regexp_list;
98
99 Lisp_Object Vcompletion_ignored_extensions;
100 Lisp_Object Qcompletion_ignore_case;
101 Lisp_Object Qdirectory_files;
102 Lisp_Object Qfile_name_completion;
103 Lisp_Object Qfile_name_all_completions;
104 Lisp_Object Qfile_attributes;
105 \f
106 DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
107 "Return a list of names of files in DIRECTORY.\n\
108 There are three optional arguments:\n\
109 If FULL is non-nil, return absolute file names. Otherwise return names\n\
110 that are relative to the specified directory.\n\
111 If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
112 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
113 NOSORT is useful if you plan to sort the result yourself.")
114 (directory, full, match, nosort)
115 Lisp_Object directory, full, match, nosort;
116 {
117 DIR *d;
118 int dirnamelen;
119 Lisp_Object list, name, dirfilename;
120 Lisp_Object handler;
121 struct re_pattern_buffer *bufp;
122
123 /* If the file name has special constructs in it,
124 call the corresponding file handler. */
125 handler = Ffind_file_name_handler (directory, Qdirectory_files);
126 if (!NILP (handler))
127 {
128 Lisp_Object args[6];
129
130 args[0] = handler;
131 args[1] = Qdirectory_files;
132 args[2] = directory;
133 args[3] = full;
134 args[4] = match;
135 args[5] = nosort;
136 return Ffuncall (6, args);
137 }
138
139 {
140 struct gcpro gcpro1, gcpro2;
141
142 /* Because of file name handlers, these functions might call
143 Ffuncall, and cause a GC. */
144 GCPRO1 (match);
145 directory = Fexpand_file_name (directory, Qnil);
146 UNGCPRO;
147 GCPRO2 (match, directory);
148 dirfilename = Fdirectory_file_name (directory);
149 UNGCPRO;
150 }
151
152 if (!NILP (match))
153 {
154 CHECK_STRING (match, 3);
155
156 /* MATCH might be a flawed regular expression. Rather than
157 catching and signaling our own errors, we just call
158 compile_pattern to do the work for us. */
159 #ifdef VMS
160 bufp = compile_pattern (match, 0,
161 buffer_defaults.downcase_table->contents, 0);
162 #else
163 bufp = compile_pattern (match, 0, 0, 0);
164 #endif
165 }
166
167 /* Now *bufp is the compiled form of MATCH; don't call anything
168 which might compile a new regexp until we're done with the loop! */
169
170 /* Do this opendir after anything which might signal an error; if
171 an error is signaled while the directory stream is open, we
172 have to make sure it gets closed, and setting up an
173 unwind_protect to do so would be a pain. */
174 d = opendir (XSTRING (dirfilename)->data);
175 if (! d)
176 report_file_error ("Opening directory", Fcons (directory, Qnil));
177
178 list = Qnil;
179 dirnamelen = XSTRING (directory)->size;
180
181 /* Loop reading blocks */
182 while (1)
183 {
184 DIRENTRY *dp = readdir (d);
185 int len;
186
187 if (!dp) break;
188 len = NAMLEN (dp);
189 if (DIRENTRY_NONEMPTY (dp))
190 {
191 if (NILP (match)
192 || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0)))
193 {
194 if (!NILP (full))
195 {
196 int afterdirindex = dirnamelen;
197 int total = len + dirnamelen;
198 int needsep = 0;
199
200 /* Decide whether we need to add a directory separator. */
201 #ifndef VMS
202 if (dirnamelen == 0
203 || !IS_ANY_SEP (XSTRING (directory)->data[dirnamelen - 1]))
204 needsep = 1;
205 #endif /* VMS */
206
207 name = make_uninit_string (total + needsep);
208 bcopy (XSTRING (directory)->data, XSTRING (name)->data,
209 dirnamelen);
210 if (needsep)
211 XSTRING (name)->data[afterdirindex++] = DIRECTORY_SEP;
212 bcopy (dp->d_name,
213 XSTRING (name)->data + afterdirindex, len);
214 }
215 else
216 name = make_string (dp->d_name, len);
217 list = Fcons (name, list);
218 }
219 }
220 }
221 closedir (d);
222 if (!NILP (nosort))
223 return list;
224 return Fsort (Fnreverse (list), Qstring_lessp);
225 }
226 \f
227 Lisp_Object file_name_completion ();
228
229 DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
230 2, 2, 0,
231 "Complete file name FILE in directory DIRECTORY.\n\
232 Returns the longest string\n\
233 common to all file names in DIRECTORY that start with FILE.\n\
234 If there is only one and FILE matches it exactly, returns t.\n\
235 Returns nil if DIR contains no name starting with FILE.")
236 (file, directory)
237 Lisp_Object file, directory;
238 {
239 Lisp_Object handler;
240
241 /* If the directory name has special constructs in it,
242 call the corresponding file handler. */
243 handler = Ffind_file_name_handler (directory, Qfile_name_completion);
244 if (!NILP (handler))
245 return call3 (handler, Qfile_name_completion, file, directory);
246
247 /* If the file name has special constructs in it,
248 call the corresponding file handler. */
249 handler = Ffind_file_name_handler (file, Qfile_name_completion);
250 if (!NILP (handler))
251 return call3 (handler, Qfile_name_completion, file, directory);
252
253 return file_name_completion (file, directory, 0, 0);
254 }
255
256 DEFUN ("file-name-all-completions", Ffile_name_all_completions,
257 Sfile_name_all_completions, 2, 2, 0,
258 "Return a list of all completions of file name FILE in directory DIRECTORY.\n\
259 These are all file names in directory DIRECTORY which begin with FILE.")
260 (file, directory)
261 Lisp_Object file, directory;
262 {
263 Lisp_Object handler;
264
265 /* If the directory name has special constructs in it,
266 call the corresponding file handler. */
267 handler = Ffind_file_name_handler (directory, Qfile_name_all_completions);
268 if (!NILP (handler))
269 return call3 (handler, Qfile_name_all_completions, file, directory);
270
271 /* If the file name has special constructs in it,
272 call the corresponding file handler. */
273 handler = Ffind_file_name_handler (file, Qfile_name_all_completions);
274 if (!NILP (handler))
275 return call3 (handler, Qfile_name_all_completions, file, directory);
276
277 return file_name_completion (file, directory, 1, 0);
278 }
279
280 Lisp_Object
281 file_name_completion (file, dirname, all_flag, ver_flag)
282 Lisp_Object file, dirname;
283 int all_flag, ver_flag;
284 {
285 DIR *d;
286 DIRENTRY *dp;
287 int bestmatchsize, skip;
288 register int compare, matchsize;
289 unsigned char *p1, *p2;
290 int matchcount = 0;
291 Lisp_Object bestmatch, tem, elt, name;
292 struct stat st;
293 int directoryp;
294 int passcount;
295 int count = specpdl_ptr - specpdl;
296 struct gcpro gcpro1, gcpro2, gcpro3;
297
298 #ifdef VMS
299 extern DIRENTRY * readdirver ();
300
301 DIRENTRY *((* readfunc) ());
302
303 /* Filename completion on VMS ignores case, since VMS filesys does. */
304 specbind (Qcompletion_ignore_case, Qt);
305
306 readfunc = readdir;
307 if (ver_flag)
308 readfunc = readdirver;
309 file = Fupcase (file);
310 #else /* not VMS */
311 CHECK_STRING (file, 0);
312 #endif /* not VMS */
313
314 #ifdef FILE_SYSTEM_CASE
315 file = FILE_SYSTEM_CASE (file);
316 #endif
317 bestmatch = Qnil;
318 GCPRO3 (file, dirname, bestmatch);
319 dirname = Fexpand_file_name (dirname, Qnil);
320
321 /* With passcount = 0, ignore files that end in an ignored extension.
322 If nothing found then try again with passcount = 1, don't ignore them.
323 If looking for all completions, start with passcount = 1,
324 so always take even the ignored ones.
325
326 ** It would not actually be helpful to the user to ignore any possible
327 completions when making a list of them.** */
328
329 for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++)
330 {
331 if (!(d = opendir (XSTRING (Fdirectory_file_name (dirname))->data)))
332 report_file_error ("Opening directory", Fcons (dirname, Qnil));
333
334 /* Loop reading blocks */
335 /* (att3b compiler bug requires do a null comparison this way) */
336 while (1)
337 {
338 DIRENTRY *dp;
339 int len;
340
341 #ifdef VMS
342 dp = (*readfunc) (d);
343 #else
344 dp = readdir (d);
345 #endif
346 if (!dp) break;
347
348 len = NAMLEN (dp);
349
350 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
351 goto quit;
352 if (! DIRENTRY_NONEMPTY (dp)
353 || len < XSTRING (file)->size
354 || 0 <= scmp (dp->d_name, XSTRING (file)->data,
355 XSTRING (file)->size))
356 continue;
357
358 if (file_name_completion_stat (dirname, dp, &st) < 0)
359 continue;
360
361 directoryp = ((st.st_mode & S_IFMT) == S_IFDIR);
362 tem = Qnil;
363 if (directoryp)
364 {
365 #ifndef TRIVIAL_DIRECTORY_ENTRY
366 #define TRIVIAL_DIRECTORY_ENTRY(n) (!strcmp (n, ".") || !strcmp (n, ".."))
367 #endif
368 /* "." and ".." are never interesting as completions, but are
369 actually in the way in a directory contains only one file. */
370 if (!passcount && TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
371 continue;
372 }
373 else
374 {
375 /* Compare extensions-to-be-ignored against end of this file name */
376 /* if name is not an exact match against specified string */
377 if (!passcount && len > XSTRING (file)->size)
378 /* and exit this for loop if a match is found */
379 for (tem = Vcompletion_ignored_extensions;
380 CONSP (tem); tem = XCONS (tem)->cdr)
381 {
382 elt = XCONS (tem)->car;
383 if (!STRINGP (elt)) continue;
384 skip = len - XSTRING (elt)->size;
385 if (skip < 0) continue;
386
387 if (0 <= scmp (dp->d_name + skip,
388 XSTRING (elt)->data,
389 XSTRING (elt)->size))
390 continue;
391 break;
392 }
393 }
394
395 /* If an ignored-extensions match was found,
396 don't process this name as a completion. */
397 if (!passcount && CONSP (tem))
398 continue;
399
400 if (!passcount)
401 {
402 Lisp_Object regexps;
403 Lisp_Object zero;
404 XSETFASTINT (zero, 0);
405
406 /* Ignore this element if it fails to match all the regexps. */
407 for (regexps = Vcompletion_regexp_list; CONSP (regexps);
408 regexps = XCONS (regexps)->cdr)
409 {
410 tem = Fstring_match (XCONS (regexps)->car, elt, zero);
411 if (NILP (tem))
412 break;
413 }
414 if (CONSP (regexps))
415 continue;
416 }
417
418 /* Update computation of how much all possible completions match */
419
420 matchcount++;
421
422 if (all_flag || NILP (bestmatch))
423 {
424 /* This is a possible completion */
425 if (directoryp)
426 {
427 /* This completion is a directory; make it end with '/' */
428 name = Ffile_name_as_directory (make_string (dp->d_name, len));
429 }
430 else
431 name = make_string (dp->d_name, len);
432 if (all_flag)
433 {
434 bestmatch = Fcons (name, bestmatch);
435 }
436 else
437 {
438 bestmatch = name;
439 bestmatchsize = XSTRING (name)->size;
440 }
441 }
442 else
443 {
444 compare = min (bestmatchsize, len);
445 p1 = XSTRING (bestmatch)->data;
446 p2 = (unsigned char *) dp->d_name;
447 matchsize = scmp(p1, p2, compare);
448 if (matchsize < 0)
449 matchsize = compare;
450 if (completion_ignore_case)
451 {
452 /* If this is an exact match except for case,
453 use it as the best match rather than one that is not
454 an exact match. This way, we get the case pattern
455 of the actual match. */
456 if ((matchsize == len
457 && matchsize + !!directoryp
458 < XSTRING (bestmatch)->size)
459 ||
460 /* If there is no exact match ignoring case,
461 prefer a match that does not change the case
462 of the input. */
463 (((matchsize == len)
464 ==
465 (matchsize + !!directoryp
466 == XSTRING (bestmatch)->size))
467 /* If there is more than one exact match aside from
468 case, and one of them is exact including case,
469 prefer that one. */
470 && !bcmp (p2, XSTRING (file)->data, XSTRING (file)->size)
471 && bcmp (p1, XSTRING (file)->data, XSTRING (file)->size)))
472 {
473 bestmatch = make_string (dp->d_name, len);
474 if (directoryp)
475 bestmatch = Ffile_name_as_directory (bestmatch);
476 }
477 }
478
479 /* If this dirname all matches, see if implicit following
480 slash does too. */
481 if (directoryp
482 && compare == matchsize
483 && bestmatchsize > matchsize
484 && IS_ANY_SEP (p1[matchsize]))
485 matchsize++;
486 bestmatchsize = matchsize;
487 }
488 }
489 closedir (d);
490 }
491
492 UNGCPRO;
493 bestmatch = unbind_to (count, bestmatch);
494
495 if (all_flag || NILP (bestmatch))
496 return bestmatch;
497 if (matchcount == 1 && bestmatchsize == XSTRING (file)->size)
498 return Qt;
499 return Fsubstring (bestmatch, make_number (0), make_number (bestmatchsize));
500 quit:
501 if (d) closedir (d);
502 Vquit_flag = Qnil;
503 return Fsignal (Qquit, Qnil);
504 }
505
506 file_name_completion_stat (dirname, dp, st_addr)
507 Lisp_Object dirname;
508 DIRENTRY *dp;
509 struct stat *st_addr;
510 {
511 int len = NAMLEN (dp);
512 int pos = XSTRING (dirname)->size;
513 int value;
514 char *fullname = (char *) alloca (len + pos + 2);
515
516 bcopy (XSTRING (dirname)->data, fullname, pos);
517 #ifndef VMS
518 if (!IS_DIRECTORY_SEP (fullname[pos - 1]))
519 fullname[pos++] = DIRECTORY_SEP;
520 #endif
521
522 bcopy (dp->d_name, fullname + pos, len);
523 fullname[pos + len] = 0;
524
525 #ifdef S_IFLNK
526 /* We want to return success if a link points to a nonexistent file,
527 but we want to return the status for what the link points to,
528 in case it is a directory. */
529 value = lstat (fullname, st_addr);
530 stat (fullname, st_addr);
531 return value;
532 #else
533 return stat (fullname, st_addr);
534 #endif
535 }
536 \f
537 #ifdef VMS
538
539 DEFUN ("file-name-all-versions", Ffile_name_all_versions,
540 Sfile_name_all_versions, 2, 2, 0,
541 "Return a list of all versions of file name FILE in directory DIRECTORY.")
542 (file, directory)
543 Lisp_Object file, directory;
544 {
545 return file_name_completion (file, directory, 1, 1);
546 }
547
548 DEFUN ("file-version-limit", Ffile_version_limit, Sfile_version_limit, 1, 1, 0,
549 "Return the maximum number of versions allowed for FILE.\n\
550 Returns nil if the file cannot be opened or if there is no version limit.")
551 (filename)
552 Lisp_Object filename;
553 {
554 Lisp_Object retval;
555 struct FAB fab;
556 struct RAB rab;
557 struct XABFHC xabfhc;
558 int status;
559
560 filename = Fexpand_file_name (filename, Qnil);
561 fab = cc$rms_fab;
562 xabfhc = cc$rms_xabfhc;
563 fab.fab$l_fna = XSTRING (filename)->data;
564 fab.fab$b_fns = strlen (fab.fab$l_fna);
565 fab.fab$l_xab = (char *) &xabfhc;
566 status = sys$open (&fab, 0, 0);
567 if (status != RMS$_NORMAL) /* Probably non-existent file */
568 return Qnil;
569 sys$close (&fab, 0, 0);
570 if (xabfhc.xab$w_verlimit == 32767)
571 return Qnil; /* No version limit */
572 else
573 return make_number (xabfhc.xab$w_verlimit);
574 }
575
576 #endif /* VMS */
577 \f
578 Lisp_Object
579 make_time (time)
580 int time;
581 {
582 return Fcons (make_number (time >> 16),
583 Fcons (make_number (time & 0177777), Qnil));
584 }
585
586 DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 1, 0,
587 "Return a list of attributes of file FILENAME.\n\
588 Value is nil if specified file cannot be opened.\n\
589 Otherwise, list elements are:\n\
590 0. t for directory, string (name linked to) for symbolic link, or nil.\n\
591 1. Number of links to file.\n\
592 2. File uid.\n\
593 3. File gid.\n\
594 4. Last access time, as a list of two integers.\n\
595 First integer has high-order 16 bits of time, second has low 16 bits.\n\
596 5. Last modification time, likewise.\n\
597 6. Last status change time, likewise.\n\
598 7. Size in bytes (-1, if number is out of range).\n\
599 8. File modes, as a string of ten letters or dashes as in ls -l.\n\
600 9. t iff file's gid would change if file were deleted and recreated.\n\
601 10. inode number.\n\
602 11. Device number.\n\
603 \n\
604 If file does not exist, returns nil.")
605 (filename)
606 Lisp_Object filename;
607 {
608 Lisp_Object values[12];
609 Lisp_Object dirname;
610 struct stat s;
611 struct stat sdir;
612 char modes[10];
613 Lisp_Object handler;
614
615 filename = Fexpand_file_name (filename, Qnil);
616
617 /* If the file name has special constructs in it,
618 call the corresponding file handler. */
619 handler = Ffind_file_name_handler (filename, Qfile_attributes);
620 if (!NILP (handler))
621 return call2 (handler, Qfile_attributes, filename);
622
623 if (lstat (XSTRING (filename)->data, &s) < 0)
624 return Qnil;
625
626 switch (s.st_mode & S_IFMT)
627 {
628 default:
629 values[0] = Qnil; break;
630 case S_IFDIR:
631 values[0] = Qt; break;
632 #ifdef S_IFLNK
633 case S_IFLNK:
634 values[0] = Ffile_symlink_p (filename); break;
635 #endif
636 }
637 values[1] = make_number (s.st_nlink);
638 values[2] = make_number (s.st_uid);
639 values[3] = make_number (s.st_gid);
640 values[4] = make_time (s.st_atime);
641 values[5] = make_time (s.st_mtime);
642 values[6] = make_time (s.st_ctime);
643 values[7] = make_number ((int) s.st_size);
644 /* If the size is out of range, give back -1. */
645 if (XINT (values[7]) != s.st_size)
646 XSETINT (values[7], -1);
647 filemodestring (&s, modes);
648 values[8] = make_string (modes, 10);
649 #ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */
650 #define BSD4_2 /* A new meaning to the term `backwards compatibility' */
651 #endif
652 #ifdef BSD4_2 /* file gid will be dir gid */
653 dirname = Ffile_name_directory (filename);
654 if (! NILP (dirname) && stat (XSTRING (dirname)->data, &sdir) == 0)
655 values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil;
656 else /* if we can't tell, assume worst */
657 values[9] = Qt;
658 #else /* file gid will be egid */
659 #ifdef WINDOWSNT
660 values[9] = Qnil; /* sorry, no group IDs on NT */
661 #else /* not WINDOWSNT */
662 values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
663 #endif /* not WINDOWSNT */
664 #endif /* BSD4_2 (or BSD4_3) */
665 #ifdef BSD4_3
666 #undef BSD4_2 /* ok, you can look again without throwing up */
667 #endif
668 #ifdef WINDOWSNT
669 /* Fill in the inode and device values specially...see nt.c. */
670 if (!get_inode_and_device_vals (filename, &values[10], &values[11])) {
671 return Qnil;
672 }
673 #else /* not WINDOWSNT */
674 values[10] = make_number (s.st_ino);
675 values[11] = make_number (s.st_dev);
676 #endif /* not WINDOWSNT */
677 return Flist (sizeof(values) / sizeof(values[0]), values);
678 }
679 \f
680 syms_of_dired ()
681 {
682 Qdirectory_files = intern ("directory-files");
683 Qfile_name_completion = intern ("file-name-completion");
684 Qfile_name_all_completions = intern ("file-name-all-completions");
685 Qfile_attributes = intern ("file-attributes");
686
687 defsubr (&Sdirectory_files);
688 defsubr (&Sfile_name_completion);
689 #ifdef VMS
690 defsubr (&Sfile_name_all_versions);
691 defsubr (&Sfile_version_limit);
692 #endif /* VMS */
693 defsubr (&Sfile_name_all_completions);
694 defsubr (&Sfile_attributes);
695
696 #ifdef VMS
697 Qcompletion_ignore_case = intern ("completion-ignore-case");
698 staticpro (&Qcompletion_ignore_case);
699 #endif /* VMS */
700
701 DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions,
702 "*Completion ignores filenames ending in any string in this list.\n\
703 This variable does not affect lists of possible completions,\n\
704 but does affect the commands that actually do completions.");
705 Vcompletion_ignored_extensions = Qnil;
706 }