1 | /* ----------------------------------------------------------------------- * |
2 | * |
3 | * Copyright 2017 The NASM Authors - All Rights Reserved |
4 | * See the file AUTHORS included with the NASM distribution for |
5 | * the specific copyright holders. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following |
9 | * conditions are met: |
10 | * |
11 | * * Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * * Redistributions in binary form must reproduce the above |
14 | * copyright notice, this list of conditions and the following |
15 | * disclaimer in the documentation and/or other materials provided |
16 | * with the distribution. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
19 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
20 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | * |
32 | * ----------------------------------------------------------------------- */ |
33 | |
34 | /* |
35 | * path.c - host operating system specific pathname manipulation functions |
36 | * |
37 | * This file is inherently nonportable ... please help adjusting it to |
38 | * any new platforms that may be necessary. |
39 | */ |
40 | |
41 | #include "compiler.h" |
42 | #include "nasmlib.h" |
43 | #include "error.h" |
44 | |
45 | #if defined(__MSDOS__) || defined(__DOS__) || \ |
46 | defined(__WINDOWS__) || defined(_Windows) || \ |
47 | defined(__OS2__) || defined(_WIN16) || defined(WIN32) || defined(_WIN32) |
48 | /* MS-DOS/Windows and like operating systems */ |
49 | # define separators "/\\:" |
50 | # define cleandirend "/\\" |
51 | # define catsep '\\' |
52 | # define leaveonclean 2 /* Leave \\ at the start alone */ |
53 | # define curdir "." |
54 | #elif defined(unix) || defined(__unix) || defined(__unix__) || \ |
55 | defined(__UNIX__) || defined(__Unix__) || \ |
56 | defined(__MACH__) || defined(__BEOS__) |
57 | /* Unix and Unix-like operating systems and others using |
58 | * the equivalent syntax (slashes as only separators, no concept of volume) |
59 | * |
60 | * This must come after the __MSDOS__ section, since it seems that at |
61 | * least DJGPP defines __unix__ despite not being a Unix environment at all. |
62 | */ |
63 | # define separators "/" |
64 | # define cleandirend "/" |
65 | # define catsep '/' |
66 | # define leaveonclean 1 |
67 | # define curdir "." |
68 | #elif defined(Macintosh) || defined(macintosh) |
69 | /* MacOS classic */ |
70 | # define separators ":" |
71 | # define curdir ":" |
72 | # define catsep ':' |
73 | # define cleandirend ":" |
74 | # define leaveonclean 0 |
75 | # define leave_leading 1 |
76 | #elif defined(__VMS) |
77 | /* VMS * |
78 | * |
79 | * VMS filenames may have ;version at the end. Assume we should count that |
80 | * as part of the filename anyway. |
81 | */ |
82 | # define separators ":]" |
83 | # define curdir "[]" |
84 | #else |
85 | /* No idea what to do here, do nothing. Feel free to add new ones. */ |
86 | # define curdir "" |
87 | #endif |
88 | |
89 | /* |
90 | * This is an inline, because most compilers can greatly simplify this |
91 | * for a fixed string, like we have here. |
92 | */ |
93 | static inline bool ismatch(const char *charset, char ch) |
94 | { |
95 | const char *p; |
96 | |
97 | for (p = charset; *p; p++) { |
98 | if (ch == *p) |
99 | return true; |
100 | } |
101 | |
102 | return false; |
103 | } |
104 | |
105 | static const char *first_filename_char(const char *path) |
106 | { |
107 | #ifdef separators |
108 | const char *p = path + strlen(path); |
109 | |
110 | while (p > path) { |
111 | if (ismatch(separators, p[-1])) |
112 | return p; |
113 | p--; |
114 | } |
115 | |
116 | return p; |
117 | #else |
118 | return path; |
119 | #endif |
120 | } |
121 | |
122 | /* Return the filename portion of a PATH as a new string */ |
123 | char *nasm_basename(const char *path) |
124 | { |
125 | return nasm_strdup(first_filename_char(path)); |
126 | } |
127 | |
128 | /* Return the directory name portion of a PATH as a new string */ |
129 | char *nasm_dirname(const char *path) |
130 | { |
131 | const char *p = first_filename_char(path); |
132 | const char *p0 = p; |
133 | (void)p0; /* Don't warn if unused */ |
134 | |
135 | if (p == path) |
136 | return nasm_strdup(curdir); |
137 | |
138 | #ifdef cleandirend |
139 | while (p > path+leaveonclean) { |
140 | if (ismatch(cleandirend, p[-1])) |
141 | break; |
142 | p--; |
143 | } |
144 | #endif |
145 | |
146 | #ifdef leave_leading |
147 | /* If the directory contained ONLY separators, leave as-is */ |
148 | if (p == path+leaveonclean) |
149 | p = p0; |
150 | #endif |
151 | |
152 | return nasm_strndup(path, p-path); |
153 | } |
154 | |
155 | /* |
156 | * Concatenate a directory path and a filename. Note that this function |
157 | * currently does NOT handle the case where file itself contains |
158 | * directory components (except on Unix platforms, because it is trivial.) |
159 | */ |
160 | char *nasm_catfile(const char *dir, const char *file) |
161 | { |
162 | #ifndef catsep |
163 | return nasm_strcat(dir, file); |
164 | #else |
165 | size_t dl = strlen(dir); |
166 | size_t fl = strlen(file); |
167 | char *p, *pp; |
168 | bool dosep = true; |
169 | |
170 | if (!dl || ismatch(separators, dir[dl-1])) { |
171 | /* No separator necessary */ |
172 | dosep = false; |
173 | } |
174 | |
175 | p = pp = nasm_malloc(dl + fl + dosep + 1); |
176 | |
177 | memcpy(pp, dir, dl); |
178 | pp += dl; |
179 | if (dosep) |
180 | *pp++ = catsep; |
181 | |
182 | memcpy(pp, file, fl+1); |
183 | |
184 | return p; |
185 | #endif |
186 | } |
187 | |