Stripping tokens in the C preprocessor

D

dov.levenglick

Hi,
I am looking for a way to strip tokens using the C preprocessor. I looked in the GNU documentation and found nothing that would help me.
Specifically, I would like to strip parenthesis "(" and ")". For example, if I would to feed the macro STRIP with "This string contains parenthesis right around here)"; I would like the output to be "This string contains parenthesis right around here".
Can anyone point me towards the proper documentation and/or a working example?

Thanks
 
E

Eric Sosman

Hi,
I am looking for a way to strip tokens using the C preprocessor. I looked in the GNU documentation and found nothing that would help me.
Specifically, I would like to strip parenthesis "(" and ")". For example, if I would to feed the macro STRIP with "This string contains parenthesis right around here)"; I would like the output to be "This string contains parenthesis right around here".
Can anyone point me towards the proper documentation and/or a working example?

If I understand your intent correctly, you're out of luck.
A quote-enclosed literal is a single preprocessing token as far
as the preprocessor is concerned, and there's no way to look
inside; tokens are indivisible. The preprocessor can suppress
tokens, duplicate them, splice them together, and rearrange
them, but it operates at the level of the token, not of the
token's interior parts.

What's your overall goal? Maybe there's a different approach.
 
D

dov.levenglick

If I understand your intent correctly, you're out of luck.

A quote-enclosed literal is a single preprocessing token as far

as the preprocessor is concerned, and there's no way to look

inside; tokens are indivisible. The preprocessor can suppress

tokens, duplicate them, splice them together, and rearrange

them, but it operates at the level of the token, not of the

token's interior parts.



What's your overall goal? Maybe there's a different approach.



--

Eric Sosman

(e-mail address removed)

Thanks,
I inherited an existing (and awkward) implementation where, in order to abstract the underlying implementation of printf; a macro was introduced:
#define PRINTF(message) os_printf message

For each OS, os_printf would be redeclared - 99% of the time as a plain old printf.

The ramification of this implementation is that in order to feed a regular printf, such as: printf ( const char * format, ... ); both format and __VA_ARGS__ would be fed as a single literal (if I understand you properly).

Now, I want to implement this differently without breaking backward compatibility. Towards this, I want to separate the format from the arguments.

Another option that came to mind would be to feed the message into sprintf; however that faces the same problem since I would have to call sprintf(buf, message); where message would be the mangled format/args tuple.

I hope that I am clear.
 
B

Ben Bacarisse

Thanks, I inherited an existing (and awkward) implementation where, in
order to abstract the underlying implementation of printf; a macro was
introduced: #define PRINTF(message) os_printf message

For each OS, os_printf would be redeclared - 99% of the time as a
plain old printf.

The ramification of this implementation is that in order to feed a
regular printf, such as: printf ( const char * format, ... ); both
format and __VA_ARGS__ would be fed as a single literal (if I
understand you properly).

Now, I want to implement this differently without breaking backward
compatibility. Towards this, I want to separate the format from the
arguments.

Ah. That's not what I got from your original post but no matter...
Is this the sort of thing you want to do:

#define PRINTF(m) PRINTF2 m
#define PRINTF2(...) fprintf(stderr, __VA_ARGS__)

so that an old invocation like: PRINTF(("x=%d\n", 42)); expands to
fprintf(stderr, "x=%d\n", 42); ?

If this is not along the right lines, you need to say exactly what "I
want to implement this differently" means.

<snip>
 
D

dov.levenglick

(e-mail address removed) writes:













Ah. That's not what I got from your original post but no matter...

Is this the sort of thing you want to do:



#define PRINTF(m) PRINTF2 m

#define PRINTF2(...) fprintf(stderr, __VA_ARGS__)



so that an old invocation like: PRINTF(("x=%d\n", 42)); expands to

fprintf(stderr, "x=%d\n", 42); ?



If this is not along the right lines, you need to say exactly what "I

want to implement this differently" means.



<snip>

My existing functions are as follows:

<file_os.h>
#define os_printf printf
<file.h>
#define PRINTF(msg) os_printf msg

<file.c>
PRINTF(("Var equals %d", var));

I am looking for a way, without changing the macro signature in file.h; to have PRINTF call in to a new function:
int global_printf(const char * fmt, ...);
 
E

Eric Sosman

My existing functions are as follows:

<file_os.h>
#define os_printf printf
<file.h>
#define PRINTF(msg) os_printf msg

<file.c>
PRINTF(("Var equals %d", var));

I am looking for a way, without changing the macro signature in file.h; to have PRINTF call in to a new function:
int global_printf(const char * fmt, ...);

What's wrong with changing <file_os.h> to say

#define os_printf global_printf

? Isn't that precisely why the os_printf macro was introduced
in the first place? What am I missing ?
 
B

Ben Bacarisse

(e-mail address removed) writes:

My existing functions are as follows:

<file_os.h>
#define os_printf printf
<file.h>
#define PRINTF(msg) os_printf msg

<file.c>
PRINTF(("Var equals %d", var));

I am looking for a way, without changing the macro signature in
file.h; to have PRINTF call in to a new function: int
global_printf(const char * fmt, ...);

From my reading of your original post, you seem to know how the above
works, so there must be some unstated reason why the obvious

#define os_printf global_printf

is not suitable.
 
D

dov.levenglick

<dov> writes:









From my reading of your original post, you seem to know how the above

works, so there must be some unstated reason why the obvious



#define os_printf global_printf



is not suitable.

I mistyped the API for global_printf - sorry.
I want to implement global_printf such that it can take a FILE* handle:
global_printf(FILE* file, const char * fmt, ...);
 
B

Ben Bacarisse

Can you do anything to avoid all these extra blanks lines? If not,
please switch back to Google's old interface which is less broken than
the new one.
I mistyped the API for global_printf - sorry.
I want to implement global_printf such that it can take a FILE* handle:
global_printf(FILE* file, const char * fmt, ...);

Now all I need to know is why the example I posted one reply previously
is not suitable. Sure, it used the name "PRINTF2" rather than
"os_printf" but the structure is not changed by using another name. To
recap, what's wrong with:

#define os_printf(...) global_printf(stderr, __VA_ARGS__)

?
 
D

dov.levenglick

Can you do anything to avoid all these extra blanks lines? If not,
please switch back to Google's old interface which is less broken than
the new one.






Now all I need to know is why the example I posted one reply previously
is not suitable. Sure, it used the name "PRINTF2" rather than
"os_printf" but the structure is not changed by using another name. To
recap, what's wrong with:

#define os_printf(...) global_printf(stderr, __VA_ARGS__)

Existing API:
#define PRINTF printf
#define LOG(logpoint, severity, msg) PRINTF msg

LOG(WARN, ("this is a warning, this is a var %d\n", var) );

I want to convert LOG to somehow call into a function:
int new_printf(int logpoint, int severity, const char* fmt, ...)
{
va_list ap;

va_start(ap,fmt);
os_printf("Logpoint %d, severity %d reporting this: ", logpoint, severity);
os_printf(fmp, ap);
va_end(ap);
}

I tried changing
#define LOG(logpoint, severity, ...) new_printf(logpoint, severity, __VA_ARGS__)

However, I am getting the following warning from the compiler:
'function' : 'const char *' differs in levels of indirection from 'unsigned long'

The reason is because ("this is a warning, this is a var %d\n", var) is being parsed as an unsigned long rather than the {format, args} tuple.
 
B

Ben Bacarisse

Existing API:
#define PRINTF printf
#define LOG(logpoint, severity, msg) PRINTF msg

LOG(WARN, ("this is a warning, this is a var %d\n", var) );

Slowly we are getting closer and closer to the problem that needs to be
solved! We're not quite there yet, because the above is obviously not
the existing API, but I think the typo is obvious. You presumably meant

LOG(XXX, WARN, ("this is a warning, this is a var %d\n", var) );
I want to convert LOG to somehow call into a function:
int new_printf(int logpoint, int severity, const char* fmt, ...)
{
}

I tried changing
#define LOG(logpoint, severity, ...) new_printf(logpoint, severity,
__VA_ARGS__)

#define LOG(lp, s, args) new_printf(lp, s, X args)
#define X(fmt, ...) fmt, __VA_ARGS__

Pick better names, but you get the idea.

<snip>
 
J

Jens Gustedt

Am 05.08.2012 16:43, schrieb (e-mail address removed):
I tried changing
#define LOG(logpoint, severity, ...) new_printf(logpoint, severity, __VA_ARGS__)


you have to keep the interface of LOG as it was before, receiving three
arguments.

just do

#define EAT_PAREN(...) __VA_ARGS__
#define LOG_(logpoint, severity, ...) new_printf(logpoint, severity,
__VA_ARGS__)
#define LOG(logpoint, severity, msg) new_printf(logpoint, severity,
EAT_PAREN msg)

Jens
 
D

dov.levenglick

you have to keep the interface of LOG as it was before, receiving three
arguments.



just do



#define EAT_PAREN(...) __VA_ARGS__

#define LOG_(logpoint, severity, ...) new_printf(logpoint, severity,
__VA_ARGS__)

#define LOG(logpoint, severity, msg) new_printf(logpoint, severity,
EAT_PAREN msg)



Jens


Hi all,
Thank you all for assisting. The EAT_PAREN macro seems to be doing the trick.

I am extremely sorry for having dragged out the discussion instead of spelling out the exact problematic API - I thought that stating it as a general problem would be more beneficial to other in the forum, but I was wrong.

Dov
 

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,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top