source: trunk/src/gmake/w32/pathstuff.c@ 304

Last change on this file since 304 was 304, checked in by bird, 20 years ago

Fixed casing paths on win32.

  • Property svn:eol-style set to native
File size: 9.7 KB
Line 
1#include <windows.h>
2#include <string.h>
3#include <stdlib.h>
4#include <stdio.h>
5#include "make.h"
6#include "pathstuff.h"
7
8
9/*
10 * Convert delimiter separated vpath to Canonical format.
11 */
12char *
13convert_vpath_to_windows32(char *Path, char to_delim)
14{
15 char *etok; /* token separator for old Path */
16
17 /*
18 * Convert all spaces to delimiters. Note that pathnames which
19 * contain blanks get trounced here. Use 8.3 format as a workaround.
20 */
21 for (etok = Path; etok && *etok; etok++)
22 if (isblank ((unsigned char) *etok))
23 *etok = to_delim;
24
25 return (convert_Path_to_windows32(Path, to_delim));
26}
27
28/*
29 * Convert delimiter separated path to Canonical format.
30 */
31char *
32convert_Path_to_windows32(char *Path, char to_delim)
33{
34 char *etok; /* token separator for old Path */
35 char *p; /* points to element of old Path */
36
37 /* is this a multi-element Path ? */
38 for (p = Path, etok = strpbrk(p, ":;");
39 etok;
40 etok = strpbrk(p, ":;"))
41 if ((etok - p) == 1) {
42 if (*(etok - 1) == ';' ||
43 *(etok - 1) == ':') {
44 etok[-1] = to_delim;
45 etok[0] = to_delim;
46 p = ++etok;
47 continue; /* ignore empty bucket */
48 } else if (!isalpha ((unsigned char) *p)) {
49 /* found one to count, handle things like '.' */
50 *etok = to_delim;
51 p = ++etok;
52 } else if ((*etok == ':') && (etok = strpbrk(etok+1, ":;"))) {
53 /* found one to count, handle drive letter */
54 *etok = to_delim;
55 p = ++etok;
56 } else
57 /* all finished, force abort */
58 p += strlen(p);
59 } else {
60 /* found another one, no drive letter */
61 *etok = to_delim;
62 p = ++etok;
63 }
64
65 return Path;
66}
67
68/*
69 * Corrects the case of a path.
70 * Expects a fullpath!
71 */
72void w32_fixcase(char *pszPath)
73{
74#define my_assert(expr) \
75 do { \
76 if (!(expr)) { \
77 printf("my_assert: %s, file %s, line %d\npszPath=%s\npsz=%s\n", \
78 #expr, __FILE__, __LINE__, pszPath, psz); \
79 __asm { __asm int 3 } \
80 exit(1); \
81 } \
82 } while (0)
83
84 char *psz = pszPath;
85 if (*psz == '/' || *psz == '\\')
86 {
87 if (psz[1] == '/' || psz[1] == '\\')
88 {
89 /* UNC */
90 my_assert(psz[1] == '/' || psz[1] == '\\');
91 my_assert(psz[2] != '/' && psz[2] != '\\');
92
93 /* skip server name */
94 psz += 2;
95 while (*psz != '\\' && *psz != '/')
96 {
97 if (!*psz)
98 return;
99 *psz++ = toupper(*psz);
100 }
101
102 /* skip the share name */
103 psz++;
104 my_assert(*psz != '/' && *psz != '\\');
105 while (*psz != '\\' && *psz != '/')
106 {
107 if (!*psz)
108 return;
109 *psz++ = toupper(*psz);
110 }
111 my_assert(*psz == '/' || *psz == '\\');
112 psz++;
113 }
114 else
115 {
116 /* Unix spec */
117 psz++;
118 }
119 }
120 else
121 {
122 /* Drive letter */
123 my_assert(psz[1] == ':');
124 *psz = toupper(*psz);
125 my_assert(psz[0] >= 'A' && psz[0] <= 'Z');
126 my_assert(psz[2] == '/' || psz[2] == '\\');
127 psz += 3;
128 }
129
130 /*
131 * Pointing to the first char after the unc or drive specifier.
132 */
133 while (*psz)
134 {
135 WIN32_FIND_DATA FindFileData;
136 HANDLE hDir;
137 char chSaved0;
138 char chSaved1;
139 char *pszEnd;
140
141
142 /* find the end of the component. */
143 pszEnd = psz;
144 while (*pszEnd && *pszEnd != '/' && *pszEnd != '\\')
145 pszEnd++;
146
147 /* replace the end with "?\0" */
148 chSaved0 = pszEnd[0];
149 chSaved1 = pszEnd[1];
150 pszEnd[0] = '?';
151 pszEnd[1] = '\0';
152
153 /* find the right filename. */
154 hDir = FindFirstFile(pszPath, &FindFileData);
155 pszEnd[1] = chSaved1;
156 if (!hDir)
157 {
158 pszEnd[0] = chSaved0;
159 return;
160 }
161 pszEnd[0] = '\0';
162 while (stricmp(FindFileData.cFileName, psz))
163 {
164 if (!FindNextFile(hDir, &FindFileData))
165 {
166 pszEnd[0] = chSaved0;
167 return;
168 }
169 }
170 strcpy(psz, FindFileData.cFileName);
171 pszEnd[0] = chSaved0;
172
173 /* advance to the next component */
174 if (!chSaved0)
175 return;
176 psz = pszEnd + 1;
177 my_assert(*psz != '/' && *psz != '\\');
178 }
179#undef my_assert
180}
181
182/*
183 * Convert to forward slashes. Resolve to full pathname optionally
184 */
185char *
186w32ify(char *filename, int resolve)
187{
188 static char w32_path[FILENAME_MAX];
189 char *p;
190
191 if (resolve)
192 _fullpath(w32_path, filename, sizeof (w32_path));
193 else
194 strncpy(w32_path, filename, sizeof (w32_path));
195
196 w32_fixcase(w32_path);
197
198 for (p = w32_path; p && *p; p++)
199 if (*p == '\\')
200 *p = '/';
201
202 return w32_path;
203}
204
205char *
206getcwd_fs(char* buf, int len)
207{
208 char *p;
209
210 if (p = getcwd(buf, len)) {
211 char *q = w32ify(buf, 0);
212 strncpy(buf, q, len);
213 }
214
215 return p;
216}
217
218#ifdef unused
219/*
220 * Convert delimiter separated pathnames (e.g. PATH) or single file pathname
221 * (e.g. c:/foo, c:\bar) to NutC format. If we are handed a string that
222 * _NutPathToNutc() fails to convert, just return the path we were handed
223 * and assume the caller will know what to do with it (It was probably
224 * a mistake to try and convert it anyway due to some of the bizarre things
225 * that might look like pathnames in makefiles).
226 */
227char *
228convert_path_to_nutc(char *path)
229{
230 int count; /* count of path elements */
231 char *nutc_path; /* new NutC path */
232 int nutc_path_len; /* length of buffer to allocate for new path */
233 char *pathp; /* pointer to nutc_path used to build it */
234 char *etok; /* token separator for old path */
235 char *p; /* points to element of old path */
236 char sep; /* what flavor of separator used in old path */
237 char *rval;
238
239 /* is this a multi-element path ? */
240 for (p = path, etok = strpbrk(p, ":;"), count = 0;
241 etok;
242 etok = strpbrk(p, ":;"))
243 if ((etok - p) == 1) {
244 if (*(etok - 1) == ';' ||
245 *(etok - 1) == ':') {
246 p = ++etok;
247 continue; /* ignore empty bucket */
248 } else if (etok = strpbrk(etok+1, ":;"))
249 /* found one to count, handle drive letter */
250 p = ++etok, count++;
251 else
252 /* all finished, force abort */
253 p += strlen(p);
254 } else
255 /* found another one, no drive letter */
256 p = ++etok, count++;
257
258 if (count) {
259 count++; /* x1;x2;x3 <- need to count x3 */
260
261 /*
262 * Hazard a guess on how big the buffer needs to be.
263 * We have to convert things like c:/foo to /c=/foo.
264 */
265 nutc_path_len = strlen(path) + (count*2) + 1;
266 nutc_path = xmalloc(nutc_path_len);
267 pathp = nutc_path;
268 *pathp = '\0';
269
270 /*
271 * Loop through PATH and convert one elemnt of the path at at
272 * a time. Single file pathnames will fail this and fall
273 * to the logic below loop.
274 */
275 for (p = path, etok = strpbrk(p, ":;");
276 etok;
277 etok = strpbrk(p, ":;")) {
278
279 /* don't trip up on device specifiers or empty path slots */
280 if ((etok - p) == 1)
281 if (*(etok - 1) == ';' ||
282 *(etok - 1) == ':') {
283 p = ++etok;
284 continue;
285 } else if ((etok = strpbrk(etok+1, ":;")) == NULL)
286 break; /* thing found was a WINDOWS32 pathname */
287
288 /* save separator */
289 sep = *etok;
290
291 /* terminate the current path element -- temporarily */
292 *etok = '\0';
293
294#ifdef __NUTC__
295 /* convert to NutC format */
296 if (_NutPathToNutc(p, pathp, 0) == FALSE) {
297 free(nutc_path);
298 rval = savestring(path, strlen(path));
299 return rval;
300 }
301#else
302 *pathp++ = '/';
303 *pathp++ = p[0];
304 *pathp++ = '=';
305 *pathp++ = '/';
306 strcpy(pathp, &p[2]);
307#endif
308
309 pathp += strlen(pathp);
310 *pathp++ = ':'; /* use Unix style path separtor for new path */
311 *pathp = '\0'; /* make sure we are null terminaed */
312
313 /* restore path separator */
314 *etok = sep;
315
316 /* point p to first char of next path element */
317 p = ++etok;
318
319 }
320 } else {
321 nutc_path_len = strlen(path) + 3;
322 nutc_path = xmalloc(nutc_path_len);
323 pathp = nutc_path;
324 *pathp = '\0';
325 p = path;
326 }
327
328 /*
329 * OK, here we handle the last element in PATH (e.g. c of a;b;c)
330 * or the path was a single filename and will be converted
331 * here. Note, testing p here assures that we don't trip up
332 * on paths like a;b; which have trailing delimiter followed by
333 * nothing.
334 */
335 if (*p != '\0') {
336#ifdef __NUTC__
337 if (_NutPathToNutc(p, pathp, 0) == FALSE) {
338 free(nutc_path);
339 rval = savestring(path, strlen(path));
340 return rval;
341 }
342#else
343 *pathp++ = '/';
344 *pathp++ = p[0];
345 *pathp++ = '=';
346 *pathp++ = '/';
347 strcpy(pathp, &p[2]);
348#endif
349 } else
350 *(pathp-1) = '\0'; /* we're already done, don't leave trailing : */
351
352 rval = savestring(nutc_path, strlen(nutc_path));
353 free(nutc_path);
354 return rval;
355}
356
357#endif
Note: See TracBrowser for help on using the repository browser.