diff options
author | Jim Blandy <jimb@red-bean.com> | 1999-09-03 07:54:06 +0000 |
---|---|---|
committer | Jim Blandy <jimb@red-bean.com> | 1999-09-03 07:54:06 +0000 |
commit | 563841768b8659dad87296be4ae9ce589cbe99d4 (patch) | |
tree | 02abd7a7c4831f6bc3a19871968b30d3d1e400d3 /libguile/load.c | |
parent | 513571767f87d0564d1466e68d42efb28ea04cd9 (diff) | |
download | guile-563841768b8659dad87296be4ae9ce589cbe99d4.tar.gz |
* load.c (scm_search_path): If the filename has any extension at
all, ignore the entire list of extensions. Also, don't check whether
the file is accessible. If the file exists, accessible or not, we
should return it. Inaccessible files should cause an error later.
(Thanks to Keisuke Nishida for the suggestions.)
Diffstat (limited to 'libguile/load.c')
-rw-r--r-- | libguile/load.c | 145 |
1 files changed, 84 insertions, 61 deletions
diff --git a/libguile/load.c b/libguile/load.c index bfe9fa410..6650837c9 100644 --- a/libguile/load.c +++ b/libguile/load.c @@ -213,7 +213,9 @@ SCM scm_listofnullstr; /* Search PATH for a directory containing a file named FILENAME. The file must be readable, and not a directory. If we find one, return its full filename; otherwise, return #f. - If FILENAME is absolute, return it unchanged. */ + If FILENAME is absolute, return it unchanged. + If given, EXTENSIONS is a list of strings; for each directory + in PATH, we search for FILENAME concatenated with each EXTENSION. */ SCM_PROC(s_search_path, "search-path", 2, 1, 0, scm_search_path); SCM scm_search_path (path, filename, extensions) @@ -221,25 +223,25 @@ scm_search_path (path, filename, extensions) SCM filename; SCM extensions; { - char *buf, *endp; + char *filename_chars; int filename_len; - size_t max_path_len; - size_t max_ext_len; - SCM result = SCM_BOOL_F; + size_t max_path_len; /* maximum length of any PATH element */ + size_t max_ext_len; /* maximum length of any EXTENSIONS element */ SCM_ASSERT (scm_ilength (path) >= 0, path, SCM_ARG1, s_search_path); SCM_ASSERT (SCM_NIMP (filename) && SCM_ROSTRINGP (filename), filename, SCM_ARG2, s_search_path); if (SCM_UNBNDP (extensions)) - extensions = scm_listofnullstr; + extensions = SCM_EOL; else SCM_ASSERT (scm_ilength (extensions) >= 0, extensions, SCM_ARG3, s_search_path); + + filename_chars = SCM_ROCHARS (filename); filename_len = SCM_ROLENGTH (filename); /* If FILENAME is absolute, return it unchanged. */ - if (filename_len >= 1 - && SCM_ROCHARS (filename)[0] == '/') + if (filename_len >= 1 && filename_chars[0] == '/') return filename; /* Find the length of the longest element of path. */ @@ -258,6 +260,28 @@ scm_search_path (path, filename, extensions) } } + /* If FILENAME has an extension, don't try to add EXTENSIONS to it. */ + { + char *endp; + + for (endp = filename_chars + filename_len - 1; + endp >= filename_chars; + endp--) + { + if (*endp == '.') + { + /* This filename already has an extension, so cancel the + list of extensions. */ + extensions = SCM_EOL; + break; + } + else if (*endp == '/') + /* This filename has no extension, so keep the current list + of extensions. */ + break; + } + } + /* Find the length of the longest element of the load extensions list. */ { @@ -275,63 +299,62 @@ scm_search_path (path, filename, extensions) } } - /* Remove the same extension that FILENAME already has. */ - for (endp = SCM_ROCHARS (filename) + filename_len - 1; - endp > SCM_ROCHARS (filename) && *endp != '/'; endp--) - if (*endp == '.') - { - extensions = scm_delete (scm_makfromstr (endp, SCM_ROCHARS (filename) - + filename_len - endp, 0), - extensions); - break; - } - SCM_DEFER_INTS; - buf = scm_must_malloc (max_path_len + 1 + filename_len + max_ext_len + 1, - s_search_path); + { + SCM result = SCM_BOOL_F; + int buf_size = max_path_len + 1 + filename_len + max_ext_len + 1; + char *buf = scm_must_malloc (buf_size, s_search_path); - /* Try every path element. At this point, we know it's a proper - list of strings. */ - for (; SCM_NIMP (path); path = SCM_CDR (path)) - { - int len; - SCM dir = SCM_CAR (path), exts; - - /* Concatenate the path name and the filename. */ - len = SCM_ROLENGTH (dir); - memcpy (buf, SCM_ROCHARS (dir), len); - if (len >= 1 && buf[len - 1] != '/') - buf[len++] = '/'; - memcpy (buf + len, SCM_ROCHARS (filename), filename_len); - endp = buf + len + filename_len; - - /* Try every extension. At this point, we know it's a proper - list of strings. */ - for (exts = extensions; SCM_NIMP (exts); exts = SCM_CDR (exts)) - { - SCM ext = SCM_CAR (exts); - struct stat mode; - - /* Concatenate the extension. */ - len = SCM_ROLENGTH (ext); - memcpy (endp, SCM_ROCHARS (ext), len); - *(endp + len) = '\0'; - - if (stat (buf, &mode) == 0 - && ! (mode.st_mode & S_IFDIR) - && access (buf, R_OK) == 0) - { - result = scm_makfromstr (buf, endp + len - buf, 0); - goto end; - } - } - } + /* This simplifies the loop below a bit. */ + if (SCM_NULLP (extensions)) + extensions = scm_listofnullstr; - end: - scm_must_free (buf); - SCM_ALLOW_INTS; - return result; + /* Try every path element. At this point, we know the path is a + proper list of strings. */ + for (; SCM_NIMP (path); path = SCM_CDR (path)) + { + int len; + SCM dir = SCM_CAR (path); + SCM exts; + + /* Concatenate the path name and the filename. */ + len = SCM_ROLENGTH (dir); + memcpy (buf, SCM_ROCHARS (dir), len); + if (len >= 1 && buf[len - 1] != '/') + buf[len++] = '/'; + memcpy (buf + len, filename_chars, filename_len); + len += filename_len; + + /* Try every extension. At this point, we know the extension + list is a proper, nonempty list of strings. */ + for (exts = extensions; SCM_NIMP (exts); exts = SCM_CDR (exts)) + { + SCM ext = SCM_CAR (exts); + int ext_len = SCM_ROLENGTH (ext); + struct stat mode; + + /* Concatenate the extension. */ + memcpy (buf + len, SCM_ROCHARS (ext), ext_len); + buf[len + ext_len] = '\0'; + + /* If the file exists at all, we should return it. If the + file is inaccessible, then that's an error. */ + if (stat (buf, &mode) == 0 + && ! (mode.st_mode & S_IFDIR)) + { + result = scm_makfromstr (buf, len + ext_len, 0); + goto end; + } + } + } + + end: + scm_must_free (buf); + scm_done_malloc (- buf_size); + SCM_ALLOW_INTS; + return result; + } } |