Home | History | Annotate | Download | only in w32
      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 *
     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 *
     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 *
     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 *
    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 *
    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