[GRASS-dev] Windows-style Pathnames
Huidae Cho
grass4u at gmail.com
Wed Nov 1 16:52:11 EST 2006
On Wed, Nov 01, 2006 at 09:25:22PM +0000, Glynn Clements wrote:
>
> Paul Kelly wrote:
>
> > While experimenting with native Windows GRASS I was having loads of
> > problems getting anything to work at all because the GISDBASE path read
> > from the GISRC file was being corrupted in some strange way. Eventually
> > tracked it down to lots of MinGW-specific hacks in lib/gis/env.c. When I
> > removed them all everything (that I've tried so far: text-based startup
> > and quite a few different modules) worked fine. Really! I've included the
> > patch that removes them below at the bottom of this e-mail.
> >
> > It appears to contain lots of stuff about prepending and stripping the
> > hardcoded path to an Msys installation - what is that all about? Surely:
> > 1) GRASS may be installed other places than under the Msys root
> > 2) The correct solution is to pass the correct Windows-style path to
> > whichever functions need it, rather than hacking about with it in the GIS
> > library functions.
> > OK maybe I've missed something but it really doesn't make sense to me and
> > seems like (from what I can see) to be fixing the problem in the wrong
> > place?
>
> Quite possibly.
>
> > There's lots of other MinGW hacks and ifdefs all over the place that look
> > very dubious to me. An example is this one in lib/gis/parser.c:
> >
> > error = 0 ;
> > need_first_opt = 1 ;
> > i = strlen(pgm_name = argv[0]) ;
> > while (--i >= 0)
> > {
> > #ifdef __MINGW32__
> > if (pgm_name[i] == '/' || pgm_name[i] == '\\')
> > #else
> > if (pgm_name[i] == '/')
> > #endif
> > {
> > pgm_name += i+1;
> > break;
> > }
> > }
> >
> > It looks to me like pgm_name[i] is the first character in an array, so how
> > does it make sense to compare it to a two-character string?
>
> '\\' isn't a string, it's a character literal equal to 92 - the ASCII
> code for the backslash character (character literals support sequences
> such as '\n', so the backslash itself has to be preceded by a
> backslash).
>
> > And if it is
> > correct, why the #ifdef anyway? Why not do the logical or comparison on
> > all platforms?
>
> A backslash isn't a directory separator on Unix, it's a legal (albeit
> unlikely) character in filenames.
>
> > I think the aim should be to try and find a way of doing
> > things that works on all platforms, rather than putting in
> > platform-specific bits like this.
>
> For the above case, there should probably be a
> G_is_directory_separator() function which determines whether or not
> its argument is a directory separator on the host platform.
>
> There also needs to be a macro (e.g. DIRSEP) which expands to the
> preferred separator. While Windows accepts both / and \ in a lot of
> situations, there are some (notably command lines) where only \ works.
>
> > It is getting really annoying trying to
> > debug things when you're never quite sure what seems to be happening is
> > really happening, because there's a MinGW-specific hack in somewhere.
> > Especially when (OK I'm generalising here but only because it's getting
> > rather annoying!) that so many of the hacks seem to be rather bogus.
> >
> > Any opinions/justifications/flames?
>
> Windows isn't Unix. There will inevitably need to be some handling of
> platform-specific behaviour.
>
> However, it's far better to create a set of functions to handle such
> issues than to deal with individual files separately.
>
> > Index: env.c
>
> > -#ifdef __MINGW32__
> > - /* We need to prepend the MSYS base path (C:/msys/1.0) to any
> > - * internal path variables since these variables cannot be
> > - * auto-transformed to win32 path by the MSYS shell. */
> > - if (strcmp(name, "GISDBASE") == 0 && value[1] != ':')
> > - {
> > - char *p;
> > -
> > - sprintf(tmp, "%s", getenv("WD"));
> > - /* the default $WD = C:\msys\1.0\\bin\ */
> > - for(p=tmp+strlen(tmp); --p>=tmp && *p=='\\';);
> > - /* C:\msys\1.0\\bin */
> > - for(; --p>=tmp && *p!='\\';);
> > - /* C:\msys\1.0\\ */
> > - for(; --p>=tmp && *p=='\\';);
> > - /* C:\msys\1.0 */
> > - *(p+1) = 0;
> > - for(p=tmp; *p; p++)
> > - if(*p == '\\')
> > - *p = '/';
> > - /* now tmp is "C:/msys/1.0" and value is "/posix/path" */
> > - strcat(tmp, value);
> > - value = tmp;
> > - }
> > -#endif
>
> This is bogus, and should go.
>
> > if (*name && *value)
> > set_env (name, value, loc);
> > }
> > @@ -271,29 +243,7 @@
> > for (n = 0; n < count; n++)
> > if (env[n].name && env[n].value && env[n].loc == loc
> > && (sscanf (env[n].value,"%1s", dummy) == 1))
> > -#ifdef __MINGW32__
> > - /* Strip out the MSYS base path (C:/msys/1.0). */
> > - {
> > - char *value = env[n].value;
> > - char tmp[200];
> > -
> > - if (strcmp(env[n].name, "GISDBASE") == 0 && value[1] ==
> > ':')
> > - {
> > - char *p;
> > -
> > - sprintf(tmp, "%s", getenv("WD"));
> > - for(p=tmp+strlen(tmp); --p>=tmp && *p=='\\';);
> > - for(; --p>=tmp && *p!='\\';);
> > - for(; --p>=tmp && *p=='\\';);
> > - *(p+1) = 0;
> > - /* skip C:/msys/1.0 */
> > - value += p+1-tmp;
> > - }
> > - fprintf(fd,"%s: %s\n", env[n].name, value);
> > - }
> > -#else
>
> Ditto.
>
> > -#ifdef __MINGW32__
> > - sprintf ( buf, "%s\\%s\\VAR", G_location_path(), G_mapset() );
> > -#else
> > sprintf ( buf, "%s/%s/VAR", G_location_path(), G_mapset() );
> > -#endif
>
> This is arguably correct, although possbily better formulated as e.g.:
>
> sprintf ( buf, "%s" DIRSEP "%s" DIRSEP "VAR", G_location_path(), G_mapset() );
> or:
> sprintf ( buf, "%s%s%s%sVAR", G_location_path(), DIRSEP, G_mapset(), DIRSEP );
>
> rather than using a platform test.
>
> However, using / should work as an argument to fopen(). The issue is
> more significant if paths are constructed and stored for later use
> (e.g. in $GISRC). In that situation, we need to decide whether to:
>
> 1. create and store the pathname in the host's syntax, or
> 2. store it in Unix syntax and convert it as required.
The above code actually does #2 under the wrong assumption that GISDBASE
is in an MSys installation directory.
>
> Either option will involve a lot of changes. #1 is easier to
> implement, but will probably need to be done in more places (it needs
> to be done for every pathname which might need to be in host syntax at
> some point). #2 is harder, but only needs to be performed in places
> where host syntax is known to be necessary.
I found #2 a better choice becase MSys shell scripts will be happier
with posix path.
Huidae
>
> --
> Glynn Clements <glynn at gclements.plus.com>
>
> _______________________________________________
> grass-dev mailing list
> grass-dev at grass.itc.it
> http://grass.itc.it/mailman/listinfo/grass-dev
More information about the grass-dev
mailing list