Mercurial > emacs
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 |