Skip to content

Commit 8f2e2ee

Browse files
committed
libutil: add functions for manipulating file names
Signed-off-by: Masatake YAMATO <[email protected]>
1 parent 7617557 commit 8f2e2ee

File tree

5 files changed

+268
-0
lines changed

5 files changed

+268
-0
lines changed

main/fname.c

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/*
2+
* Copyright (c) 2022, Masatake YAMATO
3+
*
4+
* This source code is released for free distribution under the terms of the
5+
* GNU General Public License version 2 or (at your option) any later version.
6+
*/
7+
8+
#include "general.h"
9+
#include "fname.h"
10+
11+
#include <string.h>
12+
13+
#include "routines.h"
14+
#include "vstring.h"
15+
16+
17+
struct comp {
18+
char *str;
19+
size_t len;
20+
struct comp *parent;
21+
struct comp *child;
22+
};
23+
24+
25+
extern hashTable *canonFnameCacheTableNew (void)
26+
{
27+
return hashTableNew (7, hashCstrhash, hashCstreq,
28+
eFree, eFree);
29+
}
30+
31+
static void strcpy_comps (char *buf, struct comp *comp)
32+
{
33+
while (comp)
34+
{
35+
buf[0] = '/';
36+
memcpy (buf + 1, comp->str, comp->len);
37+
buf += (1 + comp->len);
38+
comp = comp->child;
39+
}
40+
buf[0] = '\0';
41+
}
42+
43+
static size_t strlen_comps (struct comp *comp)
44+
{
45+
size_t n = 0;
46+
47+
while (comp)
48+
{
49+
n += (1 + comp->len);
50+
comp = comp->child;
51+
}
52+
return n;
53+
}
54+
55+
static char *fsimplify_absz (struct comp *comp)
56+
{
57+
struct comp *root = comp;
58+
59+
while (comp)
60+
{
61+
// fprintf (stderr, "[stack] -%s-\n", comp->str);
62+
root = comp;
63+
comp = comp->parent;
64+
}
65+
66+
if (root->child && root->len == 0)
67+
root = root->child;
68+
69+
size_t len = strlen_comps (root);
70+
char *buf = xMalloc (len + 1, char);
71+
72+
strcpy_comps(buf, root);
73+
return buf;
74+
}
75+
76+
static char *fsimplify_abs0 (char *fname, struct comp *parent)
77+
{
78+
char *next = strchr (fname, '/');
79+
struct comp comp = {
80+
.str = fname,
81+
.len = next? (next - fname): strlen (fname),
82+
.parent = parent,
83+
.child = NULL
84+
};
85+
86+
if (comp.len == 0
87+
|| (comp.len == 1 && fname [0] == '.'))
88+
{
89+
parent->child = NULL;
90+
if (next == NULL)
91+
return fsimplify_absz (parent);
92+
*next = '\0';
93+
return fsimplify_abs0 (next + 1, parent);
94+
}
95+
96+
if (comp.len == 2 && fname [0] == '.' && fname [1] == '.')
97+
{
98+
if (next == NULL)
99+
{
100+
if (parent->parent)
101+
{
102+
parent->parent->child = NULL;
103+
return fsimplify_absz (parent->parent);
104+
}
105+
return strdup("/");
106+
}
107+
*next = '\0';
108+
if (parent->parent)
109+
{
110+
parent->parent->child = NULL;
111+
return fsimplify_abs0 (next + 1, parent->parent);
112+
}
113+
comp.parent = NULL;
114+
comp.str[0] = '\0';
115+
comp.len = 0;
116+
return fsimplify_abs0 (next + 1, &comp);
117+
}
118+
119+
parent->child = &comp;
120+
if (next == NULL)
121+
return fsimplify_absz (&comp);
122+
*next = '\0';
123+
return fsimplify_abs0 (next + 1, &comp);
124+
}
125+
126+
extern char *canonicalizeAbsoluteFileName (char *fname)
127+
{
128+
char *next = strchr (fname, '/');
129+
if (next == NULL)
130+
{
131+
if (!strcmp (fname, "..") || !strcmp (fname, "."))
132+
{
133+
fname [0] = '/';
134+
fname [1] = '\0';
135+
return strdup (fname);
136+
}
137+
{
138+
char *r = xMalloc (strlen (fname) + 2, char);
139+
r[0] = '/';
140+
strcpy (r + 1, fname);
141+
return r;
142+
}
143+
}
144+
145+
*next = '\0';
146+
struct comp comp = {
147+
.str = fname,
148+
.len = next - fname,
149+
.parent = NULL,
150+
.child = NULL
151+
};
152+
if (!strcmp (comp.str, "..") || !strcmp (comp.str, "."))
153+
{
154+
comp.str[0] = '\0';
155+
comp.len = 0;
156+
}
157+
return fsimplify_abs0 (next + 1, &comp);
158+
}
159+
160+
static char *canonicalizePathNew(const char *dir, size_t dir_len, const char *rela)
161+
{
162+
bool relative = false;
163+
vString *buf = vStringNew ();
164+
165+
if (rela == NULL)
166+
vStringCopyS (buf, dir);
167+
else if (rela[0] == '/')
168+
vStringCopyS (buf, rela);
169+
else
170+
{
171+
vStringCopyS (buf, dir);
172+
vStringPut (buf, '/');
173+
vStringCatS (buf, rela);
174+
relative = true;
175+
}
176+
177+
char *r = canonicalizeAbsoluteFileName (vStringValue (buf));
178+
if (relative)
179+
{
180+
if (strncmp (dir, r, dir_len) == 0)
181+
{
182+
if (r[dir_len] == '/')
183+
{
184+
if (r[dir_len + 1] == '\0')
185+
vStringCopyS (buf, ".");
186+
else
187+
vStringCopyS (buf, r + dir_len + 1);
188+
eFree (r);
189+
return vStringDeleteUnwrap (buf);
190+
}
191+
else if (r[dir_len] == '\0')
192+
{
193+
vStringCopyS (buf, ".");
194+
eFree (r);
195+
return vStringDeleteUnwrap (buf);
196+
}
197+
else
198+
{
199+
vStringDelete (buf);
200+
return r;
201+
}
202+
}
203+
}
204+
205+
vStringDelete (buf);
206+
return r;
207+
}
208+
209+
extern const char *canonicalizeRelativeFileName (const char *cwd, size_t cwd_len, const char *input,
210+
hashTable* cache_table)
211+
{
212+
static char *input_last;
213+
static char *return_last;
214+
215+
if (input_last)
216+
{
217+
if (strcmp (input, input_last) == 0)
218+
return return_last;
219+
input_last = NULL;
220+
}
221+
222+
char *r = hashTableGetItem (cache_table, input);
223+
if (r)
224+
return r;
225+
226+
r = canonicalizePathNew (cwd, cwd_len, input);
227+
228+
input_last = eStrdup (input);
229+
return_last = r;
230+
hashTablePutItem (cache_table, input_last, return_last);
231+
return return_last;
232+
}

main/fname.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2022, Masatake YAMATO
3+
*
4+
* This source code is released for free distribution under the terms of the
5+
* GNU General Public License version 2 or (at your option) any later version.
6+
*/
7+
#ifndef CTAGS_MAIN_FNAME_UTIL_H
8+
#define CTAGS_MAIN_FNAME_UTIL_H
9+
10+
#include "general.h"
11+
12+
#include "htable.h"
13+
14+
/* hashTableDelete() is for freeing the cache returned from this function. */
15+
extern hashTable *canonFnameCacheTableNew (void);
16+
17+
/* Don't free the cstring returned from this function directly.
18+
* This function stores the cstring to the cache.
19+
*/
20+
extern const char *canonicalizeRelativeFileName(const char *cwd, size_t cwd_len, const char *input,
21+
hashTable* cache_table);
22+
23+
/* eFree() is for freeing the cstring returned from this function. */
24+
extern char *canonicalizeAbsoluteFileName (char *fname);
25+
26+
#endif /* CTAGS_MAIN_FNAME_UTIL_H */

source.mak

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ MIO_SRCS = main/mio.c
1717
UTIL_PUBLIC_HEADS = \
1818
main/general.h \
1919
\
20+
main/fname.h \
2021
main/gcc-attr.h \
2122
main/htable.h \
2223
main/inline.h \
@@ -39,6 +40,7 @@ UTIL_HEADS = \
3940
$(NULL)
4041

4142
UTIL_SRCS = \
43+
main/fname.c \
4244
main/htable.c \
4345
main/ptrarray.c \
4446
main/routines.c \

win32/ctags_vs2013.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@
193193
<ClCompile Include="..\main\field.c" />
194194
<ClCompile Include="..\main\flags.c" />
195195
<ClCompile Include="..\main\fmt.c" />
196+
<ClCompile Include="..\main\fname.c" />
196197
<ClCompile Include="..\main\htable.c" />
197198
<ClCompile Include="..\main\keyword.c" />
198199
<ClCompile Include="..\main\kind.c" />
@@ -388,6 +389,7 @@
388389
<ClInclude Include="..\main\field_p.h" />
389390
<ClInclude Include="..\main\flags_p.h" />
390391
<ClInclude Include="..\main\fmt_p.h" />
392+
<ClInclude Include="..\main\fname.h" />
391393
<ClInclude Include="..\main\gcc-attr.h" />
392394
<ClInclude Include="..\main\general.h" />
393395
<ClInclude Include="..\main\gvars.h" />

win32/ctags_vs2013.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@
102102
<ClCompile Include="..\main\fmt.c">
103103
<Filter>Source Files\main</Filter>
104104
</ClCompile>
105+
<ClCompile Include="..\main\fname.c">
106+
<Filter>Source Files\main</Filter>
107+
</ClCompile>
105108
<ClCompile Include="..\main\htable.c">
106109
<Filter>Source Files\main</Filter>
107110
</ClCompile>
@@ -683,6 +686,9 @@
683686
<ClInclude Include="..\main\fmt_p.h">
684687
<Filter>Header Files</Filter>
685688
</ClInclude>
689+
<ClInclude Include="..\main\fname.h">
690+
<Filter>Header Files</Filter>
691+
</ClInclude>
686692
<ClInclude Include="..\main\gcc-attr.h">
687693
<Filter>Header Files</Filter>
688694
</ClInclude>

0 commit comments

Comments
 (0)