summaryrefslogtreecommitdiffstats
path: root/dln.c
diff options
context:
space:
mode:
Diffstat (limited to 'dln.c')
-rw-r--r--dln.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/dln.c b/dln.c
index bb64c52a0..d3408fb0f 100644
--- a/dln.c
+++ b/dln.c
@@ -1518,28 +1518,70 @@ dln_find_1(const char *fname, const char *path, char *fbuf, int size,
register const char *ep;
register char *bp;
struct stat st;
+ int i, fspace;
+#ifdef DOSISH
+ int is_abs = 0, has_path = 0, has_ext = 0;
+ const char *p = fname;
+#endif
#define RETURN_IF(expr) if (expr) return (char *)fname;
RETURN_IF(!fname);
- RETURN_IF(fname[0] == '/');
- RETURN_IF(strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0);
- RETURN_IF(exe_flag && strchr(fname, '/'));
#ifdef DOSISH
- RETURN_IF(fname[0] == '\\');
+# ifndef CharNext
+# define CharNext(p) ((p)+1)
+# endif
# ifdef DOSISH_DRIVE_LETTER
- RETURN_IF(strlen(fname) > 2 && fname[1] == ':');
+ if (((p[0] | 0x20) - 'a') < 26 && p[1] == ':') {
+ p += 2;
+ is_abs = 1;
+ }
# endif
- RETURN_IF(strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0);
- RETURN_IF(exe_flag && strchr(fname, '\\'));
+ switch (*p) {
+ case '/': case '\\':
+ is_abs = 1;
+ p++;
+ }
+ has_path = is_abs;
+ while (*p) {
+ switch (*p) {
+ case '/': case '\\':
+ has_path = 1;
+ has_ext = 0;
+ p++;
+ break;
+ case '.':
+ has_ext = 1;
+ p++;
+ break;
+ default:
+ p = CharNext(p);
+ }
+ }
+ ep = bp = 0;
+ if (!exe_flag) {
+ RETURN_IF(is_abs);
+ }
+ else if (has_path) {
+ RETURN_IF(has_ext);
+ i = p - fname;
+ if (i + 1 > size) goto toolong;
+ fspace = size - i - 1;
+ bp = fbuf;
+ ep = p;
+ memcpy(fbuf, fname, i + 1);
+ goto needs_extension;
+ }
#endif
+ RETURN_IF(fname[0] == '/');
+ RETURN_IF(strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0);
+ RETURN_IF(exe_flag && strchr(fname, '/'));
+
#undef RETURN_IF
for (dp = path;; dp = ++ep) {
register int l;
- int i;
- int fspace;
/* extract a component */
ep = strchr(dp, PATH_SEP[0]);
@@ -1602,7 +1644,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, int size,
memcpy(bp, fname, i + 1);
#if defined(DOSISH)
- if (exe_flag) {
+ if (exe_flag && !has_ext) {
static const char extension[][5] = {
#if defined(__EMX__) || defined(_WIN32)
".exe", ".com", ".cmd", ".bat",
@@ -1611,6 +1653,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, int size,
};
int j;
+ needs_extension:
for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
if (fspace < strlen(extension[j])) {
fprintf(stderr, "openpath: pathname too long (ignored)\n");