tags:

views:

1105

answers:

5

Hi, I need help doing the following:

a preprocessor macro label(x) shall output "#x", e.g.,

#define label(x) ...

if I call label(aname), the output shall be "#aname"

I know, that the following tries were errors.

#define label(x) #x   // leads to "x"
#define label(x) \#x  // is \"x"
#define label(x) "#x" // is "#x" (but not the content of x") "#otto"

It may exist a kind of escaped # (pound), but I don't know, how to escape...

Edit: I run "gcc -E test -o test.html" to get the output. The point is: How do I print out a hash mark (#) with a makro only using preprocessor's capabilities?

+1  A: 

Try:

#define label(x) "#"x
Neil
only ok if used as char* in c
tuergeist
+3  A: 

String literals in C will be concatenated, so you can do

#define label(x) "#" #x

I don't think it's possible without string concatenation (ie without invoking the C compiler as you want to do):

You can do some fancy stuff with additional levels of indirection and I even got the preprocessor to generate the desired output via

#define hash #
#define quote(x) #x
#define in_between(c, d) quote(c ## d)
#define join(c, d) in_between(c, d)
#define label(x) join(hash, x)
label(foo)

The problem is it will also generate an error message as in_between() expands to #foo, which is not an valid preprocessor token. I don't see any way around this.

My advise would be to choose the right tool for the job: switch to another macro language like m4 or even ML/I if you feel adventurous or use a scripting language like PHP or Perl. GPP seems nice as well and might be a better fit.

Christoph
leads to '"#" "string"' which is not '#string'may I ask how do you tested your answer?
tuergeist
In the C language, writing `char *c = "#" "string";` is identical to writing `char *c = "#string";` - the language concatenates string literals that are next to each other. Thus, this doesn't work with the preprocessor along, but does work with the C language.
Chris Lutz
As I wrote, I'll use the preprocessor's output, no additional c compiler will run.
tuergeist
@christoph: you were on the right way - see my answer
tuergeist
+3  A: 

I don't think you can, which is not wholly unreasonable since the output of the C preprocessor should not produce an unquoted '#' because that would indicate a pre-processor directive, and you cannot generate pre-processor directives on the fly like that.

In other words, the C preprocessor is a preprocessor for C (and C++) and not a completely general purpose tool.

Either use an alternative macro processor (m4 is the standard recommendation on Unix-like systems), or go about things differently.

For example, have the macro replacement:

#define label(x)    !@!x

Then post-process the output replacing '!@!' with '#'.

(The imake program uses a similar stunt; the C preprocessor does most of the work, but its output doesn't preserve line breaks needed by 'make', so 'imake' uses the notation '@@\' or thereabouts to indicate where line breaks need to be inserted after the C preprocessor has done its worst.)

Jonathan Leffler
Thank you for your suggestion...
tuergeist
+4  A: 

You can do something like this:

#define f(x) x
#define label(a) f(#)a

I tested this by running it directly through cpp (the C preprocessor) instead of through gcc. Example:

cpp test > test.html

Using the cpp that is part of gcc version 4.0.1.

The only problem I noticed is that I get some extra unwanted output, namely the first 4 lines of the file are as follows:

# 1 "test"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "test"
Whisty
2:16: error: '#' is not followed by a macro parameter
tuergeist
@tuergeist - I actually tested it a little differently than you. See my updated post.
Whisty
these first line are ok and can be ignored.
tuergeist
@wintermute: my gcc 4.3.3 brought the error I posted earlier :| But it worked with the definition of hash
tuergeist
+5  A: 

The answer is:

#define hash #
#define f(x) x
#define label(a) f(hash)a

then

label(foobar)

creates

#foobar

I found it with the help of all of you, but especially wintermute. Thanks a lot!

(Using gcc 4.3.3)

tuergeist
but that's no answer to your question: you asked for the quoted expression `"#foobar"`
Christoph
Is this well-defined, or a function of the specific preprocessor implementation tuergeist is using?
bdonlan
I just want to say that, someday soon, you may find yourself coming back here and asking another question about how to get the C preprocessor to do X or Y. I hope you'll remember what I said about this being an uphill battle, and that you strongly consider my recommendation to find a new tool for this job.
Chris Lutz
@christoph: I only used the quotes to make clear whats the output, sorry
tuergeist
@Chris: I won't come back to ask preprocessor questions. I swear it.I had to use stuff from other people :( Those people thought that it was a good idea to use the preprocessor and I was not allowed to change to another tool. I really appreciate your answer.
tuergeist
@tuergeist: well, that makes things easier ;) I'd suggest using backticks to mark the output as code instead of double quotes - that would have prevented my misunderstanding
Christoph
@tuergeist - Ah, the classic "maintaining someone else's clever hack" conundrum. I apologize on behalf of whoever had the "brilliant" idea to generate HTML with the C preprocessor.
Chris Lutz
@Christoph: +1, I'll keep that in mind.
tuergeist
@ALL: I'll upvote all answer you supported this question.. Thank you and good night.
tuergeist