Skip to content

Commit 0e75950

Browse files
committed
readtags: add -A,--absolute-input option
Signed-off-by: Masatake YAMATO <[email protected]>
1 parent c34dd43 commit 0e75950

File tree

9 files changed

+232
-23
lines changed

9 files changed

+232
-23
lines changed

Tmain/readtags-canonicalize-input-names.d/run.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,10 @@ run_test good1.tags --canonicalize-input -l &&
3232
run_test good2.tags -C -l &&
3333
! run_test drive-letter0.tags --canonicalize-input -l &&
3434
! run_test drive-letter1.tags -C -l &&
35-
run_test good-ptags.tags -C -D
35+
run_test good-ptags.tags -C -D &&
36+
run_test good0.tags -A -l &&
37+
run_test good1.tags --absolute-input -l &&
38+
run_test good2.tags -A -l &&
39+
! run_test drive-letter0.tags --absolute-input -l &&
40+
! run_test drive-letter1.tags -A -l &&
41+
run_test good-ptags.tags -A -D

Tmain/readtags-canonicalize-input-names.d/stderr-expected.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,11 @@
66
# drive-letter1.tags -C -l
77
!_TAG_PROC_CWD must start with '/': D:/tmp
88
# good-ptags.tags -C -D
9+
# good0.tags -A -l
10+
# good1.tags --absolute-input -l
11+
# good2.tags -A -l
12+
# drive-letter0.tags --absolute-input -l
13+
!_TAG_PROC_CWD must start with '/': C:\tmp
14+
# drive-letter1.tags -A -l
15+
!_TAG_PROC_CWD must start with '/': D:/tmp
16+
# good-ptags.tags -A -D

Tmain/readtags-canonicalize-input-names.d/stdout-expected.txt

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,90 @@ w_fn /abc/w.c
8585
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
8686
!_TAG_PROGRAM_VERSION 5.9.0 /e08db39a3/
8787
!_TAG_PROC_DUMMY /../../tmp //
88+
# good0.tags -A -l
89+
a_fn /tmp/abc/xyz/a.c
90+
b_fn /tmp/abc/b.c
91+
c_fn /tmp/abc/c.c
92+
d_fn /tmp/d.c
93+
e_fn /tmp/e.c
94+
f_fn /f.c
95+
g_fn /g.c
96+
h_fn /h.c
97+
i_fn /i.c
98+
j_fn /j.c
99+
k_fn /k.c
100+
l_fn /tmp/abc/l.c
101+
m_fn /tmp/abc/m.c
102+
n_fn /tmp/abc/n.c
103+
o_fn /tmp/abc/o.c
104+
p_fn /tmp/xyz/p.c
105+
q_fn /tmp/xyz/q.c
106+
r_fn /r.c
107+
s_fn /s.c
108+
t_fn /t.c
109+
u_fn /tmp/u.c
110+
v_fn /tmp/abc/v.c
111+
w_fn /abc/w.c
112+
# good1.tags --absolute-input -l
113+
a_fn /tmp/abc/xyz/a.c
114+
b_fn /tmp/abc/b.c
115+
c_fn /tmp/abc/c.c
116+
d_fn /tmp/d.c
117+
e_fn /tmp/e.c
118+
f_fn /f.c
119+
g_fn /g.c
120+
h_fn /h.c
121+
i_fn /i.c
122+
j_fn /j.c
123+
k_fn /k.c
124+
l_fn /tmp/abc/l.c
125+
m_fn /tmp/abc/m.c
126+
n_fn /tmp/abc/n.c
127+
o_fn /tmp/abc/o.c
128+
p_fn /tmp/xyz/p.c
129+
q_fn /tmp/xyz/q.c
130+
r_fn /r.c
131+
s_fn /s.c
132+
t_fn /t.c
133+
u_fn /tmp/u.c
134+
v_fn /tmp/abc/v.c
135+
w_fn /abc/w.c
136+
# good2.tags -A -l
137+
a_fn /tmp/abc/xyz/a.c
138+
b_fn /tmp/abc/b.c
139+
c_fn /tmp/abc/c.c
140+
d_fn /tmp/d.c
141+
e_fn /tmp/e.c
142+
f_fn /f.c
143+
g_fn /g.c
144+
h_fn /h.c
145+
i_fn /i.c
146+
j_fn /j.c
147+
k_fn /k.c
148+
l_fn /tmp/abc/l.c
149+
m_fn /tmp/abc/m.c
150+
n_fn /tmp/abc/n.c
151+
o_fn /tmp/abc/o.c
152+
p_fn /tmp/xyz/p.c
153+
q_fn /tmp/xyz/q.c
154+
r_fn /r.c
155+
s_fn /s.c
156+
t_fn /t.c
157+
u_fn /tmp/u.c
158+
v_fn /tmp/abc/v.c
159+
w_fn /abc/w.c
160+
# drive-letter0.tags --absolute-input -l
161+
# drive-letter1.tags -A -l
162+
# good-ptags.tags -A -D
163+
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
164+
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
165+
!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/
166+
!_TAG_OUTPUT_FILESEP slash /slash or backslash/
167+
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
168+
!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/
169+
!_TAG_PROC_CWD /tmp //
170+
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
171+
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
172+
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
173+
!_TAG_PROGRAM_VERSION 5.9.0 /e08db39a3/
174+
!_TAG_PROC_DUMMY /../../tmp //

docs/man/readtags.1.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ Controlling the Output
7373
By default, the output of readtags contains only the name, input and pattern
7474
field. The Output can be tweaked using these options:
7575

76+
``-A``, ``--absolute-input``
77+
Do the same as ``-C`` option but use only absolute path form.
78+
7679
``-C``, ``--canonicalize-input``
7780
Resolve '..' and '.' in input fields of regular tags.
7881
This produces a unique representation of the input path.

extra-cmds/readtags-cmd.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ typedef struct sReadOption {
3232
struct canonWorkArea {
3333
struct canonFnameCacheTable *cacheTable;
3434
int ptags;
35+
bool absoluteOnly;
3536
};
3637

3738
static const char *TagFileName = "tags";
@@ -215,8 +216,8 @@ static void walkTags (tagFile *const file, tagEntry *first_entry,
215216
{
216217
shadowRec = *first_entry;
217218
shadow = &shadowRec;
218-
shadow->file = canonicalizeRelativeFileName (canon->cacheTable,
219-
first_entry->file);
219+
shadow->file = canonicalizeFileName (canon->cacheTable,
220+
first_entry->file);
220221
}
221222

222223
if (Qualifier)
@@ -357,11 +358,12 @@ static const char *loadCtagsCWD (tagFile *const file, tagEntry *pentry)
357358
return pentry->file;
358359
}
359360

360-
static struct canonFnameCacheTable *makeCanonFnameCacheTable (tagFile *const file)
361+
static struct canonFnameCacheTable *makeCanonFnameCacheTable (tagFile *const file,
362+
bool absoluteOnly)
361363
{
362364
tagEntry pentry;
363365
const char *cwd = loadCtagsCWD (file, &pentry);
364-
return canonFnameCacheTableNew (cwd);
366+
return canonFnameCacheTableNew (cwd, absoluteOnly);
365367
}
366368

367369
static tagFile *openTags (const char *const filePath, tagFileInfo *const info)
@@ -426,7 +428,7 @@ static void findTag (const char *const name, readOptions *readOpts,
426428
}
427429

428430
if (canon && canon->cacheTable == NULL)
429-
canon->cacheTable = makeCanonFnameCacheTable (file);
431+
canon->cacheTable = makeCanonFnameCacheTable (file, canon->absoluteOnly);
430432

431433
if (printOpts->escaping)
432434
{
@@ -487,7 +489,7 @@ static void listTags (int pseudoTags, tagPrintOptions *printOpts,
487489
}
488490

489491
if (canon && canon->cacheTable == NULL)
490-
canon->cacheTable = makeCanonFnameCacheTable (file);
492+
canon->cacheTable = makeCanonFnameCacheTable (file, canon->absoluteOnly);
491493

492494
if (printOpts->escaping)
493495
{
@@ -573,6 +575,8 @@ static const char *const Usage =
573575
" METHOD: unsorted|sorted|foldcase\n"
574576
" -C | --canonicalize-input\n"
575577
" Reduct '..' and '.' in input fields.\n"
578+
" -A | --absolute-input\n"
579+
" Do the same as -C but use absolute path form\n"
576580
#ifdef READTAGS_DSL
577581
" -F EXP | --formatter EXP\n"
578582
" Format the tags listed by ACTION with EXP when printing.\n"
@@ -666,6 +670,12 @@ extern int main (int argc, char **argv)
666670
struct canonWorkArea canonWorkArea = {
667671
.cacheTable = NULL,
668672
.ptags = 0,
673+
.absoluteOnly = false,
674+
};
675+
struct canonWorkArea canonWorkAreaAbsForm = {
676+
.cacheTable = NULL,
677+
.ptags = 0,
678+
.absoluteOnly = true,
669679
};
670680
struct canonWorkArea *canon = NULL;
671681

@@ -782,6 +792,8 @@ extern int main (int argc, char **argv)
782792
exit (1);
783793
}
784794
}
795+
else if (strcmp (optname, "absolute-input") == 0)
796+
canon = &canonWorkAreaAbsForm;
785797
else if (strcmp (optname, "canonicalize-input") == 0)
786798
canon = &canonWorkArea;
787799
#ifdef READTAGS_DSL
@@ -898,6 +910,9 @@ extern int main (int argc, char **argv)
898910
else
899911
printUsage(stderr, 1);
900912
break;
913+
case 'A':
914+
canon = &canonWorkAreaAbsForm;
915+
break;
901916
case 'C':
902917
canon = &canonWorkArea;
903918
break;

extra-cmds/utiltest.c

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,92 @@ static void test_fname_absolute(void)
4949
#undef T
5050
}
5151

52-
static void test_fname_relative(void)
52+
static void test_fname_absolute_with_cache(void)
5353
{
5454
struct canonFnameCacheTable *ct;
55-
55+
bool absoluteOnly;
5656
#define T(INPUT,OUTPUT) \
57-
if (!TEST_CHECK(strcmp(canonicalizeRelativeFileName (ct, INPUT), \
57+
if (!TEST_CHECK(strcmp(canonicalizeFileName (ct, INPUT), \
5858
OUTPUT) == 0)) \
59-
fprintf(stderr, " ACTUAL: %s\n", canonicalizeRelativeFileName (ct, INPUT))
59+
fprintf(stderr, " ACTUAL: %s (%s)\n", canonicalizeFileName (ct, INPUT), absoluteOnly? "absOnly": "relaOK")
60+
61+
absoluteOnly = true;
62+
ct = canonFnameCacheTableNew ("/abc", absoluteOnly);
63+
T("/abc/input", "/abc/input");
64+
T("/abc/../input", "/input");
65+
T("/abc/../../input", "/input");
66+
T("/abc/.././../input", "/input");
67+
T("/abc/./input", "/abc/input");
68+
T("/abc/.//input", "/abc/input");
69+
T("/abc/.//.//input", "/abc/input");
70+
T("/input", "/input");
71+
T("/./input", "/input");
72+
T("/../z/../input", "/input");
73+
T("/../z/../..input", "/..input");
6074

75+
T("input", "/abc/input");
76+
T("./input", "/abc/input");
77+
T("../input", "/input");
78+
T("..//input", "/input");
79+
T(".././input", "/input");
80+
T("..//.//input", "/input");
81+
T("../d/input", "/d/input");
82+
T("../d/../input", "/input");
83+
T("../d/..//input", "/input");
84+
T("../d/..///./input", "/input");
85+
canonFnameCacheTableDelete (ct);
86+
87+
absoluteOnly = true;
88+
ct = canonFnameCacheTableNew ("/abc/efg", absoluteOnly);
89+
T("input", "/abc/efg/input");
90+
T("../input", "/abc/input");
91+
T("..//input", "/abc/input");
92+
T(".././input", "/abc/input");
93+
T("..//.//input", "/abc/input");
94+
T("../d/input", "/abc/d/input");
95+
T("../d/../input", "/abc/input");
96+
T("../d/..//input", "/abc/input");
97+
T("../d/..///./input", "/abc/input");
98+
T("../d/..///./input/.././input", "/abc/input");
99+
T("", "/abc/efg");
100+
T(".", "/abc/efg");
101+
T("./", "/abc/efg");
102+
T("./..", "/abc");
103+
T("./.", "/abc/efg");
104+
T("././//", "/abc/efg");
105+
T("././//.", "/abc/efg");
106+
T("././../efg/.", "/abc/efg");
107+
T("..", "/abc");
108+
T("../..", "/");
109+
T("../../", "/");
110+
T("../..", "/");
111+
T("../../..", "/");
112+
T("../../../..", "/");
113+
T("../././..", "/");
114+
T("./././..", "/abc");
115+
T("...", "/abc/efg/...");
116+
T(".../", "/abc/efg/...");
117+
T("...//", "/abc/efg/...");
118+
T("..././", "/abc/efg/...");
119+
T("...//./", "/abc/efg/...");
120+
T("...//.//", "/abc/efg/...");
121+
T("..././/", "/abc/efg/...");
122+
T("..././.../", "/abc/efg/.../...");
123+
canonFnameCacheTableDelete (ct);
124+
#undef T
125+
}
126+
127+
static void test_fname_relative(void)
128+
{
129+
struct canonFnameCacheTable *ct;
130+
bool absoluteOnly;
131+
#define T(INPUT,OUTPUT) \
132+
if (!TEST_CHECK(strcmp(canonicalizeFileName (ct, INPUT), \
133+
OUTPUT) == 0)) \
134+
fprintf(stderr, " ACTUAL: %s (%s)\n", canonicalizeFileName (ct, INPUT), absoluteOnly? "absOnly": "relaOK")
61135

62-
ct = canonFnameCacheTableNew ("/abc");
136+
absoluteOnly = false;
137+
ct = canonFnameCacheTableNew ("/abc", absoluteOnly);
63138
T("/abc/input", "/abc/input");
64139
T("/abc/../input", "/input");
65140
T("/abc/../../input", "/input");
@@ -84,7 +159,8 @@ static void test_fname_relative(void)
84159
T("../d/..///./input", "/input");
85160
canonFnameCacheTableDelete (ct);
86161

87-
ct = canonFnameCacheTableNew ("/abc/efg");
162+
absoluteOnly = false;
163+
ct = canonFnameCacheTableNew ("/abc/efg", absoluteOnly);
88164
T("input", "input");
89165
T("../input", "/abc/input");
90166
T("..//input", "/abc/input");
@@ -146,6 +222,7 @@ static void test_routines_strrstr(void)
146222

147223
TEST_LIST = {
148224
{ "fname/absolute", test_fname_absolute },
225+
{ "fname/absolute+cache", test_fname_absolute_with_cache },
149226
{ "fname/relative", test_fname_relative },
150227
{ "htable/update", test_htable_update },
151228
{ "routines/strrstr", test_routines_strrstr },

main/fname.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ struct canonFnameCacheTable {
2828
size_t cwd_len;
2929
char *input_last;
3030
char *return_last;
31+
bool absoluteOnly;
3132
};
3233

33-
extern struct canonFnameCacheTable *canonFnameCacheTableNew (const char *cwd)
34+
extern struct canonFnameCacheTable *canonFnameCacheTableNew (const char *cwd, bool absoluteOnly)
3435
{
3536
struct canonFnameCacheTable *r = xMalloc (1, struct canonFnameCacheTable);
3637
r->table = hashTableNew (7, hashCstrhash, hashCstreq,
@@ -43,6 +44,8 @@ extern struct canonFnameCacheTable *canonFnameCacheTableNew (const char *cwd)
4344
eFree (cwd_tmp);
4445
r->cwd_len = strlen (r->cwd);
4546

47+
r->absoluteOnly = absoluteOnly;
48+
4649
return r;
4750
}
4851

@@ -180,7 +183,8 @@ extern char *canonicalizeAbsoluteFileName (char *fname)
180183
return fsimplify_abs0 (next + 1, &comp);
181184
}
182185

183-
static char *canonicalizePathNew(const char *dir, size_t dir_len, const char *rela)
186+
static char *canonicalizePathNew(const char *dir, size_t dir_len, const char *rela,
187+
bool absoluteOnly)
184188
{
185189
bool relative = false;
186190
vString *buf = vStringNew ();
@@ -194,7 +198,8 @@ static char *canonicalizePathNew(const char *dir, size_t dir_len, const char *re
194198
vStringNCopyS (buf, dir, dir_len);
195199
vStringPut (buf, '/');
196200
vStringCatS (buf, rela);
197-
relative = true;
201+
if (!absoluteOnly)
202+
relative = true;
198203
}
199204

200205
char *r = canonicalizeAbsoluteFileName (vStringValue (buf));
@@ -229,8 +234,8 @@ static char *canonicalizePathNew(const char *dir, size_t dir_len, const char *re
229234
return r;
230235
}
231236

232-
extern const char *canonicalizeRelativeFileName (struct canonFnameCacheTable *cache_table,
233-
const char *input)
237+
extern const char *canonicalizeFileName (struct canonFnameCacheTable *cache_table,
238+
const char *input)
234239
{
235240
if (cache_table->input_last)
236241
{
@@ -243,7 +248,8 @@ extern const char *canonicalizeRelativeFileName (struct canonFnameCacheTable *ca
243248
if (r)
244249
return r;
245250

246-
r = canonicalizePathNew (cache_table->cwd, cache_table->cwd_len, input);
251+
r = canonicalizePathNew (cache_table->cwd, cache_table->cwd_len, input,
252+
cache_table->absoluteOnly);
247253

248254
cache_table->input_last = eStrdup (input);
249255
cache_table->return_last = r;

0 commit comments

Comments
 (0)