preprocessor stringify and #include

P

pete

I've read the FAQ (although if this /is/ a FAQ, please point me at it)
and I've read quite a few promising posts in this group. But I am not
able to do what I want. Which is:

I have some very long pathnames to prepend to #included file names.
These long pathnames might change every week or two, so of course I'd
like to #define in just one place.

I've tried many ## and # things, but none seem to work for me when I
use them in #includes. I want to do this:

#define PATH Str(/longish/path/name/)
#include PATH "snmp.h"

which I am asking the preprocessor to resolve to:

#include "/longish/path/name/snmp.h"

As I say, I've tried a few things and many of them work; butin the
#include case, the preprocessor resolves my #include args to the empty
string.

How can I accomplish string cat as I wish?

Thanks!

-- Pete
 
B

Ben Pfaff

pete said:
I have some very long pathnames to prepend to #included file names.
These long pathnames might change every week or two, so of course I'd
like to #define in just one place.

Wouldn't it be easier to pass a different header file search path
to your implementation than to change the source file?
 
P

pete

Wouldn't it be easier to pass a different header file search path
to your implementation than to change the source file?

Ben, I"ve seen your posts in this group for a long time so your idea
must be right. But I'm sorry to say that I don't quite see what you
mean by "pass a different header file search path to your
implementation." This being a compile-time operation, some sources /
must/ change, right? Can you explain a little more? Thanks.

-- Pete
 
N

Nate Eldredge

pete said:
Ben, I"ve seen your posts in this group for a long time so your idea
must be right. But I'm sorry to say that I don't quite see what you
mean by "pass a different header file search path to your
implementation." This being a compile-time operation, some sources /
must/ change, right? Can you explain a little more? Thanks.

You don't change the source, you change the compilation options.

On Unix, this is typically done with the -I option to the compiler. You
would put

#include "snmp.h"

in your source file, and then do

gcc -I /longish/path/name foo.c
 
N

Nate Eldredge

pete said:
I've read the FAQ (although if this /is/ a FAQ, please point me at it)
and I've read quite a few promising posts in this group. But I am not
able to do what I want. Which is:

I have some very long pathnames to prepend to #included file names.
These long pathnames might change every week or two, so of course I'd
like to #define in just one place.

I've tried many ## and # things, but none seem to work for me when I
use them in #includes. I want to do this:

#define PATH Str(/longish/path/name/)
#include PATH "snmp.h"

which I am asking the preprocessor to resolve to:

#include "/longish/path/name/snmp.h"

This can't work in standard C. #includes are processed in translation
phase 4, while concatenation of string literals is translation phase 6.
 
P

pete

You don't change the source, you change the compilation options.

On Unix, this is typically done with the -I option to the compiler.
You would put
#include "snmp.h"
in your source file, and then do
gcc -I /longish/path/name foo.c

I should have explained right off that the C compiler that comes with
this rvoltin' development system does not correctly (if at all) honor -
I. Which is the problem I'm trying to get around with all this crazy
substitution stuff.
This can't work in standard C.  #includes are processed in translation
phase 4, while concatenation of string literals is translation phase 6.

GREAT! Thanks so much for that answer, one that'll save me lots of
time and head/wall damage.

-- Pete
 
P

pete

pete wrote:

[...]


I have some very long pathnames to prepend to #included file names.
These long pathnames might change every week or two, so of course I'd
like to #define in just one place.
I've tried many ## and # things, but none seem to work for me when I
use them in #includes. I want to do this:
  #define PATH Str(/longish/path/name/)
  #include PATH "snmp.h"
which I am asking the preprocessor to resolve to:
  #include "/longish/path/name/snmp.h"
As I say, I've tried a few things and many of them work; butin the
#include case, the preprocessor resolves my #include args to the empty
string.
How can I accomplish string cat as I wish?

I had a similar question many months ago, where I wanted to replace:

     #if THIS
     #include <configs/this.h>
     #elif THAT
     #include <configs/that.h>
     #elif ANOTHER
     #include <configs/another.h>
     ...

with a command line flag specifying the proper header.  I learned that you
can have:

     #include HEADERFILE

where "HEADERFILE" includes the "<" and >", as in:

     -DHEADERFILE="<configs/header.h>"

(I had tried, unsuccessfully, numerous combinations prior to asking here,
but none which included "<>" in the definition.)

If you are giving an absolute path, you can do this:

     #define PATH /longish/path/name
     ...
     #define SNMP_H <PATH/snmp.h>
     #include SNMP_H

I was unable to find a quick answer for header files that use quotes around
the name, rather than less-than/greater-than.

That works great! Thanks, Kenneth. Yes, I never thought of < > either.

-- Pete
 
H

Huibert Bol

pete said:
I've tried many ## and # things, but none seem to work for me when I
use them in #includes. I want to do this:

#define PATH Str(/longish/path/name/)
#include PATH "snmp.h"

which I am asking the preprocessor to resolve to:

#include "/longish/path/name/snmp.h"

As I say, I've tried a few things and many of them work; butin the
#include case, the preprocessor resolves my #include args to the empty
string.

How can I accomplish string cat as I wish?

The preprocessor can't do string cats, but perhaps something like this
will do:

#define STR(x) #x
#define PATH(x) STR(/longish/path/name/x)

#include PATH(snmp.h)
 
L

ld

pete wrote:

[...]




I have some very long pathnames to prepend to #included file names.
These long pathnames might change every week or two, so of course I'd
like to #define in just one place.
I've tried many ## and # things, but none seem to work for me when I
use them in #includes. I want to do this:
  #define PATH Str(/longish/path/name/)
  #include PATH "snmp.h"
which I am asking the preprocessor to resolve to:
  #include "/longish/path/name/snmp.h"
As I say, I've tried a few things and many of them work; butin the
#include case, the preprocessor resolves my #include args to the empty
string.
How can I accomplish string cat as I wish?

I had a similar question many months ago, where I wanted to replace:

     #if THIS
     #include <configs/this.h>
     #elif THAT
     #include <configs/that.h>
     #elif ANOTHER
     #include <configs/another.h>
     ...

with a command line flag specifying the proper header.  I learned that you
can have:

     #include HEADERFILE

where "HEADERFILE" includes the "<" and >", as in:

     -DHEADERFILE="<configs/header.h>"

(I had tried, unsuccessfully, numerous combinations prior to asking here,
but none which included "<>" in the definition.)

If you are giving an absolute path, you can do this:

     #define PATH /longish/path/name
     ...
     #define SNMP_H <PATH/snmp.h>
     #include SNMP_H

I was unable to find a quick answer for header files that use quotes around
the name, rather than less-than/greater-than.

what's wrong with:

#define HEADER(FILE) <PATH/FILE.h>
#define LOCAL_HEADER(FILE) MKSTR(PATH/FILE.h)
#define MKSTR(a) MKSTR_(a)
#define MKSTR_(a) #a

// -----

#define PATH /absolute/or/relative/path

#include HEADER(snmp)
#include LOCAL_HEADER(myfile)

I use something similar to select includes by arch names.

ld.
 
C

Chris M. Thomasson

pete said:
I've read the FAQ (although if this /is/ a FAQ, please point me at it)
and I've read quite a few promising posts in this group. But I am not
able to do what I want. Which is:

I have some very long pathnames to prepend to #included file names.
These long pathnames might change every week or two, so of course I'd
like to #define in just one place.

I've tried many ## and # things, but none seem to work for me when I
use them in #includes. I want to do this:

#define PATH Str(/longish/path/name/)
#include PATH "snmp.h"

which I am asking the preprocessor to resolve to:

#include "/longish/path/name/snmp.h"

As I say, I've tried a few things and many of them work; butin the
#include case, the preprocessor resolves my #include args to the empty
string.

How can I accomplish string cat as I wish?

______________________________________________________________
#define QUOTEX(t)#t
#define QUOTE(t)QUOTEX(t)


#define PLACEX(t)t
#define PLACE(t)PLACEX(t)


#define INCLUDE(path, file) \
QUOTE(PLACE(path)PLACE(file))


#define PATH include/


#include INCLUDE(PATH,test.h)
______________________________________________________________




Caveat... You will probablly have to take care wrt adding spaces anywhere in
the macro tokens. The above compiles fine for me... However, the following
makes GCC puke out an error:
______________________________________________________________
#define QUOTEX(t)#t
#define QUOTE(t)QUOTEX(t)


#define INCLUDE(path, file) \
QUOTE(path file)


#define PATH include/


#include INCLUDE(PATH,test.h)
______________________________________________________________




The error is:


include/ test.h: No such file or directory.





Take care because even the following gives the same error:
______________________________________________________________
#define QUOTEX(t)#t
#define QUOTE(t)QUOTEX(t)


#define PLACEX(t)t
#define PLACE(t)PLACEX(t)


#define INCLUDE(path, file) \
QUOTE(PLACE(path)PLACE(file))


#define PATH include/


#include INCLUDE(PATH, test.h)
______________________________________________________________



Yikes! ;^o
 
E

Eric Sosman

Huibert said:
The preprocessor can't do string cats, but perhaps something like this
will do:

#define STR(x) #x
#define PATH(x) STR(/longish/path/name/x)

#include PATH(snmp.h)

There are *three* kinds of things that can come
after #include: The <...> style, the "..." style, and
an arbitrary sequence of pp-tokens, subject to macro
replacement. The last holds some promise for the O.P.,
but alas! the way in which the pp-tokens combine to
produce one of the first two forms is implementation-
defined. Still, since it seems he's only concerned
about one implementation, it might be worth a look.

Another possibility (already mentioned, but I'll spell
it out because from the O.P.'s response he may not quite
have grokked the idea) is to gather the different variations
of the include'd files into their own directories, and to use
command-line options to tell the compiler where to search in
directory A for one compilation, directory B for another.
In this scenario the source just says "include foo.h", and
there are two versions of the file, A/foo.h and B/foo.h. To
compile it one way you use something like "cc -I inc/A ..."
and to compile it the other you use "cc -I inc/B ...".
Many Unixoid compilers use a "-I" flag to specify places to
search for #include files; the syntax for the O.P.'s compiler
may be different, but I don't think I've *ever* run across
a C compiler that didn't have *some* way of doing this.

If all else fails, the O.P. could populate directories
A/ and B/ as above, but instead of trying to get the compiler
to look there he could just copy all the A/*.h or B/*.h files
into the one place the compiler knows where to find things.
On Unixoid systems, the "copy" might actually just be pointing
a symbolic link at one or the other place.
 
P

pete

The preprocessor can't do string cats, but perhaps something like this
will do:

#define STR(x) #x
#define PATH(x) STR(/longish/path/name/x)

#include PATH(snmp.h)

This works perfectly, too! Thanks, Huibert.

-- Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top