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