1 /* Path conversion for Windows pathnames.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2006 Free Software Foundation, Inc.
4 This file is part of GNU Make.
5 
6 GNU Make is free software; you can redistribute it and/or modify it under the
7 terms of the GNU General Public License as published by the Free Software
8 Foundation; either version 2, or (at your option) any later version.
9 
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along with
15 GNU Make; see the file COPYING.  If not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
17 
18 #include <string.h>
19 #include <stdlib.h>
20 #include "make.h"
21 #include "pathstuff.h"
22 
23 /*
24  * Convert delimiter separated vpath to Canonical format.
25  */
26 char *
convert_vpath_to_windows32(char * Path,char to_delim)27 convert_vpath_to_windows32(char *Path, char to_delim)
28 {
29     char *etok;            /* token separator for old Path */
30 
31 	/*
32 	 * Convert all spaces to delimiters. Note that pathnames which
33 	 * contain blanks get trounced here. Use 8.3 format as a workaround.
34 	 */
35 	for (etok = Path; etok && *etok; etok++)
36 		if (isblank ((unsigned char) *etok))
37 			*etok = to_delim;
38 
39 	return (convert_Path_to_windows32(Path, to_delim));
40 }
41 
42 /*
43  * Convert delimiter separated path to Canonical format.
44  */
45 char *
convert_Path_to_windows32(char * Path,char to_delim)46 convert_Path_to_windows32(char *Path, char to_delim)
47 {
48     char *etok;            /* token separator for old Path */
49     char *p;            /* points to element of old Path */
50 
51     /* is this a multi-element Path ? */
52     for (p = Path, etok = strpbrk(p, ":;");
53          etok;
54          etok = strpbrk(p, ":;"))
55         if ((etok - p) == 1) {
56             if (*(etok - 1) == ';' ||
57                 *(etok - 1) == ':') {
58                 etok[-1] = to_delim;
59                 etok[0] = to_delim;
60                 p = ++etok;
61                 continue;    /* ignore empty bucket */
62             } else if (!isalpha ((unsigned char) *p)) {
63                 /* found one to count, handle things like '.' */
64                 *etok = to_delim;
65                 p = ++etok;
66             } else if ((*etok == ':') && (etok = strpbrk(etok+1, ":;"))) {
67                 /* found one to count, handle drive letter */
68                 *etok = to_delim;
69                 p = ++etok;
70             } else
71                 /* all finished, force abort */
72                 p += strlen(p);
73         } else {
74             /* found another one, no drive letter */
75             *etok = to_delim;
76             p = ++etok;
77 	}
78 
79     return Path;
80 }
81 
82 /*
83  * Convert to forward slashes. Resolve to full pathname optionally
84  */
85 char *
w32ify(char * filename,int resolve)86 w32ify(char *filename, int resolve)
87 {
88     static char w32_path[FILENAME_MAX];
89     char *p;
90 
91     if (resolve)
92         _fullpath(w32_path, filename, sizeof (w32_path));
93     else
94         strncpy(w32_path, filename, sizeof (w32_path));
95 
96     for (p = w32_path; p && *p; p++)
97         if (*p == '\\')
98             *p = '/';
99 
100     return w32_path;
101 }
102 
103 char *
getcwd_fs(char * buf,int len)104 getcwd_fs(char* buf, int len)
105 {
106 	char *p = getcwd(buf, len);
107 
108 	if (p) {
109 		char *q = w32ify(buf, 0);
110 		strncpy(buf, q, len);
111 	}
112 
113 	return p;
114 }
115 
116 #ifdef unused
117 /*
118  * Convert delimiter separated pathnames (e.g. PATH) or single file pathname
119  * (e.g. c:/foo, c:\bar) to NutC format. If we are handed a string that
120  * _NutPathToNutc() fails to convert, just return the path we were handed
121  * and assume the caller will know what to do with it (It was probably
122  * a mistake to try and convert it anyway due to some of the bizarre things
123  * that might look like pathnames in makefiles).
124  */
125 char *
convert_path_to_nutc(char * path)126 convert_path_to_nutc(char *path)
127 {
128     int  count;            /* count of path elements */
129     char *nutc_path;     /* new NutC path */
130     int  nutc_path_len;    /* length of buffer to allocate for new path */
131     char *pathp;        /* pointer to nutc_path used to build it */
132     char *etok;            /* token separator for old path */
133     char *p;            /* points to element of old path */
134     char sep;            /* what flavor of separator used in old path */
135     char *rval;
136 
137     /* is this a multi-element path ? */
138     for (p = path, etok = strpbrk(p, ":;"), count = 0;
139          etok;
140          etok = strpbrk(p, ":;"))
141         if ((etok - p) == 1) {
142             if (*(etok - 1) == ';' ||
143                 *(etok - 1) == ':') {
144                 p = ++etok;
145                 continue;    /* ignore empty bucket */
146             } else if (etok = strpbrk(etok+1, ":;"))
147                 /* found one to count, handle drive letter */
148                 p = ++etok, count++;
149             else
150                 /* all finished, force abort */
151                 p += strlen(p);
152         } else
153             /* found another one, no drive letter */
154             p = ++etok, count++;
155 
156     if (count) {
157         count++;    /* x1;x2;x3 <- need to count x3 */
158 
159         /*
160          * Hazard a guess on how big the buffer needs to be.
161          * We have to convert things like c:/foo to /c=/foo.
162          */
163         nutc_path_len = strlen(path) + (count*2) + 1;
164         nutc_path = xmalloc(nutc_path_len);
165         pathp = nutc_path;
166         *pathp = '\0';
167 
168         /*
169          * Loop through PATH and convert one elemnt of the path at at
170          * a time. Single file pathnames will fail this and fall
171          * to the logic below loop.
172          */
173         for (p = path, etok = strpbrk(p, ":;");
174              etok;
175              etok = strpbrk(p, ":;")) {
176 
177             /* don't trip up on device specifiers or empty path slots */
178             if ((etok - p) == 1)
179                 if (*(etok - 1) == ';' ||
180                     *(etok - 1) == ':') {
181                     p = ++etok;
182                     continue;
183                 } else if ((etok = strpbrk(etok+1, ":;")) == NULL)
184                     break;    /* thing found was a WINDOWS32 pathname */
185 
186             /* save separator */
187             sep = *etok;
188 
189             /* terminate the current path element -- temporarily */
190             *etok = '\0';
191 
192 #ifdef __NUTC__
193             /* convert to NutC format */
194             if (_NutPathToNutc(p, pathp, 0) == FALSE) {
195                 free(nutc_path);
196                 rval = savestring(path, strlen(path));
197                 return rval;
198             }
199 #else
200             *pathp++ = '/';
201             *pathp++ = p[0];
202             *pathp++ = '=';
203             *pathp++ = '/';
204             strcpy(pathp, &p[2]);
205 #endif
206 
207             pathp += strlen(pathp);
208             *pathp++ = ':';     /* use Unix style path separtor for new path */
209             *pathp   = '\0'; /* make sure we are null terminaed */
210 
211             /* restore path separator */
212             *etok = sep;
213 
214             /* point p to first char of next path element */
215             p = ++etok;
216 
217         }
218     } else {
219         nutc_path_len = strlen(path) + 3;
220         nutc_path = xmalloc(nutc_path_len);
221         pathp = nutc_path;
222         *pathp = '\0';
223         p = path;
224     }
225 
226     /*
227       * OK, here we handle the last element in PATH (e.g. c of a;b;c)
228      * or the path was a single filename and will be converted
229      * here. Note, testing p here assures that we don't trip up
230      * on paths like a;b; which have trailing delimiter followed by
231      * nothing.
232      */
233     if (*p != '\0') {
234 #ifdef __NUTC__
235         if (_NutPathToNutc(p, pathp, 0) == FALSE) {
236             free(nutc_path);
237             rval = savestring(path, strlen(path));
238             return rval;
239         }
240 #else
241         *pathp++ = '/';
242         *pathp++ = p[0];
243         *pathp++ = '=';
244         *pathp++ = '/';
245         strcpy(pathp, &p[2]);
246 #endif
247     } else
248         *(pathp-1) = '\0'; /* we're already done, don't leave trailing : */
249 
250     rval = savestring(nutc_path, strlen(nutc_path));
251     free(nutc_path);
252     return rval;
253 }
254 
255 #endif
256