comparison src/fileio.c @ 90133:4da4a09e8b1b

Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-31 Merge from emacs--cvs-trunk--0 Patches applied: * emacs--cvs-trunk--0 (patch 206-222) - Update from CVS - Merge from gnus--rel--5.10 * gnus--rel--5.10 (patch 45-52) - Update from CVS - Update from CVS: texi Makefile.in CVS keyw cruft - Update from CVS: ChangeLog tweaks
author Miles Bader <miles@gnu.org>
date Thu, 31 Mar 2005 09:58:14 +0000
parents 30ad2795fdab be58652085b8
children e1fbb019c538
comparison
equal deleted inserted replaced
90132:4080fe8b4f0f 90133:4da4a09e8b1b
1016 1016
1017 1017
1018 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, 1018 DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
1019 doc: /* Convert filename NAME to absolute, and canonicalize it. 1019 doc: /* Convert filename NAME to absolute, and canonicalize it.
1020 Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative 1020 Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative
1021 (does not start with slash); if DEFAULT-DIRECTORY is nil or missing, 1021 \(does not start with slash); if DEFAULT-DIRECTORY is nil or missing,
1022 the current buffer's value of default-directory is used. 1022 the current buffer's value of default-directory is used.
1023 File name components that are `.' are removed, and 1023 File name components that are `.' are removed, and
1024 so are file name components followed by `..', along with the `..' itself; 1024 so are file name components followed by `..', along with the `..' itself;
1025 note that these simplifications are done without checking the resulting 1025 note that these simplifications are done without checking the resulting
1026 file names in the file system. 1026 file names in the file system.
1466 Because of the admonition against calling expand-file-name 1466 Because of the admonition against calling expand-file-name
1467 when we have pointers into lisp strings, we accomplish this 1467 when we have pointers into lisp strings, we accomplish this
1468 indirectly by prepending newdir to nm if necessary, and using 1468 indirectly by prepending newdir to nm if necessary, and using
1469 cwd (or the wd of newdir's drive) as the new newdir. */ 1469 cwd (or the wd of newdir's drive) as the new newdir. */
1470 1470
1471 if (IS_DRIVE (newdir[0]) && newdir[1] == ':') 1471 if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
1472 { 1472 {
1473 drive = newdir[0]; 1473 drive = newdir[0];
1474 newdir += 2; 1474 newdir += 2;
1475 } 1475 }
1476 if (!IS_DIRECTORY_SEP (nm[0])) 1476 if (!IS_DIRECTORY_SEP (nm[0]))
1489 else 1489 else
1490 getwd (newdir); 1490 getwd (newdir);
1491 } 1491 }
1492 1492
1493 /* Strip off drive name from prefix, if present. */ 1493 /* Strip off drive name from prefix, if present. */
1494 if (IS_DRIVE (newdir[0]) && newdir[1] == ':') 1494 if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
1495 { 1495 {
1496 drive = newdir[0]; 1496 drive = newdir[0];
1497 newdir += 2; 1497 newdir += 2;
1498 } 1498 }
1499 1499
1723 1723
1724 /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'. */ 1724 /* Changed this DEFUN to a DEAFUN, so as not to confuse `make-docfile'. */
1725 DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, 1725 DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
1726 "Convert FILENAME to absolute, and canonicalize it.\n\ 1726 "Convert FILENAME to absolute, and canonicalize it.\n\
1727 Second arg DEFAULT is directory to start with if FILENAME is relative\n\ 1727 Second arg DEFAULT is directory to start with if FILENAME is relative\n\
1728 (does not start with slash); if DEFAULT is nil or missing,\n\ 1728 \(does not start with slash); if DEFAULT is nil or missing,\n\
1729 the current buffer's value of default-directory is used.\n\ 1729 the current buffer's value of default-directory is used.\n\
1730 Filenames containing `.' or `..' as components are simplified;\n\ 1730 Filenames containing `.' or `..' as components are simplified;\n\
1731 initial `~/' expands to your home directory.\n\ 1731 initial `~/' expands to your home directory.\n\
1732 See also the function `substitute-in-file-name'.") 1732 See also the function `substitute-in-file-name'.")
1733 (name, defalt) 1733 (name, defalt)
2042 2042
2043 return make_string (target, o - target); 2043 return make_string (target, o - target);
2044 } 2044 }
2045 #endif 2045 #endif
2046 2046
2047 /* If /~ or // appears, discard everything through first slash. */
2048 static int
2049 file_name_absolute_p (filename)
2050 const unsigned char *filename;
2051 {
2052 return
2053 (IS_DIRECTORY_SEP (*filename) || *filename == '~'
2054 #ifdef VMS
2055 /* ??? This criterion is probably wrong for '<'. */
2056 || index (filename, ':') || index (filename, '<')
2057 || (*filename == '[' && (filename[1] != '-'
2058 || (filename[2] != '.' && filename[2] != ']'))
2059 && filename[1] != '.')
2060 #endif /* VMS */
2061 #ifdef DOS_NT
2062 || (IS_DRIVE (*filename) && IS_DEVICE_SEP (filename[1])
2063 && IS_DIRECTORY_SEP (filename[2]))
2064 #endif
2065 );
2066 }
2067
2068 static unsigned char *
2069 search_embedded_absfilename (nm, endp)
2070 unsigned char *nm, *endp;
2071 {
2072 unsigned char *p, *s;
2073
2074 for (p = nm + 1; p < endp; p++)
2075 {
2076 if ((0
2077 #ifdef VMS
2078 || p[-1] == ':' || p[-1] == ']' || p[-1] == '>'
2079 #endif /* VMS */
2080 || IS_DIRECTORY_SEP (p[-1]))
2081 && file_name_absolute_p (p)
2082 #if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN)
2083 /* // at start of file name is meaningful in Apollo,
2084 WindowsNT and Cygwin systems. */
2085 && !(IS_DIRECTORY_SEP (p[0]) && p - 1 == nm)
2086 #endif /* not (APOLLO || WINDOWSNT || CYGWIN) */
2087 )
2088 {
2089 for (s = p; *s && (!IS_DIRECTORY_SEP (*s)
2090 #ifdef VMS
2091 && *s != ':'
2092 #endif /* VMS */
2093 ); s++);
2094 if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */
2095 {
2096 unsigned char *o = alloca (s - p + 1);
2097 struct passwd *pw;
2098 bcopy (p, o, s - p);
2099 o [s - p] = 0;
2100
2101 /* If we have ~user and `user' exists, discard
2102 everything up to ~. But if `user' does not exist, leave
2103 ~user alone, it might be a literal file name. */
2104 if ((pw = getpwnam (o + 1)))
2105 return p;
2106 else
2107 xfree (pw);
2108 }
2109 else
2110 return p;
2111 }
2112 }
2113 return NULL;
2114 }
2115
2047 DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name, 2116 DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name,
2048 Ssubstitute_in_file_name, 1, 1, 0, 2117 Ssubstitute_in_file_name, 1, 1, 0,
2049 doc: /* Substitute environment variables referred to in FILENAME. 2118 doc: /* Substitute environment variables referred to in FILENAME.
2050 `$FOO' where FOO is an environment variable name means to substitute 2119 `$FOO' where FOO is an environment variable name means to substitute
2051 the value of that variable. The variable name should be terminated 2120 the value of that variable. The variable name should be terminated
2063 register unsigned char *s, *p, *o, *x, *endp; 2132 register unsigned char *s, *p, *o, *x, *endp;
2064 unsigned char *target = NULL; 2133 unsigned char *target = NULL;
2065 int total = 0; 2134 int total = 0;
2066 int substituted = 0; 2135 int substituted = 0;
2067 unsigned char *xnm; 2136 unsigned char *xnm;
2068 struct passwd *pw;
2069 Lisp_Object handler; 2137 Lisp_Object handler;
2070 2138
2071 CHECK_STRING (filename); 2139 CHECK_STRING (filename);
2072 2140
2073 /* If the file name has special constructs in it, 2141 /* If the file name has special constructs in it,
2083 substituted = (strcmp (nm, SDATA (filename)) != 0); 2151 substituted = (strcmp (nm, SDATA (filename)) != 0);
2084 #endif 2152 #endif
2085 endp = nm + SBYTES (filename); 2153 endp = nm + SBYTES (filename);
2086 2154
2087 /* If /~ or // appears, discard everything through first slash. */ 2155 /* If /~ or // appears, discard everything through first slash. */
2088 2156 p = search_embedded_absfilename (nm, endp);
2089 for (p = nm; p != endp; p++) 2157 if (p)
2090 { 2158 /* Start over with the new string, so we check the file-name-handler
2091 if ((p[0] == '~' 2159 again. Important with filenames like "/home/foo//:/hello///there"
2092 #if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN) 2160 which whould substitute to "/:/hello///there" rather than "/there". */
2093 /* // at start of file name is meaningful in Apollo, 2161 return Fsubstitute_in_file_name
2094 WindowsNT and Cygwin systems. */ 2162 (make_specified_string (p, -1, endp - p,
2095 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm) 2163 STRING_MULTIBYTE (filename)));
2096 #else /* not (APOLLO || WINDOWSNT || CYGWIN) */ 2164
2097 || IS_DIRECTORY_SEP (p[0])
2098 #endif /* not (APOLLO || WINDOWSNT || CYGWIN) */
2099 )
2100 && p != nm
2101 && (0
2102 #ifdef VMS 2165 #ifdef VMS
2103 || p[-1] == ':' || p[-1] == ']' || p[-1] == '>' 2166 return filename;
2104 #endif /* VMS */
2105 || IS_DIRECTORY_SEP (p[-1])))
2106 {
2107 for (s = p; *s && (!IS_DIRECTORY_SEP (*s)
2108 #ifdef VMS
2109 && *s != ':'
2110 #endif /* VMS */
2111 ); s++);
2112 if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */
2113 {
2114 o = (unsigned char *) alloca (s - p + 1);
2115 bcopy ((char *) p, o, s - p);
2116 o [s - p] = 0;
2117
2118 pw = (struct passwd *) getpwnam (o + 1);
2119 }
2120 /* If we have ~/ or ~user and `user' exists, discard
2121 everything up to ~. But if `user' does not exist, leave
2122 ~user alone, it might be a literal file name. */
2123 if (IS_DIRECTORY_SEP (p[0]) || s == p + 1 || pw)
2124 {
2125 nm = p;
2126 substituted = 1;
2127 }
2128 }
2129 #ifdef DOS_NT
2130 /* see comment in expand-file-name about drive specifiers */
2131 else if (IS_DRIVE (p[0]) && p[1] == ':'
2132 && p > nm && IS_DIRECTORY_SEP (p[-1]))
2133 {
2134 nm = p;
2135 substituted = 1;
2136 }
2137 #endif /* DOS_NT */
2138 }
2139
2140 #ifdef VMS
2141 return make_specified_string (nm, -1, strlen (nm),
2142 STRING_MULTIBYTE (filename));
2143 #else 2167 #else
2144 2168
2145 /* See if any variables are substituted into the string 2169 /* See if any variables are substituted into the string
2146 and find the total length of their values in `total' */ 2170 and find the total length of their values in `total' */
2147 2171
2264 } 2288 }
2265 2289
2266 *x = 0; 2290 *x = 0;
2267 2291
2268 /* If /~ or // appears, discard everything through first slash. */ 2292 /* If /~ or // appears, discard everything through first slash. */
2269 2293 while ((p = search_embedded_absfilename (xnm, x)))
2270 for (p = xnm; p != x; p++) 2294 /* This time we do not start over because we've already expanded envvars
2271 if ((p[0] == '~' 2295 and replaced $$ with $. Maybe we should start over as well, but we'd
2272 #if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN) 2296 need to quote some $ to $$ first. */
2273 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm) 2297 xnm = p;
2274 #else /* not (APOLLO || WINDOWSNT || CYGWIN) */
2275 || IS_DIRECTORY_SEP (p[0])
2276 #endif /* not (APOLLO || WINDOWSNT || CYGWIN) */
2277 )
2278 && p != xnm && IS_DIRECTORY_SEP (p[-1]))
2279 xnm = p;
2280 #ifdef DOS_NT
2281 else if (IS_DRIVE (p[0]) && p[1] == ':'
2282 && p > xnm && IS_DIRECTORY_SEP (p[-1]))
2283 xnm = p;
2284 #endif
2285 2298
2286 return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename)); 2299 return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename));
2287 2300
2288 badsubst: 2301 badsubst:
2289 error ("Bad format environment-variable substitution"); 2302 error ("Bad format environment-variable substitution");
2962 doc: /* Return t if file FILENAME specifies an absolute file name. 2975 doc: /* Return t if file FILENAME specifies an absolute file name.
2963 On Unix, this is a name starting with a `/' or a `~'. */) 2976 On Unix, this is a name starting with a `/' or a `~'. */)
2964 (filename) 2977 (filename)
2965 Lisp_Object filename; 2978 Lisp_Object filename;
2966 { 2979 {
2967 const unsigned char *ptr;
2968
2969 CHECK_STRING (filename); 2980 CHECK_STRING (filename);
2970 ptr = SDATA (filename); 2981 return file_name_absolute_p (SDATA (filename)) ? Qt : Qnil;
2971 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
2972 #ifdef VMS
2973 /* ??? This criterion is probably wrong for '<'. */
2974 || index (ptr, ':') || index (ptr, '<')
2975 || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']'))
2976 && ptr[1] != '.')
2977 #endif /* VMS */
2978 #ifdef DOS_NT
2979 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
2980 #endif
2981 )
2982 return Qt;
2983 else
2984 return Qnil;
2985 } 2982 }
2986 2983
2987 /* Return nonzero if file FILENAME exists and can be executed. */ 2984 /* Return nonzero if file FILENAME exists and can be executed. */
2988 2985
2989 static int 2986 static int