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