Discussion:
Portable way to retrieve path separator
(too old to reply)
Matthias Hofmann
2005-09-06 16:07:39 UTC
Permalink
Hello everyone!

I wonder if there is a portable way to retrieve the platform-dependant path
separator. Windows uses '\' while Linux uses '/', and other platforms might
still use other characters. The standard says nothing about path separators,
and I found no information on the internet either.

If there is no way to tell the path separator, then can anyone please tell
me a portable way to make clients of my code aware of the problem? What I
have in mind is something like this:

#ifdef _WIN32
#define PATH_SEPARATOR "\\"
#else
#pragma message ( "Could not determine path separator." )
#endif

However, as far as I know the message pragma is not portable.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Victor Bazarov
2005-09-07 00:56:23 UTC
Permalink
Post by Matthias Hofmann
I wonder if there is a portable way to retrieve the platform-dependant path
separator. Windows uses '\' while Linux uses '/', and other platforms might
still use other characters. The standard says nothing about path separators,
and I found no information on the internet either.
The Standard says nothing because the system doesn't have to have any
"paths" and hence nothing like "path separator" can be standardized.
Post by Matthias Hofmann
If there is no way to tell the path separator, then can anyone please tell
me a portable way to make clients of my code aware of the problem?
Tell them to supply it.
Post by Matthias Hofmann
What I
#ifdef _WIN32
#define PATH_SEPARATOR "\\"
#else
#pragma message ( "Could not determine path separator." )
#endif
However, as far as I know the message pragma is not portable.
Right, it's not.

V

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Matthias Hofmann
2005-09-07 17:21:32 UTC
Permalink
Post by Victor Bazarov
The Standard says nothing because the system doesn't have to have any
"paths" and hence nothing like "path separator" can be standardized.
The standard also uses locales to support internationalization, though the
system does not have to have formats for the display of date and time. All
that would be required is a function that returns a character, which would
be the implementation-dependent path separator.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Russell Hind
2005-09-07 00:57:36 UTC
Permalink
Post by Matthias Hofmann
Hello everyone!
I wonder if there is a portable way to retrieve the platform-dependant path
separator. Windows uses '\' while Linux uses '/', and other platforms might
still use other characters. The standard says nothing about path separators,
and I found no information on the internet either.
If there is no way to tell the path separator, then can anyone please tell
me a portable way to make clients of my code aware of the problem? What I
Have you looked at boost::filesystem library?
http://www.boost.org/libs/filesystem/doc/index.htm

Cheers

Russell

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Matthias Hofmann
2005-09-07 17:20:17 UTC
Permalink
Post by Russell Hind
Have you looked at boost::filesystem library?
http://www.boost.org/libs/filesystem/doc/index.htm
No, but this looks very interesting, thank you for this link. However, it
would be great if my code would not require separate libraries.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Ulrich Eckhardt
2005-09-07 01:05:21 UTC
Permalink
Post by Matthias Hofmann
#ifdef _WIN32
#define PATH_SEPARATOR "\\"
#else
#pragma message ( "Could not determine path separator." )
#endif
#if defined(WIN32) || defined(_WIN32)
# define PATH_SEPARATOR "\\"
#else
# error "Could not determine path separator."
#endif

Uli
--
Questions ?
see C++-FAQ Lite: http://parashift.com/c++-faq-lite/ first !


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Matthias Hofmann
2005-09-07 17:21:07 UTC
Permalink
Post by Ulrich Eckhardt
Post by Matthias Hofmann
#ifdef _WIN32
#define PATH_SEPARATOR "\\"
#else
#pragma message ( "Could not determine path separator." )
#endif
#if defined(WIN32) || defined(_WIN32)
# define PATH_SEPARATOR "\\"
#else
# error "Could not determine path separator."
#endif
Thank you, that looks promising. Is there a list of macros for other
systems, like Linux or Mac?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Bjorn Reese
2005-09-07 19:09:29 UTC
Permalink
Post by Matthias Hofmann
Thank you, that looks promising. Is there a list of macros for other
systems, like Linux or Mac?
http://predef.sourceforge.net/
--
mail1dotstofanetdotdk

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
kanze
2005-09-08 13:46:19 UTC
Permalink
Post by Bjorn Reese
Post by Matthias Hofmann
Thank you, that looks promising. Is there a list of macros
for other systems, like Linux or Mac?
http://predef.sourceforge.net/
Note that some of this information doesn't hold for all
compiler options. In fact, a lot of it doesn't hold as soon as
you specify that you want a standards conformant compiler. (I
know that some of my code needs the standards conformant options
to compile, precisely because of a name conflict with one of the
predefined macros.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Bjorn Reese
2005-09-09 15:22:28 UTC
Permalink
Post by kanze
Note that some of this information doesn't hold for all
compiler options. In fact, a lot of it doesn't hold as soon as
you specify that you want a standards conformant compiler. (I
know that some of my code needs the standards conformant options
to compile, precisely because of a name conflict with one of the
predefined macros.)
If you have more specific information, I would be happy to add it.
--
mail1dotstofanetdotdk

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
kanze
2005-09-12 09:32:22 UTC
Permalink
Post by Bjorn Reese
Post by kanze
Note that some of this information doesn't hold for all
compiler options. In fact, a lot of it doesn't hold as soon
as you specify that you want a standards conformant
compiler. (I know that some of my code needs the standards
conformant options to compile, precisely because of a name
conflict with one of the predefined macros.)
If you have more specific information, I would be happy to add
it.
Well, the only case I know for sure is the one I actually
encountered. On my Linux machine, some of my include files are
in a directory named linux, and the include directive, after
expansion of all relevant macros, was something like "#include
"i80x86/linux/gcc/xxx.hh". Except that in fact, the path was
being expanded to "i80x86/1/gcc/xxx.hh", because linux was a
predefined macro. Specifying that I wanted strict standard
conformance ("-std=something", if I recall correctly) was
necessary for the code to work.

More to the point, many of the predefined macros are in the user
namespace, and cannot legally be defined by a compliant
compiler. Presumably (hopefully), specifying the options
necessary for full compliance will suppress these definitions.

Note that there are usually alternatives available. Thus, while
insisting on full compliance for g++ under Linux suppresses the
predefined macro linux, you can still test for __linux. (I
suppose. I didn't check it, because of course, I don't use
conditional compilation.)

As far as your site is concerned, I think a simple mention of
the issue in the introduction, with a recommendation to use the
standard conforming macros (those with either a double
underscore, or starting with an underscore followed by a capital
letter) where ever possible, would be largely sufficient. In
the end, anyone doing anything but the most simple things has to
revert to the compiler documentation anyway -- think of the
different options under Sun CC/Solaris which control the
threading model, for example, all of which affect in some way
some predefined macros (or require -D options defining specific
macros).

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Matthias Hofmann
2005-09-09 15:23:11 UTC
Permalink
Post by kanze
Post by Bjorn Reese
Post by Matthias Hofmann
Thank you, that looks promising. Is there a list of macros
for other systems, like Linux or Mac?
http://predef.sourceforge.net/
Note that some of this information doesn't hold for all
compiler options. In fact, a lot of it doesn't hold as soon as
you specify that you want a standards conformant compiler. (I
know that some of my code needs the standards conformant options
to compile, precisely because of a name conflict with one of the
predefined macros.)
You mean that some of the macros in the list from sourceforge.net might be
in use by a compiler?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
kanze
2005-09-12 09:30:41 UTC
Permalink
Post by Matthias Hofmann
Post by kanze
Post by Bjorn Reese
Post by Matthias Hofmann
Thank you, that looks promising. Is there a list of
macros for other systems, like Linux or Mac?
http://predef.sourceforge.net/
Note that some of this information doesn't hold for all
compiler options. In fact, a lot of it doesn't hold as soon
as you specify that you want a standards conformant
compiler. (I know that some of my code needs the standards
conformant options to compile, precisely because of a name
conflict with one of the predefined macros.)
You mean that some of the macros in the list from
sourceforge.net might be in use by a compiler?
Many of the macros cannot legally be in use in a conforming
compiler.

My only experience with this is with g++, under Linux -- I
happened to have a user defined symbol (actually, the name of a
directory) with the name "linux" (which is documented at this
site as being pre-defined); the compiler ended up generating
filenames like "i80x86/1/gcc/xxx.hh", rather than
"i80x86/linux/gcc/xxx.hh". Specifying that I wanted standard
conformance from the compiler was all that was necessary for the
code to work.

Frankly, I find this whole business of using ad hoc pre-defined
macros to specify OS etc. a bit idiotic. In the end, you will
need different options to invoke the compiler depending on the
system, the compiler and who knows what all else. Given that,
there's absolutely no problem in defining whatever you want on
the compile line, using -D or /D options. Or putting whatever
is system dependant in separate files (which you should be doing
anyway) in a separate directory, and using -I (or /I) to pick up
the right one.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Matthias Hofmann
2005-09-12 14:47:12 UTC
Permalink
Post by kanze
Frankly, I find this whole business of using ad hoc pre-defined
macros to specify OS etc. a bit idiotic. In the end, you will
need different options to invoke the compiler depending on the
system, the compiler and who knows what all else.
I agree. Besides, there is no guarantee that these predefined macros will
ever work, even when they are not intruding the user namespace. For example,
there might be a compiler that defines _WIN32 without the author having
Microsoft or Windows in mind, causing the platform to be erroneously
detected as Microsoft Windows.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Carl Barron
2005-09-07 01:06:17 UTC
Permalink
Post by Matthias Hofmann
Hello everyone!
I wonder if there is a portable way to retrieve the platform-dependant path
separator. Windows uses '\' while Linux uses '/', and other platforms might
still use other characters. The standard says nothing about path separators,
and I found no information on the internet either.
If there is no way to tell the path separator, then can anyone please tell
me a portable way to make clients of my code aware of the problem? What I
#ifdef _WIN32
#define PATH_SEPARATOR "\\"
#else
#pragma message ( "Could not determine path separator." )
#endif
However, as far as I know the message pragma is not portable.
replace #pragma messsage with
#error Could not determine path separator

is easiest solution.
#error generates a complier error with the text after #error on the
same line.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Matthias Hofmann
2005-09-07 17:19:27 UTC
Permalink
Post by Carl Barron
Post by Matthias Hofmann
However, as far as I know the message pragma is not portable.
replace #pragma messsage with
#error Could not determine path separator
is easiest solution.
#error generates a complier error with the text after #error on the
same line.
Is #error a platform independent directive? It is not even listed in the
MSDN-Library, but maybe I simply oversaw it.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Carl Barron
2005-09-08 09:12:13 UTC
Permalink
Post by Matthias Hofmann
Post by Carl Barron
Post by Matthias Hofmann
However, as far as I know the message pragma is not portable.
replace #pragma messsage with
#error Could not determine path separator
is easiest solution.
#error generates a complier error with the text after #error on the
same line.
Is #error a platform independent directive? It is not even listed in the
MSDN-Library, but maybe I simply oversaw it.
its in the grammar specification of a pre processor directive. The
purpose is to create a compiler error. Appendix A, section A.14.
--
A

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Greg Herlihy
2005-09-07 09:58:50 UTC
Permalink
Post by Matthias Hofmann
Hello everyone!
I wonder if there is a portable way to retrieve the platform-dependant path
separator. Windows uses '\' while Linux uses '/', and other platforms might
still use other characters. The standard says nothing about path separators,
and I found no information on the internet either.
If there is no way to tell the path separator, then can anyone please tell
me a portable way to make clients of my code aware of the problem? What I
#ifdef _WIN32
#define PATH_SEPARATOR "\\"
#else
#pragma message ( "Could not determine path separator." )
#endif
However, as far as I know the message pragma is not portable.
Actually, Windows will accept the slash character in either direction
as a file system delimiter (see below). But the issue is not
necessarily OS-dependent since the delimiter could depend on the format
of the volume being accessed

The good news is that there there is a portable way to specify file
path names, just not one that C++ provides. As far as I know #include
directives are about the only place where file system paths would have
much bearing on a C++ program. But the C++ Standard leaves the
interpretation of an include directive open. It simply states that the
mapping between the the contents of the include directive and the local
file system is implementation-defined.

But as long as the C++ program can check the system APIs for POSIX
compliance at runtime, then the program can call POSIX routines with
POSIX compliant path names (which look like traditional UNIX paths).
Most of the popular OSes including Windows, Linux, and MacOS X do have
POSIX APIs for accessing their file systems; so a portable
implementation in C++ should be possible.

Greg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Matthias Hofmann
2005-09-07 17:14:51 UTC
Permalink
Post by Greg Herlihy
Most of the popular OSes including Windows, Linux, and MacOS X do have
POSIX APIs for accessing their file systems; so a portable
implementation in C++ should be possible.
What I actually want to do is take the __FILE__ predefined macro and cut off
the path in front of the filename, so that
"C:\MyDocuments\MyProject\main.cpp" turns into "main.cpp". In order to
achieve this, I usually write code like the following:

char* cutoff_path( char* p )
{
char* _p;

if ( ( _p = strrchr( p, '\\' ) ) != NULL )
p = _p + 1;

return p;
}

However, it seems to be a bad idea to hard code the backslash if you want to
be portable.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
BobR
2005-09-08 09:19:23 UTC
Permalink
Matthias Hofmann wrote in message
Post by Matthias Hofmann
What I actually want to do is take the __FILE__ predefined macro and cut off
the path in front of the filename, so that
"C:\MyDocuments\MyProject\main.cpp" turns into "main.cpp". In order to
char* cutoff_path( char* p ){
char* _p;
if ( ( _p = strrchr( p, '\\' ) ) != NULL ) p = _p + 1;
return p;
}
However, it seems to be a bad idea to hard code the backslash if you want to
be portable.
--
Matthias Hofmann
GOOD GRIEF!!! Why didn't you just say what you wanted to begin with!

#include <string> // C++
std::string Temp(__FILE__);
std::string FindChr("/\\");
// strip off path
std::string NameOnly = Temp.substr(Temp.find_last_of(FindChr)+1,
Temp.size());

char SepChar = Temp.at(Temp.find_first_of(FindChr));

--
Bob R
POVrookie


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Matthias Hofmann
2005-09-08 14:04:51 UTC
Permalink
Post by BobR
GOOD GRIEF!!! Why didn't you just say what you wanted to begin with!
I did not want to bother anyone with details... ;-)
Post by BobR
#include <string> // C++
std::string Temp(__FILE__);
std::string FindChr("/\\");
// strip off path
std::string NameOnly = Temp.substr(Temp.find_last_of(FindChr)+1,
Temp.size());
char SepChar = Temp.at(Temp.find_first_of(FindChr));
This code seems to assume that either a forward slash or a backslash is used
as the path sparator, so does this solve the original problem? There could
be file systems that use a different separator, and on some systems, a slash
might even be part of the filename.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Bo Persson
2005-09-09 15:18:35 UTC
Permalink
Post by Matthias Hofmann
Post by BobR
GOOD GRIEF!!! Why didn't you just say what you wanted to begin with!
I did not want to bother anyone with details... ;-)
Post by BobR
#include <string> // C++
std::string Temp(__FILE__);
std::string FindChr("/\\");
// strip off path
std::string NameOnly = Temp.substr(Temp.find_last_of(FindChr)+1,
Temp.size());
char SepChar = Temp.at(Temp.find_first_of(FindChr));
This code seems to assume that either a forward slash or a backslash is used
as the path sparator, so does this solve the original problem? There could
be file systems that use a different separator, and on some systems, a slash
might even be part of the filename.
There are also file systems without the concept of paths, much less a
path separator. The above code is a quick hack that works on a lot of
systems, but far from all. You can improve on it, but there is no
total solution.



Bo Persson



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
BobR
2005-09-09 15:21:45 UTC
Permalink
Matthias Hofmann wrote in message
Post by Matthias Hofmann
Post by BobR
#include <string> // C++
std::string Temp(__FILE__);
std::string FindChr("/\\");
// strip off path
std::string NameOnly = Temp.substr(Temp.find_last_of(FindChr)+1,
Temp.size());
char SepChar = Temp.at(Temp.find_first_of(FindChr));
This code seems to assume that either a forward slash or a backslash is used
as the path sparator, so does this solve the original problem? There could
be file systems that use a different separator, and on some systems, a slash
might even be part of the filename.
--
Matthias Hofmann
Well, that certainly blows Darwin's theory out of the water!

--
Bob R
POVrookie


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Walter Bright
2005-09-09 15:26:59 UTC
Permalink
Post by BobR
Matthias Hofmann wrote in message
Post by Matthias Hofmann
What I actually want to do is take the __FILE__ predefined macro and cut
off
Post by Matthias Hofmann
the path in front of the filename, so that
"C:\MyDocuments\MyProject\main.cpp" turns into "main.cpp".
[...]
Post by BobR
GOOD GRIEF!!! Why didn't you just say what you wanted to begin with!
#include <string> // C++
std::string Temp(__FILE__);
std::string FindChr("/\\");
// strip off path
std::string NameOnly = Temp.substr(Temp.find_last_of(FindChr)+1,
Temp.size());
char SepChar = Temp.at(Temp.find_first_of(FindChr));
That doesn't work for the following filename: "C:main.cpp". Here's what I've
been using for a very long time:

/* Macro to determine if char is a path or drive delimiter */
#if MSDOS || __OS2__ || __NT__ || _WIN32
#define ispathdelim(c) ((c) == '\\' || (c) == ':' || (c) == '/')
#else
#ifdef VMS
#define ispathdelim(c) ((c)==':' || (c)=='[' || (c)==']' )
#else
#ifdef MPW
#define ispathdelim(c) ((c) == ':')
#else
#define ispathdelim(c) ((c) == '/')
#endif /* MPW */
#endif /* VMS */
#endif

char * filespecname(const char *filespec)
{ register const char *p;

/* Start at end of string and back up till we find the beginning */
/* of the filename or a path. */
for (p = filespec + strlen(filespec);
p != filespec && !ispathdelim(*(p - 1));
p--
)
;
return (char *)p;
}

You can download this and a bunch of other handy filespec functions from
http://ftp.digitalmars.com/ctools.zip

-Walter
www.digitalmars.com C, C++, D compilers
"code of the nerds"



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
BobR
2005-09-10 00:45:27 UTC
Permalink
Walter Bright wrote in message ...
Post by Walter Bright
Post by BobR
Matthias Hofmann wrote in message
ref: convert "C:\MyDocuments\MyProject\main.cpp" to "main.cpp".
#include <string> // C++
std::string Temp(__FILE__);
std::string FindChr("/\\");
// strip off path
std::string NameOnly = Temp.substr(Temp.find_last_of(FindChr)+1,
Temp.size());
char SepChar = Temp.at(Temp.find_first_of(FindChr));
That doesn't work for the following filename: "C:main.cpp". Here's what I've
/* Macro to determine if char is a path or drive delimiter */
#if MSDOS || __OS2__ || __NT__ || _WIN32
#define ispathdelim(c) ((c) == '\\' || (c) == ':' || (c) == '/')
#else
[snip]
Post by Walter Bright
#endif
So, that could be?:

#include <string> // C++
#if MSDOS || __OS2__ || __NT__ || _WIN32
std::string FindChr("/\\:"); // colon added
#else
#ifdef VMS
std::string FindChr(":[]");
#else
#ifdef MPW
std::string FindChr(":");
#else
std::string FindChr("/");
#endif /* MPW */
#endif /* VMS */
#endif
// or: std::string FindChr("/\\:[]"); // anything disallowed in filename for
OSs.

std::string Temp("C:main.cpp");

// - strip off path -
std::string NameOnly =
Temp.substr(Temp.find_last_of(FindChr)+1,Temp.size());
// char SepChar = Temp.at(Temp.find_first_of(FindChr));
char SepChar = Temp.at(Temp.find_last_of(FindChr));
Post by Walter Bright
char* filespecname(const char *filespec)
{ register const char *p;
// ....[snip]....
Post by Walter Bright
return (char *)p;
?? Shouldn't that be (for C++)? [yeah, I know it's 'C' <G>]:
return const_cast<char*>(p);
Post by Walter Bright
}
-Walter
--
Bob R
POVrookie


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Walter Bright
2005-09-10 13:36:35 UTC
Permalink
I did write that piece of code in 1986. I didn't write a C++ compiler until
1987. <string> came along much, much later <g>.



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Torsten Robitzki
2005-09-13 00:20:22 UTC
Permalink
Walter Bright wrote:
<snup>>
Post by Walter Bright
That doesn't work for the following filename: "C:main.cpp". Here's what I've
/* Macro to determine if char is a path or drive delimiter */
#if MSDOS || __OS2__ || __NT__ || _WIN32
#define ispathdelim(c) ((c) == '\\' || (c) == ':' || (c) == '/')
#else
#ifdef VMS
#define ispathdelim(c) ((c)==':' || (c)=='[' || (c)==']' )
You should add '<' and '>' too, because that are valid path delimiters
under VMS too ;-)

regards
Torsten


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Yuri Khan
2005-09-12 14:52:49 UTC
Permalink
Post by Matthias Hofmann
What I actually want to do is take the __FILE__ predefined macro and cut off
the path in front of the filename, so that
"C:\MyDocuments\MyProject\main.cpp" turns into "main.cpp".
You have two problems here.

First, once your project becomes large enough to span several
directories and be developed by a team of programmers, there will be
two or more source files with the same name in different directories.
Then your runtime-trimmed filename will become ambiguous and therefore
less useful. In the extreme case where every file in the project is
named "main.cpp", it will become completely useless.

The second problem will surface as soon as you use a cross-compiler,
for example, to build a VMS binary while running on Linux. I would
expect that predefined macros would indicate the *target* platform and
thus any separator determined by these macros will also be the target
platform path separator; but I would equally expect the __FILE__ macro
to expand to a path formatted using *host* platform separators, because
that's where the source files are.

What you should want to do is take the __FILE__ name and trim the
project base path from it. Depending on the OSes you're using, it may
be as simple as this:

// : root.h
// must be in the base directory of the project
#ifndef ROOT_H
#define ROOT_H

#include <algorithm>

inline const char* trimSourceFilename(const char* filename)
{
static const char* rootFilename = __FILE__;
/*static?*/ const char* rootPathEnd = rootFilename +
strlen(rootFilename) - strlen("root.h");
return std::mismatch(rootFilename, rootPathEnd, filename).second;
}
// # root.h

// : some/subdirectory/main.cpp
#include "../../root.h"
// ...
std::cout << trimSourceFilename(__FILE__) << std::endl;
// # some/subdirectory/main.cpp

This assumes that the path's most general component is on the left and
will fail on a hypothetical system where file names look like email
addresses (***@MyProject.MyDocuments.C). But then again, your
original example had the same assumption.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
ThosRTanner
2005-09-07 10:08:06 UTC
Permalink
Post by Matthias Hofmann
Hello everyone!
I wonder if there is a portable way to retrieve the platform-dependant path
separator. Windows uses '\' while Linux uses '/', and other platforms might
still use other characters. The standard says nothing about path separators,
and I found no information on the internet either.
Acutally, windows32 will let you use / as a path separator, so as long
as you intend to use only windows or unix, you needn't worry.
Post by Matthias Hofmann
If there is no way to tell the path separator, then can anyone please tell
me a portable way to make clients of my code aware of the problem? What I
#ifdef _WIN32
#define PATH_SEPARATOR "\\"
#else
#pragma message ( "Could not determine path separator." )
#endif
However, as far as I know the message pragma is not portable.
To what precisely?


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Matthias Hofmann
2005-09-07 17:16:32 UTC
Permalink
Post by ThosRTanner
Post by Matthias Hofmann
However, as far as I know the message pragma is not portable.
To what precisely?
Actually to any platform that supports C++, although I mainly use Windows.
Nevertheless, I want to make my code available to other people as well, and
they might use systems of any kind.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Klomanager
http://www.anvil-soft.de - Die Macher des Klomanagers



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
kanze
2005-09-07 10:08:29 UTC
Permalink
Post by Matthias Hofmann
I wonder if there is a portable way to retrieve the
platform-dependant path separator. Windows uses '\' while
Linux uses '/', and other platforms might still use other
characters.
Windows uses both. If you're parsing pathnames, you have to
accept both '/' and '\' as path separators. If you're
displaying pathnames, '\' is preferred.
Post by Matthias Hofmann
The standard says nothing about path separators, and I found
no information on the internet either.
If there is no way to tell the path separator, then can anyone
please tell me a portable way to make clients of my code aware
#ifdef _WIN32
#define PATH_SEPARATOR "\\"
#else
#pragma message ( "Could not determine path separator." )
#endif
However, as far as I know the message pragma is not portable.
Never heard of it. And what happens when you have twenty
different systems, with twenty different attributes.

The usual solution is to create a system dependant include file
for each system, which contains all of this sort of
information. Things like:

static char const GB_optId = '-' ; // - under UNIX
static char const GB_altOptId = '+' ; // + under UNIX
static char const GB_asciiEsc = '\\' ; // \ under UNIX
static char const GB_preferredPathSep = '/' ; // / under UNIX
static char const GB_allowedPathSep[] = "/" ;
static bool const GB_ignoreCase = false ; // in filenames
only.
static char const GB_stdinName[] = "-" ;
static int const GB_exitSuccess = 0 ;
static int const GB_exitWarning = 1 ;
static int const GB_exitError = 2 ;
static int const GB_exitFatal = 3 ;
static int const GB_exitInternal = 4 ;

This version is for Unix based systems. For Windows,
GB_allowedPathSep becomes "/\\".

Put the version for each system in a separate directory, and use
-I to select at compile time. (Your compiler invocation is
pretty system dependant anyway, so adding a system dependant
option to it won't change much.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Loading...