xref: /netbsd-src/external/gpl2/gmake/dist/w32/pathstuff.c (revision 69606e3f5c9388e52aed8c120ad63c049ca45d8f)
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