Skip to content

Commit

Permalink
make WIN32 file/dirname comparison in relativeFilename case-insensitive
Browse files Browse the repository at this point in the history
Issue

Running recent https://github.com/universal-ctags/ctags-win32/releases
builds including ctags-2018-09-25_619a6fac-x64

* on Windows 10 (x64), I observe that ctags writes tag (output) file
  having input fields containing absolute file paths, and
* on Windows 8.1 (x64), running the same binary, tag file input fields
  contain relative paths (which is IMO correct/documented behavior).

This behavior occurs with --tag-relative=yes and --tag-relative=always.

Diagnosis

(using MinGW builds of current master branch) showed that getcwd function
called by setCurrentDirectory is returning a lowercase drive-letter on
Win10, and a uppercase drive-letter on Win8.1 (I can think of no
explanation for this behavior, as I assume this routine is statically
linked into ctags.exe; while diagnosing this issue I copied locally-built
MinGW ctags.exe binaries from Win10 to Win8.1 host and observed same
results as when using the ctags-win32/releases builds per above).

The existing ctags function relativeFilename (case-sensitively) compares
this (setCurrentDirectory) value against the output of
absoluteFilename( tagfile-name ) in order to determine the relative path;
this comparison fails if there is a mismatch on the 0th character (in
WIN32 this is the drive-letter); absoluteFilename contains WIN32-specific
code that forces the drive-letter of its return value to uppercase,
causing its output to match the (uppercase) drive-letter of Win8.1
setCurrentDirectory value (allowing a common path-prefix to be detected,
and a valid relative path constructed), but to always mismatch the
(lowercase) drive-letter of Win10 setCurrentDirectory value (preventing
construction of a relative path, the issue).

Offered Fix

Because I wish to avoid falling into the tarpit of adding more/competing
code to ensure (or assume) a specific case for the WIN32 drive-letter
character (when the (WIN32 API to the) underlying filesystem is case-
insensitive!), the fix in this PR takes the approach of changing the
filename comparison operation performed in relativeFilename to be case-
insensitive on WIN32, a behavior which I believe to be in alignment with
the characteristics of filesystem on that platform.
  • Loading branch information
fwmechanic committed Oct 7, 2018
1 parent f4be743 commit 004231d
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion main/routines.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,18 @@ extern const char *getExecutablePath (void)
return ExecutableProgram;
}

/*
* compare file/dirname characters with platform-correct case sensitivity
*/
static bool fnmChEq (int c1, int c2)
{
#ifdef WIN32
return tolower( c1 ) == tolower( c2 ); /* case-insensitive */
#else
return c1 == c2 ; /* case- sensitive */
#endif
}

/*
* Memory allocation functions
*/
Expand Down Expand Up @@ -846,7 +858,7 @@ extern char* relativeFilename (const char *file, const char *dir)
absdir = absoluteFilename (file);
fp = absdir;
dp = dir;
while (*fp++ == *dp++)
while (fnmChEq (*fp++, *dp++))
continue;
fp--;
dp--; /* back to the first differing char */
Expand Down

0 comments on commit 004231d

Please sign in to comment.