Skip to content

Commit eb3eb02

Browse files
committed
main,win32: introduce an option replacing backslashes in input file names with slashes
(TODO: documentation, more log should be here) Suggested by @k-takata in #1325.
1 parent de3bac3 commit eb3eb02

File tree

9 files changed

+103
-1
lines changed

9 files changed

+103
-1
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright: 2019 Masatake YAMATO
2+
# License: GPL-2
3+
4+
CTAGS=$1
5+
OPT=--use-slash-as-filename-separator
6+
7+
. ../utils.sh
8+
9+
exit_unless_win32 $CTAGS
10+
11+
echo '#u-ctags output'
12+
$CTAGS --quiet --options=NONE -o - 'src\input.c'
13+
$CTAGS --quiet --options=NONE -o - $OPT 'src\input.c'
14+
$CTAGS --quiet --options=NONE -o - ${OPT}=no 'src\input.c'
15+
16+
echo '#e-ctags output'
17+
$CTAGS --quiet --options=NONE --output-format=e-ctags -o - 'src\input.c'
18+
$CTAGS --quiet --options=NONE --output-format=e-ctags -o - $OPT 'src\input.c'
19+
$CTAGS --quiet --options=NONE --output-format=e-ctags -o - ${OPT}=no 'src\input.c'
20+
21+
echo '#xref output'
22+
$CTAGS --quiet --options=NONE --output-format=xref -o - 'src\input.c'
23+
$CTAGS --quiet --options=NONE --output-format=xref -o - $OPT 'src\input.c'
24+
$CTAGS --quiet --options=NONE --output-format=xref -o - ${OPT}=no 'src\input.c'
25+
26+
# TODO: json output
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int n;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#u-ctags output
2+
n src/input.c /^int n;$/;" v typeref:typename:int
3+
n src/input.c /^int n;$/;" v typeref:typename:int
4+
n src\\input.c /^int n;$/;" v typeref:typename:int
5+
#e-ctags output
6+
n src\input.c /^int n;$/;" v typeref:typename:int
7+
n src/input.c /^int n;$/;" v typeref:typename:int
8+
n src\input.c /^int n;$/;" v typeref:typename:int
9+
#xref output
10+
n variable 1 src\\input.c int n;
11+
n variable 1 src/input.c int n;
12+
n variable 1 src\\input.c int n;

main/entry.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,20 @@ static void writeTagEntry (const tagEntryInfo *const tag, bool checkingNeeded)
12361236

12371237
DebugStatement ( debugEntry (tag); )
12381238

1239+
#ifdef WIN32
1240+
if (getFilenameSeparator(Option.useSlashAsFilenameSeparator) == FILENAME_SEP_USE_SLASH)
1241+
{
1242+
Assert (((const tagEntryInfo *)tag)->inputFileName);
1243+
char *c = (char *)(((tagEntryInfo *const)tag)->inputFileName);
1244+
while (*c)
1245+
{
1246+
if (*c == PATH_SEPARATOR)
1247+
*c = OUTPUT_PATH_SEPARATOR;
1248+
c++;
1249+
}
1250+
}
1251+
#endif
1252+
12391253
if (includeExtensionFlags ()
12401254
&& isXtagEnabled (XTAG_QUALIFIED_TAGS)
12411255
&& doesInputLanguageRequestAutomaticFQTag ()

main/options.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ optionValues Option = {
172172
.putFieldPrefix = false,
173173
.maxRecursionDepth = 0xffffffff,
174174
.interactive = false,
175+
#ifdef WIN32
176+
.useSlashAsFilenameSeparator = FILENAME_SEP_UNSET,
177+
#endif
175178
#ifdef DEBUG
176179
.breakLine = 0,
177180
#endif
@@ -416,6 +419,10 @@ static optionDescription LongOptionDescription [] = {
416419
{0," never: be absolute even if input files are passed in with relative paths" },
417420
{1," --totals=[yes|no|extra]"},
418421
{1," Print statistics about input and tag files [no]."},
422+
#ifdef WIN32
423+
{1," --use-slash-as-filename-separator"},
424+
{1," Use slash as filename separator [no]."},
425+
#endif
419426
{1," --verbose=[yes|no]"},
420427
{1," Enable verbose messages describing actions on each input file."},
421428
{1," --version"},
@@ -2786,6 +2793,9 @@ static booleanOption BooleanOptions [] = {
27862793
{ "recurse", &Option.recurse, false, STAGE_ANY },
27872794
#endif
27882795
{ "verbose", &ctags_verbose, false, STAGE_ANY },
2796+
#ifdef WIN32
2797+
{ "use-slash-as-filename-separator", (bool *)&Option.useSlashAsFilenameSeparator, false, STAGE_ANY },
2798+
#endif
27892799
{ "with-list-header", &localOption.withListHeader, true, STAGE_ANY },
27902800
{ "_fatal-warnings",&Option.fatalWarnings, false, STAGE_ANY },
27912801
};

main/options_p.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ typedef struct sOptionValues {
120120
enum interactiveMode { INTERACTIVE_NONE = 0,
121121
INTERACTIVE_DEFAULT,
122122
INTERACTIVE_SANDBOX, } interactive; /* --interactive */
123+
#ifdef WIN32
124+
enum filenameSepOp { FILENAME_SEP_NO_REPLACE = false,
125+
FILENAME_SEP_USE_SLASH = true,
126+
FILENAME_SEP_UNSET,
127+
} useSlashAsFilenameSeparator; /* --use-slash-as-filename-separator */
128+
#endif
123129
#ifdef DEBUG
124130
unsigned long breakLine;/* -b input line at which to call lineBreak() */
125131
#endif

main/writer-ctags.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,23 @@ static int writeCtagsPtagEntry (tagWriter *writer CTAGS_ATTR_UNUSED,
3434
void *clientData);
3535
static bool treatFieldAsFixed (int fieldType);
3636

37+
#ifdef WIN32
38+
static enum filenameSepOp overrideFilenameSeparator (enum filenameSepOp currentSetting);
39+
#endif /* WIN32 */
40+
3741
struct rejection {
3842
bool rejectionInThisInput;
3943
};
4044

4145
tagWriter uCtagsWriter = {
4246
.writeEntry = writeCtagsEntry,
4347
.writePtagEntry = writeCtagsPtagEntry,
44-
.preWriteEntry = NULL,
4548
.postWriteEntry = NULL,
4649
.rescanFailedEntry = NULL,
4750
.treatFieldAsFixed = treatFieldAsFixed,
51+
#ifdef WIN32
52+
.overrideFilenameSeparator = overrideFilenameSeparator,
53+
#endif
4854
.defaultFileName = CTAGS_FILE,
4955
};
5056

@@ -65,6 +71,15 @@ static bool endECTagsFile (tagWriter *writer, MIO * mio CTAGS_ATTR_UNUSED, const
6571
return rej->rejectionInThisInput;
6672
}
6773

74+
#ifdef WIN32
75+
static enum filenameSepOp overrideFilenameSeparator (enum filenameSepOp currentSetting)
76+
{
77+
if (currentSetting == FILENAME_SEP_UNSET)
78+
return FILENAME_SEP_USE_SLASH;
79+
return currentSetting;
80+
}
81+
#endif
82+
6883
tagWriter eCtagsWriter = {
6984
.writeEntry = writeCtagsEntry,
7085
.writePtagEntry = writeCtagsPtagEntry,

main/writer.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,12 @@ extern bool writerDoesTreatFieldAsFixed (int fieldType)
119119
return writer->treatFieldAsFixed (fieldType);
120120
return false;
121121
}
122+
123+
#ifdef WIN32
124+
extern enum filenameSepOp getFilenameSeparator (enum filenameSepOp currentSetting)
125+
{
126+
if (writer->overrideFilenameSeparator)
127+
return writer->overrideFilenameSeparator (currentSetting);
128+
return currentSetting;
129+
}
130+
#endif

main/writer_p.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "general.h" /* must always come first */
1313
#include "mio.h"
14+
#include "options_p.h"
1415
#include "types.h"
1516

1617
/* Other than writeEntry can be NULL.
@@ -49,6 +50,11 @@ struct sTagWriter {
4950
void (* rescanFailedEntry) (tagWriter *writer, unsigned long validTagNum,
5051
void *clientData);
5152
bool (* treatFieldAsFixed) (int fieldType);
53+
54+
#ifdef WIN32
55+
enum filenameSepOp (* overrideFilenameSeparator) (enum filenameSepOp currentSetting);
56+
#endif /* WIN32 */
57+
5258
const char *defaultFileName;
5359

5460
/* The value returned from preWriteEntry is stored `private' field.
@@ -86,4 +92,7 @@ extern bool ptagMakeCtagsOutputMode (ptagDesc *desc, void *data CTAGS_ATTR_UNUSE
8692
extern bool writerCanPrintPtag (void);
8793
extern bool writerDoesTreatFieldAsFixed (int fieldType);
8894

95+
#ifdef WIN32
96+
extern enum filenameSepOp getFilenameSeparator (enum filenameSepOp currentSetting);
97+
#endif /* WIN32 */
8998
#endif /* CTAGS_MAIN_WRITER_PRIVATE_H */

0 commit comments

Comments
 (0)